JavaScript must be enabled to play.
Browser lacks capabilities required to play.
Upgrade or switch to another browser.
Loading…
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 40px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4); text-align: center; max-width: 600px;"> <h1 style="color: white; margin: 0 0 20px 0; font-size: 36px;">👋 Thank You for Playing</h1> <p style="color: white; margin: 0; font-size: 18px;"> That was supposed to kick you but if you still see this just close the game manually. </p> </div> <<script>> // Close the window/tab window.close(); // If window.close() doesn't work (blocked by browser), redirect to a blank page setTimeout(function() { window.location.href = "about:blank"; }, 1000); <</script>> <p style="color: #aaa; text-align: center; font-size: 14px; margin-top: 20px;"> If the window does not close automatically, you can safely close this tab. </p> </div> <</nobr>>
<<nobr>> <!-- Time and Date Display --> <<set _currentTime = getTimeOfDay()>> <<run checkWeatherUpdate()>> <div style="text-align: center; margin-bottom: 10px;"> <<if _currentTime === "morning">> <span style="font-size: 14px; font-weight: bold;">🌅 Morning</span> <<elseif _currentTime === "afternoon">> <span style="font-size: 14px; font-weight: bold;">☀️ Afternoon</span> <<elseif _currentTime === "evening">> <span style="font-size: 14px; font-weight: bold;">🌆 Evening</span> <<else>> <span style="font-size: 18px;">🌙 Night</span> <</if>> <br> <span style="font-size: 14px; font-weight: bold;">$dayOfWeek, Week $weekNumber</span> <br> <span style="font-size: 12px;"><<= getTimeString()>> - Day $dayNumber</span> <br> <<if $lastLocation === "Desert" || $lastLocation === "DesertExplore" || $lastLocation === "StoneTablet">><span style="font-size: 12px;">☀️ Clear</span><<else>><span style="font-size: 12px;"><<= getWeatherIcon($currentWeather)>> <<print $currentWeather || "Clear">></span><</if>> <span style="font-size: 12px; margin-left: 8px;"><<= setup.moon ? setup.moon.getIcon() : "">> <<= setup.moon ? setup.moon.getLabel() : "">></span> <<if $possessionActive>><br><span style="font-size: 11px; color: #c9a9ff; text-shadow: 0 0 8px rgba(201,169,255,0.6); animation: cuffPulseGlow 2.8s ease-in-out infinite;">🐟 Wearing the Sunfish Artifact</span><<if $skills && $skills.includes("Stealth") && $possessionBodyLocation>><br><<link "<span style='font-size: 11px; color: #ffd6ec; text-decoration: underline; cursor: pointer;'>🪟 Sneak to your old body</span>">><<goto "RoisinBreakInPlayerHome">><</link>><</if>><</if>> </div> <!-- Player Name --> <div style="text-align: center; margin-bottom: 10px;"> <<if $activeTransformation === "Cerberus" && $firstName !== undefined>> <div @style="'color: ' + setup.cerberusHeadColors.center + '; font-weight: bold; font-size: 18px; line-height: 1.2;'">$firstName</div> <div style="display: flex; justify-content: center; gap: 14px; margin-top: 2px;"> <span @style="'color: ' + setup.cerberusHeadColors.left + '; font-weight: bold; font-size: 14px;'"><<print ($cerberusHeadNames ? ($cerberusHeadNames.left || "?") : "?")>></span> <span @style="'color: ' + setup.cerberusHeadColors.right + '; font-weight: bold; font-size: 14px;'"><<print ($cerberusHeadNames ? ($cerberusHeadNames.right || "?") : "?")>></span> </div> <div style="color: #ccc; font-weight: bold; font-size: 16px; margin-top: 2px;">$lastName</div> <<elseif $firstName !== undefined && $lastName !== undefined>> <h2 style="color: #667eea; margin: 0;">$firstName $lastName</h2> <<else>> <h2 style="color: #667eea; margin: 0;">Water Bottle</h2> <</if>> </div> <<if $witchFormActive || $clairFormActive>> <div style="margin: 4px 0 10px 0; text-align: center;"> <div style="font-size: 11px; color: #CE93D8; margin-bottom: 3px;">Mana: <<print ($witchMana || 0) + " / " + ($witchManaMax || 100)>></div> <<set _manaPct = Math.max(0, Math.min(100, Math.round(100 * ($witchMana || 0) / ($witchManaMax || 100))))>> <div style="background: #1a1a2e; border-radius: 6px; height: 10px; overflow: hidden; border: 1px solid #7b1fa2; max-width: 160px; margin: 0 auto;"> <<= "<div style='background: linear-gradient(90deg, #7b1fa2, #e040fb); height: 100%; width: " + _manaPct + "%;'></div>">> </div> </div> <</if>> <!-- Character Portrait --> <div style="margin: 15px 0; text-align: center;"> <<if $appearance && $bodyParts>> <<set _faceImagePath = setup.getPlayerFaceImage()>> <<if _faceImagePath && _faceImagePath !== "">> <img @src="_faceImagePath" style="max-width: 100%; height: auto; border-radius: 10px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.2);" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"> <div style="width: 100%; height: 200px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; display: none; align-items: center; justify-content: center; color: white; font-style: italic; border: 3px solid #667eea;"> No Portrait </div> <<else>> <div style="width: 100%; height: 200px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: white; font-style: italic; border: 3px solid #667eea;"> No Portrait </div> <</if>> <<else>> <div style="width: 100%; height: 200px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 10px; display: flex; align-items: center; justify-content: center; color: white; font-style: italic; border: 3px solid #667eea;"> No Portrait </div> <</if>> </div> <!-- Stats Overview --> <div style="margin: 10px 0;"> <h3 style="margin: 5px 0; color: #667eea; font-size: 16px;">Stats</h3> <div style="font-size: 12px;"> <<set _totalStrength = setup.getTotalStat("strength")>> <<set _totalIntelligence = setup.getTotalStat("intelligence")>> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _totalDexterity = setup.getTotalStat("dexterity")>> <<set _strengthBonus = _totalStrength - $stats.strength>> <<set _intelligenceBonus = _totalIntelligence - $stats.intelligence>> <<set _charismaBonus = _totalCharisma - $stats.charisma>> <<set _dexterityBonus = _totalDexterity - $stats.dexterity>> <strong>Strength:</strong> $stats.strength<<if _strengthBonus > 0>> <span style="color: #51cf66;">(+<<print _strengthBonus>>)</span><<elseif _strengthBonus < 0>> <span style="color: #ff6b6b;">(<<print _strengthBonus>>)</span><</if>><br> <strong>Intelligence:</strong> $stats.intelligence<<if _intelligenceBonus > 0>> <span style="color: #51cf66;">(+<<print _intelligenceBonus>>)</span><<elseif _intelligenceBonus < 0>> <span style="color: #ff6b6b;">(<<print _intelligenceBonus>>)</span><</if>><br> <strong>Charisma:</strong> $stats.charisma<<if _charismaBonus > 0>> <span style="color: #51cf66;">(+<<print _charismaBonus>>)</span><<elseif _charismaBonus < 0>> <span style="color: #ff6b6b;">(<<print _charismaBonus>>)</span><</if>><br> <strong>Dexterity:</strong> $stats.dexterity<<if _dexterityBonus > 0>> <span style="color: #51cf66;">(+<<print _dexterityBonus>>)</span><<elseif _dexterityBonus < 0>> <span style="color: #ff6b6b;">(<<print _dexterityBonus>>)</span><</if>><br> </div> </div> <!-- Quick Info --> <div style="margin: 10px 0;"> <h3 style="margin: 5px 0; color: #667eea; font-size: 16px;">Info</h3> <div style="font-size: 12px;"> <strong>Gender:</strong> <<print $bodyParts.gender.toUpperFirst()>><br> <strong>Skin:</strong> <<print $appearance.skinTone.toUpperFirst()>><br> <strong>Age:</strong> $appearance.age<br> <<if $jobs && $jobs.length > 0>> <strong>Job:</strong> <<print $jobs[0]>> <<else>> <strong>Job:</strong> <span style="color: #e74c3c;">Unemployed</span> <</if>><br> <strong>Money:</strong> <<print setup.formatMoney($money)>> </div> </div> <</nobr>>
:: Widgets [widget nobr] /* --- Custom textbox widget for reliable name input --- */ <<widget "ctext">> <<set _varName = _args[0]>> <<set _defaultValue = State.getVar(_varName) || "">> <<textbox _varName _defaultValue>> <</widget>> /* --- Trait Selection Widget --- */ <<widget "traitSelection">> <<for _name, _desc range $availableTraits>> <<capture _name, _desc>> <div style="margin-bottom: 8px;"> ''<<= _name>>'' <<if $selectedTraits.includes(_name)>> <span style="color: green;">(SELECTED)</span> <<link "REMOVE">> <<set $selectedTraits.delete(_name)>> <<replace "#trait-selection-ui">><<traitSelection>><</replace>> <<replace "#continue-check-area">><<continueCheck>><</replace>> <</link>> <<else>> <<if $selectedTraits.length < $maxTraits>> <<link "SELECT">> <<set $selectedTraits.push(_name)>> <<replace "#trait-selection-ui">><<traitSelection>><</replace>> <<replace "#continue-check-area">><<continueCheck>><</replace>> <</link>> <<else>> <span style="color: gray;">(Max Reached)</span> <</if>> <</if>> <br> <span style="font-size: 90%; color: #888888;"><<= _desc>></span> </div> <</capture>> <</for>> <</widget>> /* --- Continue Check Widget --- */ <<widget "continueCheck">> <<set _disable = $firstName === "" || $lastName === "">> <<disable _disable>> <<link "Continue to Stats">> <<set $stats = clone($baseStats)>> <<if $selectedTraits.length > 0>> <<for _i to 0; _i < $selectedTraits.length; _i++>> <<if $selectedTraits[_i] === "Pensive">> <<set $stats.intelligence += 3>> <<elseif $selectedTraits[_i] === "Silver-Tongued">> <<set $stats.charisma += 3>> <<elseif $selectedTraits[_i] === "Swift">> <<set $stats.dexterity += 3>> <<elseif $selectedTraits[_i] === "Jock">> <<set $stats.strength += 3>> <<elseif $selectedTraits[_i] === "Naturally Gifted">> <<set $stats.charisma += 2>> <<set $stats.dexterity += 2>> <<set $stats.strength += 2>> <<set $stats.intelligence += 2>> <<elseif $selectedTraits[_i] === "Quick Learner">> /* No stat effect - skill learning bonus only */ <</if>> <</for>> <</if>> <<set $maxTraits = 300>> <<goto "StatMenu">> <</link>> <</disable>> <<if _disable>> <br> <span style="color: red;">Please complete your name to continue.</span> <</if>> <</widget>>
:: CodeLibrary [widget nobr] <<widget "traitSelection">> <<for _name, _desc range $availableTraits>> <<capture _name, _desc>> <div style="margin-bottom: 8px;"> ''<<= _name>>'' <<if $selectedTraits.includes(_name)>> <span style="color: green;">(SELECTED)</span> <<link "REMOVE">> <<set $selectedTraits.delete(_name)>> <<replace "#trait-selection-ui">><<traitSelection>><</replace>> <<replace "#continue-check-area">><<continueCheck>><</replace>> <</link>> <<else>> <<if $selectedTraits.length < $maxTraits>> <<link "SELECT">> <<set $selectedTraits.push(_name)>> <<replace "#trait-selection-ui">><<traitSelection>><</replace>> <<replace "#continue-check-area">><<continueCheck>><</replace>> <</link>> <<else>> <span style="color: gray;">(Max Reached)</span> <</if>> <</if>> <br> <span style="font-size: 90%; color: #888888;"><<= _desc>></span> </div> <</capture>> <</for>> <</widget>> <<widget "continueCheck">> <<set _disable = $firstName === "" || $lastName === "">> <<disable _disable>> <<link "Continue to Traits">> <<set $stats = clone($baseStats)>> <<if $selectedTraits.length > 0>> <<for _i to 0; _i < $selectedTraits.length; _i++>> <<if $selectedTraits[_i] === "Pensive">> <<set $stats.intelligence += 5>> <<elseif $selectedTraits[_i] === "Silver-Tongued">> <<set $stats.charisma += 5>> <<elseif $selectedTraits[_i] === "Jock">> <<set $stats.strength += 5>> <<set $stats.intelligence -= 1>> <<elseif $selectedTraits[_i] === "Naturally Gifted">> <<goto "GiftedStatChoice">> <<elseif $selectedTraits[_i] === "Quick Learner" || $selectedTraits[_i] === "Keen Observer">> /* No stat effect needed, continue normally */ <</if>> <</for>> <</if>> <<set $maxTraits = 100>> <<goto "StatMenu">> <</link>> <</disable>> <<if _disable>> <br> <span style="color: red;">Please complete your name to continue.</span> <</if>> <</widget>> :: Widgets [widget] /* --- Custom textbox widget for reliable name input --- */ <<widget "ctext">> <<set _varName = _args[0]>> <<set _defaultValue = State.getVar(_varName) || "">> <<textbox _varName _defaultValue>> <</widget>> <<widget "traitSelection">> <<for _name, _desc range $availableTraits>> <<capture _name, _desc>> <div style="margin-bottom: 8px;"> ''<<= _name>>'' <<if $selectedTraits.includes(_name)>> <span style="color: green;">(SELECTED)</span> <<link "REMOVE">> <<set $selectedTraits.delete(_name)>> <<replace "#trait-selection-ui">><<traitSelection>><</replace>> <<replace "#continue-check-area">><<continueCheck>><</replace>> <</link>> <<else>> <<if $selectedTraits.length < $maxTraits>> <<link "SELECT">> <<set $selectedTraits.push(_name)>> <<replace "#trait-selection-ui">><<traitSelection>><</replace>> <<replace "#continue-check-area">><<continueCheck>><</replace>> <</link>> <<else>> <span style="color: gray;">(Max Reached)</span> <</if>> <</if>> <br> <span style="font-size: 90%; color: #888888;"><<= _desc>></span> </div> <</capture>> <</for>> <</widget>> <<widget "continueCheck">> <<set _disable = $firstName === "" || $lastName === "">> <<disable _disable>> <<link "Continue to Traits">> <<set $stats = clone($baseStats)>> <<if $selectedTraits.length > 0>> <<for _i to 0; _i < $selectedTraits.length; _i++>> <<if $selectedTraits[_i] === "Pensive">> <<set $stats.intelligence += 5>> <<elseif $selectedTraits[_i] === "Silver-Tongued">> <<set $stats.charisma += 5>> <<elseif $selectedTraits[_i] === "Jock">> <<set $stats.strength += 5>> <<set $stats.intelligence -= 1>> <<elseif $selectedTraits[_i] === "Naturally Gifted">> <<goto "GiftedStatChoice">> <<elseif $selectedTraits[_i] === "Quick Learner" || $selectedTraits[_i] === "Keen Observer">> /* No stat effect needed, continue normally */ <</if>> <</for>> <</if>> <<set $maxTraits = 100>> <<goto "StatMenu">> <</link>> <</disable>> <<if _disable>> <br> <span style="color: red;">Please complete your name to continue.</span> <</if>> <</widget>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Alleyway")>> <<run $visitedLocations.push("Alleyway")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "Alleyway">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #666; text-align: center;">🌆 Dark Alleyway</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Alley.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Dark Alleyway"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #434343 0%, #000000 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #666;"> <p style="color: white; font-size: 18px; margin: 0;"> You find yourself in a dimly lit alleyway in Sunfish City. The city sprawls around you, full of possibilities and dangers. Neon signs flicker in the distance, and the sounds of urban life echo off the grimy walls. </p> <<if $homeless>> <p style="color: #ff6b6b; margin: 10px 0 0 0; font-style: italic;"> You are homeless. You need to find work, shelter, or a way to change your circumstances. </p> <</if>> </div> <h2 style="color: #666;">Where do you want to go?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<goto "BusStop">> <</link>> </div> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">The heart of the city, bustling with activity.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Corporate towers and professional opportunities.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Neon lit streets filled with nightlife and vice.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> <!-- Shady Shop --> <div style="border: 3px solid #ff4444; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff4444; margin: 0 0 10px 0;">🕶️ Shady Shop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">A suspicious storefront with unmarked goods.</p> <<link "<div style='background: #ff4444; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Shady Shop</div>">> <<goto "ShadyShop">> <</link>> </div> <!-- The Angler Bar --> <div style="border: 3px solid #d4a574; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #d4a574; margin: 0 0 10px 0;">🍺 The Angler</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">A dimly lit dive bar frequented by workers and shady characters.</p> <<link "<div style='background: #d4a574; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter The Angler</div>">> <<goto "TheAngler">> <</link>> </div> </div> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "Alleyway">> <<goto "CrimeHub">> <</link>> <</if>> </div> <!-- Black Market Dealer Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Black Market Dealer">> <div style="border: 3px solid #00c853; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #00c853; margin: 0 0 10px 0;">☠ Black Market Dealings</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Buy contraband from suppliers and sell at a markup. Requires cash upfront. Watch your heat level!</p> <<link "<div style='background: #00c853; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Dealing Session</div>">> <<goto "BlackMarketDealerWork">> <</link>> </div> <</if>> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Alleyway")>> <!-- Also gather all unemployed NPCs --> <<set _unemployedNPCs = []>> <<for _npc range $npcs>> <<set _isUnemployed = false>> <<if !_npc.jobs || _npc.jobs.length === 0>> <<set _isUnemployed = true>> <<elseif typeof _npc.jobs === "string" && _npc.jobs === "Unemployed">> <<set _isUnemployed = true>> <<elseif Array.isArray(_npc.jobs) && (_npc.jobs.length === 0 || (_npc.jobs.length === 1 && _npc.jobs[0] === "Unemployed"))>> <<set _isUnemployed = true>> <</if>> <<if _isUnemployed && (!_npc.location || _npc.location === "Alleyway")>> <<run _unemployedNPCs.push(_npc)>> <</if>> <</for>> <!-- Combine scheduled NPCs and unemployed NPCs, removing duplicates --> <<set _allNPCsHere = _npcsHere ? _npcsHere.slice() : []>> <<for _unemployed range _unemployedNPCs>> <<set _alreadyInList = false>> <<for _existing range _allNPCsHere>> <<if _existing.name === _unemployed.name>> <<set _alreadyInList = true>> <</if>> <</for>> <<if !_alreadyInList>> <<run _allNPCsHere.push(_unemployed)>> <</if>> <</for>> <h2 style="margin-top: 30px; color: #ff6b6b;">🌆 People Here</h2> <<if _allNPCsHere && _allNPCsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _allNPCsHere>> <<capture _npc>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"> <<if _npc.jobs && _npc.jobs.length > 0>> <<print _npc.jobs.join(", ")>> <<else>> Unemployed <</if>> </p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The alley is empty right now. Just shadows and silence. </p> </div> <</if>> <!-- Street Sleep Section --> <h2 style="margin-top: 30px; color: #666;">💤 Rest</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #666; margin: 0 0 10px 0;">😴 Sleep on the Street</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.6;"> You can try to catch some sleep curled up behind a pile of trash bags. The stench is overwhelming, and the cold concrete offers little comfort. Rats scurry nearby, and the sounds of the city never quite fade. It's far from ideal, but when you have nowhere else to go, sometimes this is all you can do. </p> <p style="color: #ff6b6b; font-size: 13px; margin: 0 0 15px 0; font-weight: bold; font-style: italic;"> ⚠️ Warning: This is a sketchy place to sleep. Bad things could happen while you're vulnerable... </p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Sleep</div>">> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #666; margin-top: 0;">😴 How long do you want to sleep?</h2> <p style="color: #ccc; margin-bottom: 10px;">Enter hours (max 6):</p> <p style="color: #ff6b6b; font-size: 13px; margin-bottom: 15px; font-style: italic;">⚠️ 5% chance of robbery if you have money</p> <input type="number" id="alley-sleep-input" min="1" max="6" value="4" style="width: 100px; padding: 8px; font-size: 16px; text-align: center; border: 2px solid #666; border-radius: 5px; background: #2a2a2a; color: white;"> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #666; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; margin-right: 10px;'>Confirm</div>">> <<set _sleepHours = Number(jQuery("#alley-sleep-input").val())>> <<if _sleepHours < 1 || _sleepHours > 6 || Number.isNaN(_sleepHours)>> <<set _sleepHours = 4>> <</if>> <!-- 5% chance of theft if player has money --> <<set _wasRobbed = false>> <<set _stolenAmount = 0>> <<if $money > 0>> <<set _robberyChance = Math.random() * 100>> <<if _robberyChance < 5>> <<set _stolenAmount = Math.floor($money * 0.5)>> <<set $money -= _stolenAmount>> <<set _wasRobbed = true>> <</if>> <</if>> <<if !$lucidRestActive>><<run advanceTime(_sleepHours * 60)>><</if>> <<run setup.setHairMessy()>> <!-- Update sleep time and handle debuffs (alleyway does NOT grant Well Rested) --> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.removeDebuff("exhaustion")>> <<set _dreamRoute = setup.witchSpells.onSleep(_sleepHours, "Alleyway")>> <<run Dialog.close()>> <<if _dreamRoute === "DreamFirstMeeting">> <<if _wasRobbed>><<run setup.questSystem.addNotification("failed", "Someone went through your pockets while you slept. $" + _stolenAmount + " is gone.")>><</if>> <<goto _dreamRoute>> <<elseif _wasRobbed>> <<goto "AlleySleepRobbed">> <<elseif _dreamRoute>> <<goto _dreamRoute>> <<else>> <<goto "AlleySleepSafe">> <</if>> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">👤 Body & Traits Overview</h1> <!-- IMAGE SLOTS --> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 25px;"> <!-- Face Image --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; text-align: center; background: #2a2a2a;"> <h3 style="color: #667eea; margin-top: 0;">Face</h3> <<set _faceImagePath = setup.getPlayerFaceImage()>> <<if _faceImagePath && _faceImagePath !== "">> <img @src="_faceImagePath" style="max-width: 100%; height: auto; border-radius: 8px; border: 2px solid #667eea;" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"> <div style="width: 150px; height: 150px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); margin: 5px auto; display: none; align-items: center; justify-content: center; color: white; border-radius: 8px; font-style: italic;"> No Image </div> <<else>> <div style="width: 150px; height: 150px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); margin: 5px auto; display: flex; align-items: center; justify-content: center; color: white; border-radius: 8px; font-style: italic;"> No Image </div> <</if>> </div> <!-- Chest Image --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; text-align: center; background: #2a2a2a;"> <h3 style="color: #667eea; margin-top: 0;">Chest</h3> <<set _chestImagePath = setup.getPlayerChestImage()>> <<if _chestImagePath && _chestImagePath !== "">> <img @src="_chestImagePath" style="max-width: 100%; height: auto; border-radius: 8px; border: 2px solid #667eea;" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"> <div style="width: 150px; height: 150px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); margin: 5px auto; display: none; align-items: center; justify-content: center; color: white; border-radius: 8px; font-style: italic;"> No Image </div> <<else>> <div style="width: 150px; height: 150px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); margin: 5px auto; display: flex; align-items: center; justify-content: center; color: white; border-radius: 8px; font-style: italic;"> No Image </div> <</if>> </div> <!-- Butt Image --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; text-align: center; background: #2a2a2a;"> <h3 style="color: #667eea; margin-top: 0;">Butt</h3> <<set _buttImagePath = setup.getPlayerButtImage()>> <<if _buttImagePath && _buttImagePath !== "">> <img @src="_buttImagePath" style="max-width: 100%; height: auto; border-radius: 8px; border: 2px solid #667eea;" onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';"> <div style="width: 150px; height: 150px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); margin: 5px auto; display: none; align-items: center; justify-content: center; color: white; border-radius: 8px; font-style: italic;"> No Image </div> <<else>> <div style="width: 150px; height: 150px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); margin: 5px auto; display: flex; align-items: center; justify-content: center; color: white; border-radius: 8px; font-style: italic;"> No Image </div> <</if>> </div> </div> <!-- PERSONAL INFORMATION --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin-top: 0;">📋 Personal Information</h2> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div> <strong style="color: #aaa;">Name:</strong> <span style="color: #ccc;">$firstName $lastName</span> </div> <div> <strong style="color: #aaa;">Gender:</strong> <span style="color: #ccc;"><<print $bodyParts.gender.toUpperFirst()>></span> </div> <div> <strong style="color: #aaa;">Housing Status:</strong> <span style="color: <<if !$homeless>>#51cf66<<else>>#ff6b6b<</if>>;"> <<if !$homeless>>Housed<<else>>Homeless<</if>> </span> </div> <div> <strong style="color: #aaa;">Age:</strong> <span style="color: #ccc;">$appearance.age</span> </div> </div> </div> <!-- APPEARANCE DETAILS --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin-top: 0;">✨ Appearance Details</h2> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div> <strong style="color: #aaa;">Hair:</strong> <<set _playerHairStyle = $appearance.hairStyle === "messy" ? "Messy " : "">> <<set _playerHairLength = $appearance.hairLength ? $appearance.hairLength.toUpperFirst() : "Short">> <span style="color: #ccc;"><<print _playerHairStyle + _playerHairLength>> $appearance.hairColor</span> </div> <div> <strong style="color: #aaa;">Skin Tone:</strong> <span style="color: #ccc;"><<print $appearance.skinTone.toUpperFirst()>></span> </div> <div> <strong style="color: #aaa;">Chest:</strong> <span style="color: #ccc;"><<print $bodyParts.chest.toUpperFirst()>></span> </div> <div> <strong style="color: #aaa;">Butt:</strong> <span style="color: #ccc;"><<print $bodyParts.butt.toUpperFirst()>></span> </div> <div> <strong style="color: #aaa;">Genitals:</strong> <span style="color: #ccc;"><<print $bodyParts.genitals.toUpperFirst()>></span> </div> </div> </div> <!-- STATS --> <<set _bonuses = setup.calculateStatBonuses()>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #17a2b8; margin-top: 0;">📊 Stats</h2> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div> <strong style="color: #aaa;">Strength:</strong> <span style="color: #ccc;">$stats.strength</span> <<if _bonuses.strength !== 0>> <span style="color: <<if _bonuses.strength > 0>>#51cf66<<else>>#ff6b6b<</if>>;"> (<<if _bonuses.strength > 0>>+<</if>>_bonuses.strength) </span> <</if>> </div> <div> <strong style="color: #aaa;">Intelligence:</strong> <span style="color: #ccc;">$stats.intelligence</span> <<if _bonuses.intelligence !== 0>> <span style="color: <<if _bonuses.intelligence > 0>>#51cf66<<else>>#ff6b6b<</if>>;"> (<<if _bonuses.intelligence > 0>>+<</if>>_bonuses.intelligence) </span> <</if>> </div> <div> <strong style="color: #aaa;">Charisma:</strong> <span style="color: #ccc;">$stats.charisma</span> <<if _bonuses.charisma !== 0>> <span style="color: <<if _bonuses.charisma > 0>>#51cf66<<else>>#ff6b6b<</if>>;"> (<<if _bonuses.charisma > 0>>+<</if>>_bonuses.charisma) </span> <</if>> </div> <div> <strong style="color: #aaa;">Dexterity:</strong> <span style="color: #ccc;">$stats.dexterity</span> <<if _bonuses.dexterity !== 0>> <span style="color: <<if _bonuses.dexterity > 0>>#51cf66<<else>>#ff6b6b<</if>>;"> (<<if _bonuses.dexterity > 0>>+<</if>>_bonuses.dexterity) </span> <</if>> </div> <<if !($physicalTraits && $physicalTraits.includes("Ojou"))>> <div> <strong style="color: #aaa;">Refinement:</strong> <span style="color: #ccc;"><<print ($ojou_refinement || 0)>></span> </div> <</if>> </div> </div> <!-- SEXUAL SKILLS SECTION (Only if Sexually Skilled trait or Succubus/Slut present) --> <<if ($skills && $skills.includes("Sexually Skilled")) || ($physicalTraits && (($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju")))>> <<run setup.initializeSexualSkills()>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 id="sexualSkillsHeader" style="color: #e91e63; margin-top: 0; cursor: pointer; user-select: none;" onclick="jQuery('#sexualSkillsContent').slideToggle(300); jQuery('#sexualSkillsArrow').text(jQuery('#sexualSkillsArrow').text() === '▼' ? '▶' : '▼');"> <span id="sexualSkillsArrow">▼</span> 💋 Sexual Skills </h2> <div id="sexualSkillsContent"> <!-- Core Acts --> <h3 style="color: #e91e63; font-size: 16px; margin: 15px 0 10px 0; border-bottom: 2px solid #e91e63; padding-bottom: 5px;">Core Sexual Acts</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-bottom: 15px;"> <<set _coreSkills = ["oralGiving", "oralReceiving", "vaginal", "anal", "handjobs", "fingering", "titWorship", "titfuck"]>> <<for _skillKey range _coreSkills>> <<set _skill = $sexualSkills[_skillKey]>> <<set _displayName = setup.getSexualSkillDisplayName(_skillKey)>> <div style="background: #1a1a1a; border: 2px solid #e91e63; border-radius: 8px; padding: 10px;"> <div style="color: #e91e63; font-weight: bold; margin-bottom: 5px;">_displayName</div> <div style="color: #ccc; font-size: 14px;">Level: <span style="color: #51cf66;"><<print _skill.level>></span></div> <div style="background: #333; border-radius: 4px; height: 8px; margin-top: 5px; overflow: hidden;"> <<set _expPercent = (_skill.exp / _skill.maxExp) * 100>> <div @style="'width: ' + _expPercent + '%; height: 100%; background: linear-gradient(90deg, #e91e63 0%, #c2185b 100%);'"></div> </div> <div style="color: #888; font-size: 11px; margin-top: 3px;"><<print _skill.exp>>/<<print _skill.maxExp>> XP</div> </div> <</for>> </div> <!-- Styles & Techniques --> <h3 style="color: #e91e63; font-size: 16px; margin: 15px 0 10px 0; border-bottom: 2px solid #e91e63; padding-bottom: 5px;">Styles & Techniques</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-bottom: 15px;"> <<set _styleSkills = ["teasing", "dirtyTalk", "roleplay", "domination", "submission", "sensual", "rough"]>> <<for _skillKey range _styleSkills>> <<set _skill = $sexualSkills[_skillKey]>> <<set _displayName = setup.getSexualSkillDisplayName(_skillKey)>> <div style="background: #1a1a1a; border: 2px solid #9b59b6; border-radius: 8px; padding: 10px;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 5px;">_displayName</div> <div style="color: #ccc; font-size: 14px;">Level: <span style="color: #51cf66;"><<print _skill.level>></span></div> <div style="background: #333; border-radius: 4px; height: 8px; margin-top: 5px; overflow: hidden;"> <<set _expPercent = (_skill.exp / _skill.maxExp) * 100>> <div @style="'width: ' + _expPercent + '%; height: 100%; background: linear-gradient(90deg, #9b59b6 0%, #7b1fa2 100%);'"></div> </div> <div style="color: #888; font-size: 11px; margin-top: 3px;"><<print _skill.exp>>/<<print _skill.maxExp>> XP</div> </div> <</for>> </div> <!-- Physical Attributes & Advanced --> <h3 style="color: #e91e63; font-size: 16px; margin: 15px 0 10px 0; border-bottom: 2px solid #e91e63; padding-bottom: 5px;">Physical & Advanced</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<set _advancedSkills = ["stamina", "flexibility", "rhythm", "exhibitionism", "fetishPlay"]>> <<for _skillKey range _advancedSkills>> <<set _skill = $sexualSkills[_skillKey]>> <<set _displayName = setup.getSexualSkillDisplayName(_skillKey)>> <div style="background: #1a1a1a; border: 2px solid #ffc107; border-radius: 8px; padding: 10px;"> <div style="color: #ffc107; font-weight: bold; margin-bottom: 5px;">_displayName</div> <div style="color: #ccc; font-size: 14px;">Level: <span style="color: #51cf66;"><<print _skill.level>></span></div> <div style="background: #333; border-radius: 4px; height: 8px; margin-top: 5px; overflow: hidden;"> <<set _expPercent = (_skill.exp / _skill.maxExp) * 100>> <div @style="'width: ' + _expPercent + '%; height: 100%; background: linear-gradient(90deg, #ffc107 0%, #ff9800 100%);'"></div> </div> <div style="color: #888; font-size: 11px; margin-top: 3px;"><<print _skill.exp>>/<<print _skill.maxExp>> XP</div> </div> <</for>> </div> </div> </div> <</if>> <!-- ACTIVE EFFECTS (Buffs, Debuffs & Passive Trait Effects) --> <<set _pyrowPassiveActive = ($physicalTraits && $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive())>> <<set _vampireTraitActive = ($physicalTraits && $physicalTraits.includes("Vampire"))>> <<set _vampireHour = Math.floor($timeInMinutes / 60) % 24>> <<set _vampireIsNight = (_vampireHour < 6 || _vampireHour >= 18)>> <<if ($activeBuffs && $activeBuffs.length > 0) || ($activeDebuffs && $activeDebuffs.length > 0) || _pyrowPassiveActive || _vampireTraitActive>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ffd43b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffd43b; margin-top: 0;">⚡ Active Effects</h2> <!-- Debuffs (red) --> <<if $activeDebuffs && $activeDebuffs.length > 0>> <<for _debuff range $activeDebuffs>> <div style="background: #1a1a1a; border: 2px solid #ff6b6b; border-radius: 8px; padding: 12px 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ff6b6b; font-weight: bold; font-size: 16px;">❌ <<= _debuff.name>></span> <span style="color: #888; font-size: 12px;">(Until Sleep)</span> </div> <div style="color: #aaa; font-size: 13px; margin-top: 8px;"> <<if _debuff.id === "exhaustion">> • -20% Trade Success<br> • -20% Steal Success <<elseif _debuff.id === "compulsion">> • -15% Trade Success<br> • -15% Steal Success <<elseif _debuff.id === "sexual_needs">> • -20% Trade Success<br> • -20% Steal Success <<elseif _debuff.id === "cheshire_sexual_needs">> • -20% Trade Success<br> • -20% Steal Success <</if>> </div> </div> <</for>> <</if>> <!-- Buffs (green) --> <<if $activeBuffs && $activeBuffs.length > 0>> <<for _buff range $activeBuffs>> <<set _currentTotalMinutes = ($dayNumber - 1) * 1440 + $timeInMinutes>> <<set _remainingMinutes = _buff.expiresAt - _currentTotalMinutes>> <<set _remainingHours = Math.floor(_remainingMinutes / 60)>> <<set _remainingMins = _remainingMinutes % 60>> <div style="background: #1a1a1a; border: 2px solid #51cf66; border-radius: 8px; padding: 12px 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #51cf66; font-weight: bold; font-size: 16px;">✓ <<= _buff.name>></span> <span style="color: #888; font-size: 12px;"> <<if _remainingHours > 0>> <<= _remainingHours>>h <<= _remainingMins>>m remaining <<else>> <<= _remainingMins>>m remaining <</if>> </span> </div> <div style="color: #aaa; font-size: 13px; margin-top: 8px;"> <<if _buff.id === "well_rested">> • +5% Trade Success<br> • +5% Steal Success<br> • Improved Fishing Luck<br> • +1 Daily Talk Bonus <<elseif _buff.id === "satisfied">> • +5% Trade Success<br> • +5% Steal Success<br> • Improved Fishing Luck<br> • +1 Daily Talk Bonus <<elseif _buff.id === "shower_fresh">> • +15% Trading Bonus <<elseif _buff.id === "bath_relaxed">> • +10% Steal Chance <<elseif _buff.id === "bath_luxury">> • +20% Trading Bonus<br> • +5% Steal Chance <<elseif _buff.id === "food_morning_boost">> • +$2-5 from all money sources <<elseif _buff.id === "food_comfort">> • +10% Trading Bonus <<elseif _buff.id === "food_social_glow">> • +1 Relationship points per daily talk <<elseif _buff.id === "food_well_fed">> • +15% Trading Bonus <<elseif _buff.id === "food_treasure_hunter">> • +1% Treasure chance in fishing<br> • -1% Trash chance in fishing <<elseif _buff.id === "food_hearty_meal">> • +2 Relationship points per daily talk <<elseif _buff.id === "food_trade">> • +<<print _buff.effects.tradeChance || 0>>% Trading Bonus <<elseif _buff.id === "food_fishing">> • Improved Fishing Luck <<elseif _buff.id === "food_stealing">> • +<<print _buff.effects.stealChance || 0>>% Steal Chance <<elseif _buff.id === "food_money">> • +<<print _buff.effects.moneyBonus || 0>>% Money Bonus <<elseif _buff.id === "food_relationship">> • +<<print _buff.effects.relationshipBonus || 0>> Relationship Bonus <<elseif _buff.id === "automaton_overcharged">> • +300 to all stats<br> • 3× fish catch multiplier <<elseif _buff.id === "honeybee_lustful">> • +50% Brothel pay<br> • +50% Stripper tips<br> • +50% PrawnHub earnings <<elseif _buff.id === "jinko_fish_common">> • +1% to all stats <<elseif _buff.id === "jinko_fish_uncommon">> • +5% to all stats <<elseif _buff.id === "jinko_fish_rare">> • +10% to all stats <<elseif _buff.id === "jinko_fish_epic">> • +15% to all stats <<elseif _buff.id === "jinko_fish_legendary">> • +20% to all stats <<else>> <<if setup.buffDefinitions && setup.buffDefinitions[_buff.id] && setup.buffDefinitions[_buff.id].description>> • <<print setup.buffDefinitions[_buff.id].description>> <<elseif setup.foodBuffs && setup.foodBuffs[_buff.id] && setup.foodBuffs[_buff.id].description>> • <<print setup.foodBuffs[_buff.id].description>> <</if>> <</if>> </div> </div> <</for>> <</if>> <!-- Passive Trait Effects (not timed) --> <<if _pyrowPassiveActive>> <div style="background: #1a1a1a; border: 2px solid #ff8c00; border-radius: 8px; padding: 12px 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ff8c00; font-weight: bold; font-size: 16px;">☀️ Solar Radiance</span> <span style="color: #888; font-size: 12px;">(Clear + Day)</span> </div> <div style="color: #aaa; font-size: 13px; margin-top: 8px;"> • +25% All Stats<br> • +25% Trade, Steal, Relationship<br> • +25% Streaming, Brothel, Stripper Pay<br> • +25% Epic Fishing Chance </div> </div> <</if>> <<if _vampireTraitActive>> <<if _vampireIsNight>> <div style="background: #1a1a1a; border: 2px solid #9b59b6; border-radius: 8px; padding: 12px 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #9b59b6; font-weight: bold; font-size: 16px;">🌙 Nocturnal Power</span> <span style="color: #888; font-size: 12px;">(Night)</span> </div> <div style="color: #aaa; font-size: 13px; margin-top: 8px;"> • +50% All Stats </div> </div> <<else>> <div style="background: #1a1a1a; border: 2px solid #ff6b6b; border-radius: 8px; padding: 12px 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ff6b6b; font-weight: bold; font-size: 16px;">☀️ Daylight Weakness</span> <span style="color: #888; font-size: 12px;">(Day)</span> </div> <div style="color: #aaa; font-size: 13px; margin-top: 8px;"> • -50% All Stats </div> </div> <</if>> <</if>> </div> <</if>> <!-- PHYSICAL TRAITS --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 id="physicalTraitsHeader" style="color: #51cf66; margin-top: 0; cursor: pointer; user-select: none;" onclick="jQuery('#physicalTraitsContent').slideToggle(300); jQuery('#physicalTraitsArrow').text(jQuery('#physicalTraitsArrow').text() === '▼' ? '▶' : '▼');"> <span id="physicalTraitsArrow">▼</span> 💪 Physical Traits </h2> <div id="physicalTraitsContent"> <<if $physicalTraits && $physicalTraits.length > 0>> <<set _displayPhysicalTraits = $physicalTraits.filter(function(trait) { return trait !== "Short Hair" && trait !== "Long Hair" && trait !== "Cerberus"; })>> <<if _displayPhysicalTraits.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _trait range _displayPhysicalTraits>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <<set _traitColor = _traitValue >= 0 ? "#51cf66" : "#ff6b6b">> /* Player-crafted traits store their stat bonuses in $craftedTraitBonuses, not setup.traitBonuses; fall back to it so their values show here. */ <<set _traitBonuses = setup.traitBonuses[_trait] || ($craftedTraitBonuses ? $craftedTraitBonuses[_trait] : null) || {}>> <div @style="'background: #1a1a1a; border: 2px solid ' + _traitColor + '; border-radius: 8px; padding: 10px 15px;'"> <strong style="color: #ccc;"><<if _trait === "Futanari">><<print setup.getFutaDisplayName()>><<else>>_trait<</if>></strong> <span @style="'color: ' + _traitColor + '; font-size: 13px; margin-left: 5px;'"> (<<if _traitValue > 0>>+<</if>>_traitValue) </span> <<if Object.keys(_traitBonuses).length > 0>> <div style="font-size: 11px; color: #888; margin-top: 3px;"> <<set _bonusText = []>> <<if _traitBonuses.strength !== undefined>><<run _bonusText.push("STR: " + (_traitBonuses.strength > 0 ? "+" : "") + _traitBonuses.strength)>><</if>> <<if _traitBonuses.intelligence !== undefined>><<run _bonusText.push("INT: " + (_traitBonuses.intelligence > 0 ? "+" : "") + _traitBonuses.intelligence)>><</if>> <<if _traitBonuses.charisma !== undefined>><<run _bonusText.push("CHA: " + (_traitBonuses.charisma > 0 ? "+" : "") + _traitBonuses.charisma)>><</if>> <<if _traitBonuses.dexterity !== undefined>><<run _bonusText.push("DEX: " + (_traitBonuses.dexterity > 0 ? "+" : "") + _traitBonuses.dexterity)>><</if>> <<print _bonusText.join(" ")>> </div> <</if>> </div> <</for>> </div> <<else>> <p style="color: #666; font-style: italic; margin: 0;">No physical traits acquired yet.</p> <</if>> <<else>> <p style="color: #666; font-style: italic; margin: 0;">No physical traits acquired yet.</p> <</if>> </div> </div> <!-- MENTAL TRAITS --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 id="mentalTraitsHeader" style="color: #9b59b6; margin-top: 0; cursor: pointer; user-select: none;" onclick="jQuery('#mentalTraitsContent').slideToggle(300); jQuery('#mentalTraitsArrow').text(jQuery('#mentalTraitsArrow').text() === '▼' ? '▶' : '▼');"> <span id="mentalTraitsArrow">▼</span> 🧠 Mental Traits </h2> <div id="mentalTraitsContent"> <<if $activeTransformation === "Cerberus">> <<run setup.ensureCerberusHeads()>> <<set _headDefs = [{key: "center", label: $firstName}, {key: "left", label: ($cerberusHeadNames ? ($cerberusHeadNames.left || "?") : "?")}, {key: "right", label: ($cerberusHeadNames ? ($cerberusHeadNames.right || "?") : "?")}]>> <<for _hd range _headDefs>> <div style="margin-bottom: 18px;"> <h3 style="margin: 0 0 8px 0; border-bottom: 1px solid #c0392b; padding-bottom: 4px;"><span @style="'color: ' + (setup.cerberusHeadColors[_hd.key] || '#e74c3c') + ';'">_hd.label</span> <span style="color: #ccc;">$lastName</span></h3> <<set _cnt = 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _trait range $mentalTraits>> <<if $cerberusHeadMap[_trait] === _hd.key>> <<set _cnt++>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<set _traitColor = _traitValue >= 0 ? "#9b59b6" : "#ff6b6b">> <<set _traitBonuses = setup.traitBonuses[_trait] || {}>> <div @style="'background: #1a1a1a; border: 2px solid ' + _traitColor + '; border-radius: 8px; padding: 10px 15px;'"> <strong style="color: #ccc;">_trait</strong> <span @style="'color: ' + _traitColor + '; font-size: 13px; margin-left: 5px;'"> (<<if _traitValue > 0>>+<</if>>_traitValue) </span> <<if Object.keys(_traitBonuses).length > 0>> <div style="font-size: 11px; color: #888; margin-top: 3px;"> <<set _bonusText = []>> <<if _traitBonuses.strength !== undefined>><<run _bonusText.push("STR: " + (_traitBonuses.strength > 0 ? "+" : "") + _traitBonuses.strength)>><</if>> <<if _traitBonuses.intelligence !== undefined>><<run _bonusText.push("INT: " + (_traitBonuses.intelligence > 0 ? "+" : "") + _traitBonuses.intelligence)>><</if>> <<if _traitBonuses.charisma !== undefined>><<run _bonusText.push("CHA: " + (_traitBonuses.charisma > 0 ? "+" : "") + _traitBonuses.charisma)>><</if>> <<if _traitBonuses.dexterity !== undefined>><<run _bonusText.push("DEX: " + (_traitBonuses.dexterity > 0 ? "+" : "") + _traitBonuses.dexterity)>><</if>> <<print _bonusText.join(" ")>> </div> <</if>> </div> <</if>> <</for>> </div> <<if _cnt === 0>><p style="color: #666; font-style: italic; margin: 4px 0 0 0;">No mental traits on this head.</p><</if>> </div> <</for>> <<elseif $mentalTraits && $mentalTraits.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _trait range $mentalTraits>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<set _traitColor = _traitValue >= 0 ? "#9b59b6" : "#ff6b6b">> <<set _traitBonuses = setup.traitBonuses[_trait] || {}>> <div @style="'background: #1a1a1a; border: 2px solid ' + _traitColor + '; border-radius: 8px; padding: 10px 15px;'"> <strong style="color: #ccc;">_trait</strong> <span @style="'color: ' + _traitColor + '; font-size: 13px; margin-left: 5px;'"> (<<if _traitValue > 0>>+<</if>>_traitValue) </span> <<if Object.keys(_traitBonuses).length > 0>> <div style="font-size: 11px; color: #888; margin-top: 3px;"> <<set _bonusText = []>> <<if _traitBonuses.strength !== undefined>><<run _bonusText.push("STR: " + (_traitBonuses.strength > 0 ? "+" : "") + _traitBonuses.strength)>><</if>> <<if _traitBonuses.intelligence !== undefined>><<run _bonusText.push("INT: " + (_traitBonuses.intelligence > 0 ? "+" : "") + _traitBonuses.intelligence)>><</if>> <<if _traitBonuses.charisma !== undefined>><<run _bonusText.push("CHA: " + (_traitBonuses.charisma > 0 ? "+" : "") + _traitBonuses.charisma)>><</if>> <<if _traitBonuses.dexterity !== undefined>><<run _bonusText.push("DEX: " + (_traitBonuses.dexterity > 0 ? "+" : "") + _traitBonuses.dexterity)>><</if>> <<print _bonusText.join(" ")>> </div> <</if>> </div> <</for>> </div> <<else>> <p style="color: #666; font-style: italic; margin: 0;">No mental traits acquired yet.</p> <</if>> </div> </div> <!-- SKILLS --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 id="skillsHeader" style="color: #ffc107; margin-top: 0; cursor: pointer; user-select: none;" onclick="jQuery('#skillsContent').slideToggle(300); jQuery('#skillsArrow').text(jQuery('#skillsArrow').text() === '▼' ? '▶' : '▼');"> <span id="skillsArrow">▼</span> 🎯 Skills </h2> <div id="skillsContent"> <<if $skills && $skills.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _skill range $skills>> <<set _skillValue = setup.getTraitValue("skill", _skill)>> <<set _skillBonuses = setup.skillBonuses[_skill] || {}>> <div style="background: #1a1a1a; border: 2px solid #ffc107; border-radius: 8px; padding: 10px 15px;"> <strong style="color: #ccc;">_skill</strong> <span style="color: #ffc107; font-size: 13px; margin-left: 5px;"> (+_skillValue) </span> <<if Object.keys(_skillBonuses).length > 0>> <div style="font-size: 11px; color: #888; margin-top: 3px;"> <<if _skillBonuses.strength>>STR: <<if _skillBonuses.strength > 0>>+<</if>><<print _skillBonuses.strength>> <</if>> <<if _skillBonuses.intelligence>>INT: <<if _skillBonuses.intelligence > 0>>+<</if>><<print _skillBonuses.intelligence>> <</if>> <<if _skillBonuses.charisma>>CHA: <<if _skillBonuses.charisma > 0>>+<</if>><<print _skillBonuses.charisma>> <</if>> <<if _skillBonuses.dexterity>>DEX: <<if _skillBonuses.dexterity > 0>>+<</if>><<print _skillBonuses.dexterity>><</if>> </div> <</if>> </div> <</for>> </div> <<else>> <p style="color: #666; font-style: italic; margin: 0;">No skills acquired yet.</p> <</if>> </div> </div> <!-- CURRENT JOB --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 id="jobsHeader" style="color: #667eea; margin-top: 0; cursor: pointer; user-select: none;" onclick="jQuery('#jobsContent').slideToggle(300); jQuery('#jobsArrow').text(jQuery('#jobsArrow').text() === '▼' ? '▶' : '▼');"> <span id="jobsArrow">▼</span> 💼 Current Employment </h2> <div id="jobsContent"> <<if $jobs && $jobs.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _job range $jobs>> <<set _jobValue = setup.getTraitValue("job", _job)>> <div style="background: #1a1a1a; border: 2px solid #667eea; border-radius: 8px; padding: 10px 15px;"> <strong style="color: #ccc;">_job</strong> <span style="color: #667eea; font-size: 13px; margin-left: 5px;"> (Value: _jobValue) </span> </div> <</for>> </div> <<else>> <p style="color: #ff6b6b; font-style: italic; margin: 0;">Currently unemployed.</p> <</if>> </div> </div> <!-- BACK BUTTON --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<set $returningFromBody = true>> <<set _prev = previous()>> <<if $lastLocation && $lastLocation !== "Body" && $lastLocation !== "Debug" && $lastLocation !== "Credits">> <<goto $lastLocation>> <<elseif _prev !== "Body" && _prev !== "Debug">> <<goto _prev>> <<else>> <<goto "Summary">> <</if>> <</link>> </div> </div> <</nobr>>
:: StoryMenu <<nobr>> <<if passage() !== "PrawnHubStreamEnd">> <<if $currentArtifact === "The Tidal Memory Stone" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> [[Teleport]] <</if>> <<if $physicalTraits && ($physicalTraits.includes("Angel") || $physicalTraits.includes("Cupid") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Honeybee") || $physicalTraits.includes("Dark Angel") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Anubis"))>> [[Abilities]] <</if>> <<if $witchFormActive || $clairFormActive>> [[Spells|Spellbook]] <</if>> [[Body]] [[Traits|Trait Information]] [[Inventory]] <<if $hasSmartphone>> [[Phone|Phone]] <</if>> [[Feats|Achievements]] <<if setup.questSystem && setup.questSystem.getActiveQuestCount() > 0>>[[Quests]] (<<= setup.questSystem.getActiveQuestCount()>>)<<else>>[[Quests]]<</if>> <<if $sideJobs && $sideJobs.includes("Prostitute")>> [[Solicit|Soliciting]] <</if>> [[Cheats|CheatMenuPassword]] [[Settings|ImageSettings]] <</if>> [[Patreon|https://www.patreon.com/Grankor]] [[Discord|https://discord.gg/z9eDdQC6zA]] [[Credits]] <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Downtown")>> <<run $visitedLocations.push("Downtown")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "Downtown">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">🏙️ Downtown</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Downtown.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Downtown"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #4a9eff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0;"> The bustling heart of Sunfish City stretches out before you. Skyscrapers tower overhead, streets are packed with people rushing to their destinations, and the air buzzes with the energy of urban life. Shop fronts line the sidewalks, and the constant hum of traffic fills the air. </p> </div> <h2 style="color: #667eea;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<goto "BusStop">> <</link>> </div> <!-- Apartments --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏢 Sunfish Apartments</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Residential high-rise offering furnished apartments for rent.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Apartments</div>">> <<goto "Apartments">> <</link>> </div> <!-- Town Hall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🏛️ Town Hall</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The seat of city government and administration.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Town Hall</div>">> <<goto "TownHall">> <</link>> </div> <!-- Aquarium --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🐠 Sunfish City Aquarium</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A massive oceanarium featuring marine life from around the world.</p> <<link "<div style='background: #1e90ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> <!-- Police Department --> <div style="border: 3px solid #4169e1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4169e1; margin: 0 0 10px 0;">🚔 Police Department</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Sunfish City's main police headquarters and precinct.</p> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Police Department</div>">> <<goto "PoliceDepartment">> <</link>> </div> <!-- Bank --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🏦 Sunfish City Bank</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Professional banking services and account management.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bank</div>">> <<goto "Bank">> <</link>> </div> <!-- Vending Machine --> <div style="border: 3px solid #00b894; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #55efc4; margin: 0 0 10px 0;">🍫 Vending Machine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Grab a quick snack or drink.</p> <<link "<div style='background: #00b894; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Machine</div>">> <<goto "VendingMachineShop">> <</link>> </div> </div> <h2 style="color: #667eea;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Corporate towers and professional opportunities.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Neon-lit streets filled with nightlife and vice.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the dark alleyway.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Alleyway</div>">> <<goto "Alleyway">> <</link>> </div> <!-- Commercial District --> <div style="border: 3px solid #5ca4e8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #5ca4e8; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Shopping centers, medical facilities, and various services.</p> <<link "<div style='background: #5ca4e8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Commercial District</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "Downtown">> <<goto "CrimeHub">> <</link>> <</if>> </div> <<set _npcsHere = setup.getNPCsAtLocation("Downtown")>> <h2 style="margin-top: 30px; color: #667eea;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #667eea; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"> <<if _npc.jobs && _npc.jobs.length > 0>> <<print _npc.jobs.join(", ")>> <<else>> Unemployed <</if>> </p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The downtown streets are busy, but no one you know is around right now. </p> </div> <</if>> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("BusinessDistrict")>> <<run $visitedLocations.push("BusinessDistrict")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "BusinessDistrict">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">💼 Business District</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/BusinessDistrict.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Business District"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> Gleaming corporate towers pierce the sky. Professionals in sharp suits hurry along pristine sidewalks, clutching briefcases and smartphones. The atmosphere is calculated and ruthlessly efficient. </p> </div> <h2 style="color: #17a2b8;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<goto "BusStop">> <</link>> </div> <!-- Seabass Park --> <div style="border: 3px solid #2d5016; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4a7c2c; margin: 0 0 10px 0;">🌳 Seabass Park</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public park with green spaces and walking paths.</p> <<link "<div style='background: #2d5016; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Park</div>">> <<goto "SeabassPark">> <</link>> </div> <!-- Gym --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">💪 Opah Fitness</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">State of the art gym with weights and cardio equipment.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Gym</div>">> <<goto "OpahFitness">> <</link>> </div> <!-- Dance Studio --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💃 Ribbonfish Dance Studio</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Professional dance studio with classes and private sessions.</p> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Dance Studio</div>">> <<goto "DanceStudio">> <</link>> </div> <!-- Cafe --> <div style="border: 3px solid #8b4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d2691e; margin: 0 0 10px 0;">☕ Manta Ray Cafe</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Upscale coffee shop for business professionals.</p> <<link "<div style='background: #8b4513; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Cafe</div>">> <<goto "Cafe">> <</link>> </div> <!-- Training Center --> <div style="border: 3px solid #5c6bc0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #5c6bc0; margin: 0 0 10px 0;">🎓 Bluefin Development Center</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Training center offering courses to improve skills and stats.</p> <<link "<div style='background: #5c6bc0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Training Center</div>">> <<goto "TrainingCenter">> <</link>> </div> <!-- Mall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Shopping center with stores and services.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Mall</div>">> <<goto "Mall">> <</link>> </div> <!-- Sawtooth Construction --> <div style="border: 3px solid #795548; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #a1887f; margin: 0 0 10px 0;">🏗️ Sawtooth Construction</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Construction company offering building projects and contracting work.</p> <<link "<div style='background: #795548; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Office</div>">> <<goto "ConstructionOffice">> <</link>> </div> <!-- Vending Machine --> <div style="border: 3px solid #00b894; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #55efc4; margin: 0 0 10px 0;">🍫 Vending Machine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Grab a quick snack or drink.</p> <<link "<div style='background: #00b894; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Machine</div>">> <<goto "VendingMachineShop">> <</link>> </div> </div> <h2 style="color: #17a2b8;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">City center and hub.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Industrial waterfront district.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Docks</div>">> <<goto "Docks">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Neon-lit streets filled with nightlife and vice.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the dark alley.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Alleyway</div>">> <<goto "Alleyway">> <</link>> </div> </div> <!-- Negotiator Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Negotiator">> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">⚖ Negotiator - Case Board</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Take on negotiation cases for businesses in the district. Pick your case, choose your approach. Max 2 cases per day.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>View Case Board</div>">> <<goto "NegotiatorWork">> <</link>> </div> <</if>> <!-- Add after the travel grid, before closing div --> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "BusinessDistrict">> <<goto "CrimeHub">> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("RedLightDistrict")>> <<run $visitedLocations.push("RedLightDistrict")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "RedLightDistrict">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 Red Light District</h1> <!-- Location Image (Conditional) --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/RedLightDistrict.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #ff1493; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Red Light District"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #c31432 0%, #ff1493 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1493;"> <p style="color: white; font-size: 18px; margin: 0;"> Neon signs cast a crimson glow over the streets. Workers beckon from doorways while shadowy figures conduct business in dark corners. This is where pleasure, vice, and opportunity intertwine. </p> </div> <!-- Prostitute Side Job Discovery Event --> <<if !$sideJobs>><<set $sideJobs = []>><</if>> <<if !$sideJobs.includes("Prostitute") && (getTimeOfDay() === "evening" || getTimeOfDay() === "night")>> <!-- Minimized bar --> <div id="prostMinBar" style="background: linear-gradient(135deg, #1a0a2e 0%, #2d1b4e 100%); border-radius: 15px; padding: 15px 20px; margin-bottom: 20px; border: 2px solid #ff1493; box-shadow: 0 0 20px rgba(255,20,147,0.3); cursor: pointer; display: none;" onclick="document.getElementById('prostMinBar').style.display='none'; document.getElementById('prostFullEvent').style.display='block'; SugarCube.State.variables.prostEventMinimized=false;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ff1493; font-weight: bold; font-size: 14px;">💋 A figure in the shadows wants your attention...</span> <span style="color: #b8a9c9; font-size: 14px; font-weight: bold;">▲</span> </div> </div> <!-- Full event --> <div id="prostFullEvent" class="prost-fade" style="background: linear-gradient(135deg, #1a0a2e 0%, #2d1b4e 100%); border-radius: 15px; padding: 25px; margin-bottom: 20px; border: 2px solid #ff1493; box-shadow: 0 0 20px rgba(255,20,147,0.3); position: relative; display: none;"> <!-- Set initial visibility based on minimized state --> <<run setTimeout(function() { var m = document.getElementById('prostMinBar'); var f = document.getElementById('prostFullEvent'); if (State.variables.prostEventMinimized) { if (m) m.style.display = 'block'; } else { if (f) f.style.display = 'block'; } }, 0)>> <!-- Minimize arrow --> <div style="position: absolute; top: 8px; right: 12px; color: #b8a9c9; font-size: 14px; cursor: pointer; padding: 4px 8px; border-radius: 4px; background: rgba(0,0,0,0.3);" title="Minimize" onclick="document.getElementById('prostFullEvent').style.display='none'; document.getElementById('prostMinBar').style.display='block'; SugarCube.State.variables.prostEventMinimized=true;">▼</div> <p style="color: #e0d0f0; font-style: italic; font-size: 16px; line-height: 1.7; margin-bottom: 15px;"> A figure leans against the neon-washed wall ahead, watching the street with practiced ease. As you pass, they catch your eye and smile — not predatory, just knowing. </p> <p style="color: #e0d0f0; font-style: italic; font-size: 16px; line-height: 1.7; margin-bottom: 15px;"> "You've got the look," they say, sizing you up with frank appreciation. "If you ever want to make some real money out here, you've got the goods for it. Trust me — I can tell." </p> <p style="color: #b8a9c9; font-size: 14px; margin-bottom: 15px;">They nod toward the deeper shadows of the district, where figures move in and out of doorways, quick transactions happening in half-whispered exchanges.</p> <div style="display: flex; gap: 10px; flex-wrap: wrap; align-items: center;"> <<if setup.prostitute.meetsSexualWorkReq()>> <<link "<div style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; padding: 12px 24px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 3px 8px rgba(0,0,0,0.3);'>💋 "Tell me more..."</div>">> <<if !$sideJobs>><<set $sideJobs = []>><</if>> <<run $sideJobs.push("Prostitute")>> <<run setup.prostitute.initData()>> <<replace "#prostFullEvent">> <div style="background: rgba(255,20,147,0.1); border-radius: 10px; padding: 15px; border: 1px solid #ff149366;"> <p style="color: #ff1493; font-weight: bold; margin-bottom: 5px;">💋 Side Job Unlocked: Prostitute</p> <p style="color: #ccc; font-size: 13px; margin: 0;">You can now solicit clients using the Solicit button in the sidebar. Work the streets at night, or any time in the Red Light District.</p> </div> <</replace>> <</link>> <<else>> <div style="background: #2a2a2a; color: #666; padding: 12px 24px; border-radius: 8px; font-weight: bold; font-size: 14px; border: 1px solid #444;">💋 "Tell me more..."</div> <p style="color: #ff1493; font-size: 12px; margin: 4px 0 0 0; font-style: italic;">Requires: Sexually Skilled</p> <</if>> </div> </div> <</if>> <h2 style="color: #ff1493;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<goto "BusStop">> <</link>> </div> <!-- Azure Angelfish Lounge --> <div style="border: 3px solid #007FFF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #007FFF; margin: 0 0 10px 0;">💋 Azure Angelfish Lounge</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">High-end establishment offering companionship.</p> <<link "<div style='background: #007FFF; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Brothel</div>">> <<goto "Brothel">> <</link>> </div> <!-- Electric Jelly Revue --> <div style="border: 3px solid #9D00FF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9D00FF; margin: 0 0 10px 0;">🪼 Electric Jelly Revue</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Pulsing music and dancers on stage.</p> <<link "<div style='background: #9D00FF; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Strip Club</div>">> <<goto "StripClub">> <</link>> </div> <!-- The Silver Marlin --> <div style="border: 3px solid #C0C0C0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #C0C0C0; margin: 0 0 10px 0;">🎰 The Silver Marlin</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Bright lights and high stakes gambling.</p> <<link "<div style='background: #C0C0C0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Casino</div>">> <<goto "Casino">> <</link>> </div> </div> <h2 style="color: #ff1493;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">City center and hub.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Corporate towers and offices.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Industrial waterfront district.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Docks</div>">> <<goto "Docks">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the dark alley.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Alleyway</div>">> <<goto "Alleyway">> <</link>> </div> <!-- Outskirts --> <div style="border: 3px solid #4a4a4a; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #888; margin: 0 0 10px 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Travel to the city outskirts.</p> <<link "<div style='background: #4a4a4a; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Outskirts</div>">> <<goto "Outskirts">> <</link>> </div> </div> <!-- Add after the travel grid, before closing div --> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "RedLightDistrict">> <<goto "CrimeHub">> <</link>> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("RedLightDistrict")>> <h2 style="color: #ff1493;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff1493; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The streets are quiet at the moment. No one is visible in this area. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Docks")>> <<run $visitedLocations.push("Docks")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "Docks">> <<if !setup.diving.QUESTLINES_DISABLED && $sunfishDayAccepted && !$queshaRecruitState.docks>> <div style="background: linear-gradient(135deg, #2a1f08 0%, #1a1408 100%); border: 2px solid #ffd700; border-radius: 10px; padding: 14px; margin: 10px 0;"> <h3 style="color: #ffd700; margin: 0 0 8px 0;">🌅 Sunfish Day: Lanterns and Boats</h3> <p style="color: #ddd; line-height: 1.5; margin: 0 0 10px 0;">Quesha asked you to find someone at the docks who could string lanterns along the boats.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask the dockworkers</div>">> <<goto "QueshaRecruitDocks">> <</link>> </div> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">⚓ Docks</h1> <!-- Location Image (Day/Night Cycle) --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <<set _timeOfDay = getTimeOfDay()>> <<if _timeOfDay === "morning">> <<set _locationImg = "Images/Locations/Docks.webp">> <<elseif _timeOfDay === "afternoon">> <<set _locationImg = "Images/Locations/DocksDay.webp">> <<else>> <<set _locationImg = "Images/Locations/DocksNight.webp">> <</if>> <div style="text-align: center; margin: 20px 0;"> <img @src="_locationImg" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #3498db; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Docks"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1e3a5f 0%, #2c5f8d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0;"> The salty tang of sea air fills your lungs as waves lap against weathered wooden piers. Massive cargo ships loom in the harbor, their hulls rusted and barnacle covered. This is a place of hard labor and harder people. </p> </div> <<if setup.questSystem && setup.questSystem.isQuestActive("island_supply_lines")>> <<set _slStep = $questData.active["island_supply_lines"].step>> <h2 style="color:#d98a3d;">Nothing Leaves This Shore</h2> <div style="border: 3px solid #d98a3d; border-radius: 10px; padding: 15px; background: #1c130b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <<if _slStep === "investigate">> <p style="font-size:14px; color:#f0cf95; margin:0 0 12px 0;">She wants you to learn where the island's supplies come from. Watch the cargo, get inside the warehouse if you can, and come back across more than one day.</p> <<set _canWarehouse = $jobs.includes("Dock Worker") || (Array.isArray($skills) && $skills.includes("Stealth")) || (setup.slime && setup.slime.isPlayerSlimeBodied())>> <<if _canWarehouse>> <<link "<div class='mikla-btn'>Slip into the warehouse</div>">> <<if setup.canCombineTap()>> <<if !Array.isArray($supplyWarehouseDays)>><<set $supplyWarehouseDays = []>><</if>> <<if !$supplyWarehouseDays.includes($dayNumber)>><<run $supplyWarehouseDays.push($dayNumber)>><</if>> <<goto "DockWarehouse">> <</if>> <</link>> <br><br> <<else>> <p style="font-size:12px; color:#b0895a; margin:0 0 12px 0; font-style:italic;">The warehouse doors are watched. You cannot get inside as you are. You would need work at the docks (the Dock Worker job), the Stealth skill to slip past, or a slime's shapeless body to seep through.</p> <</if>> <<link "<div class='mikla-btn'>Watch the cargo ships</div>">> <<if setup.canCombineTap()>> <<if $supplyShipDepartDay < 0>> <<set $supplyShipDepartDay = $dayNumber>> <<elseif $dayNumber >= $supplyShipDepartDay + 2 && !$supplyShipReturned>> <<set $supplyShipReturned = true>> <</if>> <<goto "SupplyHarborWatch">> <</if>> <</link>> <br><br> <<link "<div class='mikla-btn'>Ask a ship's captain about the far water</div>">> <<if setup.canCombineTap()>> <<set $supplyCaptainAsked = true>> <<goto "SupplyCaptainTalk">> <</if>> <</link>> <<elseif _slStep === "voyage">> <p style="font-size:14px; color:#f0cf95; margin:0 0 12px 0;">She wants you to take a vessel out to sea, as far as you can go, and see what the edge of the world does.</p> <<set _canBoat = $boat>> <<set _canSwim = Array.isArray($physicalTraits) && ($physicalTraits.includes("Siren") || $physicalTraits.includes("Naiad"))>> <<if _canBoat>> <<link "<div class='mikla-btn'>Set out to sea</div>">> <<if setup.canCombineTap()>> <<advancetime 720>> <<set $supplyVoyageCount += 1>> <<set $supplyVoyageDone = true>> <<goto "SupplyVoyage">> <</if>> <</link>> <<elseif _canSwim>> <<link "<div class='mikla-btn'>Swim out past the horizon</div>">> <<if setup.canCombineTap()>> <<advancetime 1440>> <<set $supplyVoyageCount += 1>> <<set $supplyVoyageDone = true>> <<goto "SupplyVoyage">> <</if>> <</link>> <<else>> <p style="font-size:12px; color:#b0895a; margin:0 0 12px 0; font-style:italic;">You cannot go out as you are. You would need a boat of your own (buy one from the fishing and gear dealer here at the docks), or the body of a Siren or Naiad to swim it yourself.</p> <</if>> <<if $supplyVoyageDone>> <p style="font-size:12px; color:#9a8f7a; margin:10px 0 0 0; font-style:italic;">You have seen what the sea does. She is waiting to hear of it, though you may go out again to be sure.</p> <</if>> <<else>> <p style="font-size:14px; color:#f0cf95; margin:0;">There is nothing more to do at the docks for now. Return to the searing pool of lava and tell her what you found.</p> <</if>> </div> <</if>> <!-- Check job availability --> <<set _alreadyHasDockJob = $jobs && $jobs.includes("Dock Worker")>> <<set _meetsRequirements = false>> <!-- Check strength requirement (10+) using effective strength (base + trait bonuses + TF multipliers) so traits like Muscular / Strong / Sturdy count toward the bar, not just the raw base stat. --> <<set _effectiveStr = (typeof setup.getTotalStat === "function") ? setup.getTotalStat("strength") : (($stats && $stats.strength) || 0)>> <<if _effectiveStr >= 10>> <<set _meetsRequirements = true>> <</if>> <!-- Check for qualifying physical traits --> <<if !_meetsRequirements && $physicalTraits>> <<set _qualifyingPhysicalTraits = ["Athletic Build", "Muscular", "Strong", "Sturdy"]>> <<for _trait range _qualifyingPhysicalTraits>> <<if $physicalTraits.includes(_trait)>> <<set _meetsRequirements = true>> <<break>> <</if>> <</for>> <</if>> <!-- Check for qualifying skills --> <<if !_meetsRequirements && $skills>> <<set _qualifyingSkills = ["Heavy Lifting", "Inventory Management", "Management", "Forklift Certified"]>> <<for _skill range _qualifyingSkills>> <<if $skills.includes(_skill)>> <<set _meetsRequirements = true>> <<break>> <</if>> <</for>> <</if>> <!-- Himbo transformation includes Heavy Lifting benefits --> <<if !_meetsRequirements && $physicalTraits && $physicalTraits.includes("Himbo")>> <<set _meetsRequirements = true>> <</if>> <<set _dockWorkerNPCs = setup.getNPCsByJob("Dock Worker")>> <<set _dockWorkerCount = _dockWorkerNPCs ? _dockWorkerNPCs.length : 0>> <<set _canHire = _dockWorkerCount < 8>> <!-- Dock Work Area (Only shows if player is a Dock Worker) --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Dock Worker">> <h2 style="color: #28a745;">Your Workplace</h2> <div style="margin-bottom: 25px;"> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 10px 0;">⚒️ Loading Bay</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Report for dock work. Work hours: 6 AM - 10 PM, max 8 hours per day.</p> <p style="font-size: 14px; color: #28a745; margin: 0 0 10px 0; font-weight: bold;">Pay: $23/hour</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Loading Bay</div>">> <<goto "UniversalWork">> <</link>> </div> </div> <</if>> <h2 style="color: #3498db;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to the Bus Stop</div>">> <<bustravel>> <<goto "BusStop">> <</link>> </div> <!-- Fishing & Gear Dealership --> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20c997; margin: 0 0 10px 0;">🎣 Fishing & Gear Dealership</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Buy boats, tackle, and fishing gear.</p> <<link "<div style='background: #20c997; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> <!-- Dock Fishing --> <div style="border: 3px solid #1a5276; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1a5276; margin: 0 0 10px 0;">🎣 Dock Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Cast your line from the docks.</p> <<link "<div style='background: #1a5276; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Fishing</div>">> <<goto "FishingDocks">> <</link>> </div> <!-- Ocean Fishing (requires boat) --> <<if $boat>> <div style="border: 3px solid #0077be; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #0077be; margin: 0 0 10px 0;">🚤 Ocean Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take your boat out to sea.</p> <<link "<div style='background: #0077be; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Ocean Fishing</div>">> <<goto "OceanFishing">> <</link>> </div> <<else>> <div style="border: 3px solid #555; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.6;"> <h3 style="color: #555; margin: 0 0 10px 0;">🚤 Ocean Fishing</h3> <p style="font-size: 14px; color: #666; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Requires a boat. Buy one at the Dealership.</p> <div style='background: #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; cursor: not-allowed; font-weight: bold; margin-top: 10px;'>No Boat</div> </div> <</if>> </div> <h2 style="color: #3498db;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">City center and hub.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel Downtown</div>">> <<travel>> <<goto "Downtown">> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Corporate towers and offices.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to the Business District</div>">> <<travel>> <<goto "BusinessDistrict">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Neon lit streets filled with nightlife and vice.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to the Red Light District </div>">> <<travel>> <<goto "RedLightDistrict">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the dark alley.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to the Alleyway</div>">> <<travel>> <<goto "Alleyway">> <</link>> </div> <!-- Beach --> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">🏖️ Beach</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Sandy shores and ocean waves.</p> <<link "<div style='background: #f4a460; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to the Beach</div>">> <<travel>> <<goto "Beach">> <</link>> </div> </div> <!-- Employment Section --> <h2 style="color: #3498db;">Employment</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Apply for Dock Worker Job --> <<if _alreadyHasDockJob>> <!-- Already working here --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">💼 Employment</h3> <p style="font-size: 14px; color: #51cf66; margin-bottom: 15px;">You're already employed here as a dock worker!</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Already Employed</div> </div> <<elseif !_meetsRequirements>> <!-- Doesn't meet requirements --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">💼 Apply for Dock Work</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">You don't meet the physical requirements for dock work.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif !_canHire>> <!-- Docks are fully staffed --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">💼 Apply for Dock Work</h3> <p style="font-size: 14px; color: #ff6b6b; margin-bottom: 10px;">The docks are fully staffed (<<print _dockWorkerCount>>/8 workers)</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <!-- Can apply for the job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Apply for Dock Work</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Join the loading crew!</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 6px;">Pay: $23/hour | Hours: 6 AM - 10 PM</p> <p style="font-size: 13px; color: #ffd43b; margin-bottom: 15px;">Requires: STR 10 — or Athletic Build / Muscular / Strong / Sturdy trait, or Heavy Lifting / Inventory Management / Management / Forklift Certified skill</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "DocksJobOffer">> <</link>> </div> <</if>> </div> <!-- Criminal Activities --> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "Docks">> <<goto "CrimeHub">> <</link>> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Docks")>> <h2 style="color: #3498db;">⚓ People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #3498db; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #5dade2; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic;"> Various people can be found working or passing through the docks... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #3498db; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #5dade2; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The docks are quiet right now. The workers must be on break. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit for achievements --> <<if !$visitedLocations>> <<set $visitedLocations = []>> <</if>> <<if !$visitedLocations.includes("BusStop")>> <<run $visitedLocations.push("BusStop")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffc107; text-align: center;">🚌 Bus Stop</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Bus.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Bus Stop"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #f39c12 0%, #f1c40f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffc107;"> <p style="color: white; font-size: 18px; margin: 0;"> A covered bus stop with benches and a digital display showing arrival times. People wait patiently, some checking their phones, others reading newspapers. </p> </div> <!-- Bus Pass Information --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffc107; margin: 0 0 15px 0;">🎫 Your Bus Pass Status</h2> <<if $busPassDaysRemaining && $busPassDaysRemaining > 0>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #28a745; margin-bottom: 15px;"> <p style="color: #28a745; margin: 0; text-align: center; font-size: 18px; font-weight: bold;"> ✅ Active 30-Day Pass </p> <p style="color: #aaa; margin: 10px 0 0 0; text-align: center;"> Days Remaining: <strong style="color: #51cf66;"><<print $busPassDaysRemaining>></strong> </p> </div> <<else>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #dc3545; margin-bottom: 15px;"> <p style="color: #dc3545; margin: 0; text-align: center; font-size: 18px; font-weight: bold;"> ❌ No Active Pass </p> <p style="color: #aaa; margin: 10px 0 0 0; text-align: center;"> You'll need to pay per ride or purchase a pass </p> </div> <</if>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; text-align: center;"> <strong>Your Money:</strong> <<print setup.formatMoney($money)>> </p> </div> </div> <!-- Purchase Options --> <h2 style="color: #ffc107;">Purchase Tickets</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Single Ride --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🎫 Single Ride</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0; line-height: 1.4;">One-way ticket to any destination.</p> <p style="font-size: 18px; color: #51cf66; margin: 0 0 auto 0; font-weight: bold; flex-grow: 1;">$5</p> <p style="font-size: 12px; color: #aaa; margin: 0 0 10px 0; font-style: italic;">Pay per ride</p> </div> <!-- 30-Day Pass --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">🎟️ 30-Day Pass</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0; line-height: 1.4;">Unlimited rides for 30 days.</p> <p style="font-size: 18px; color: #51cf66; margin: 0 0 5px 0; font-weight: bold;">$50</p> <p style="font-size: 12px; color: #aaa; margin: 0 0 auto 0; font-style: italic; flex-grow: 1;">Best value for frequent travelers!</p> <<if !$busPassDaysRemaining || $busPassDaysRemaining <= 0>> <<if $money >= 50>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Purchase Pass ($50)</div>">> <<set $money -= 50>> <<set $busPassDaysRemaining = 30>> <!-- Achievement for buying bus pass --> <<run setup.achievements.unlock("buy_bus_pass")>> <<goto "BusStop">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Enough Money</div> <</if>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Already Have Pass</div> <</if>> </div> </div> <!-- Bus Routes --> <h2 style="color: #ffc107;">Bus Routes</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">City center and hub.</p> <<set _isBusDriver = $jobs && $jobs.length > 0 && $jobs[0] === "Bus Driver">> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Downtown">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Downtown">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Corporate towers and offices.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "BusinessDistrict">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "BusinessDistrict">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Industrial waterfront district.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Docks">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Docks">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Beach --> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">🏖️ Beach</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Sandy shores and ocean waves.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #f4a460; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Beach">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #f4a460; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Beach">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Neon lit streets of nightlife.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "RedLightDistrict">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "RedLightDistrict">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the dark alley.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Alleyway">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Alleyway">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Outskirts --> <div style="border: 3px solid #4a4a4a; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #888; margin: 0 0 10px 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Rural areas outside the city.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #4a4a4a; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Outskirts">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #4a4a4a; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "Outskirts">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Commercial District --> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20c997; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Shops and services center.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #20c997; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "CommercialDistrict">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #20c997; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "CommercialDistrict">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Residential District --> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">🏘️ Residential District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Neighborhoods and homes.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "ResidentialDistrict">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "ResidentialDistrict">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Industrial District --> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #888; margin: 0 0 10px 0;">🏭 Industrial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Smokestacks and warehouses on the city's edge.</p> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #555; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "IndustrialOutskirts">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #555; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "IndustrialOutskirts">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <!-- Go Home (House takes priority over Apartment) --> <<if $ownsHouse && $houseLocation === "ResidentialMansions">> <div style="border: 3px solid #fd7e14; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #fd7e14; margin: 0 0 10px 0;">🏰 Go Home</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take the bus to your mansion.</p> <<set _isBusDriver = $jobs && $jobs.length > 0 && $jobs[0] === "Bus Driver">> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #fd7e14; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "PlayerModernMansion">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #fd7e14; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "PlayerModernMansion">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <<elseif $ownsHouse && $houseLocation === "ResidentialExpensiveHomes">> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🏡 Go Home</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take the bus to your luxury home.</p> <<set _isBusDriver = $jobs && $jobs.length > 0 && $jobs[0] === "Bus Driver">> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "PlayerExpensiveHome">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "PlayerExpensiveHome">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <<elseif $ownsHouse>> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏡 Go Home</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take the bus to your house.</p> <<set _isBusDriver = $jobs && $jobs.length > 0 && $jobs[0] === "Bus Driver">> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "PlayerSuburbanHome">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "PlayerSuburbanHome">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <<elseif $hasApartment>> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏠 Go Home</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take the bus to your apartment.</p> <<set _isBusDriver = $jobs && $jobs.length > 0 && $jobs[0] === "Bus Driver">> <<if ($busPassDaysRemaining && $busPassDaysRemaining > 0) || _isBusDriver>> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - Free</div>">> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "StudioApartment">> <</link>> <<elseif $money >= 5>> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take Bus (3 min) - $5</div>">> <<set $money -= 5>> <<bustravel>> <<set $skipTimeAdvancement = true>> <<goto "StudioApartment">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Need $5 or Pass</div> <</if>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🏠 Go Home</h3> <p style="font-size: 14px; color: #666; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">You don't have a home to go to.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>No Home</div> </div> <</if>> <!-- Bus Driver Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Bus Driver")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🚌 Apply: Bus Driver</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Bus Driver")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🚌 Apply: Bus Driver</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">🚌 Apply: Bus Driver</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $15/hour</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "BusDriverJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Bus Driver Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Bus Driver">> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">🚌 Bus Driver Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Clock in for your driving shift. Choose a route and hit the road! (Max 8 hours/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Work Shift</div>">> <<goto "BusDriverWork">> <</link>> </div> <</if>> <!-- NPC Interaction - Bus Driver (schedule-aware) --> <<set _npcsHere = setup.getNPCsAtLocation("BusStop")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="color: #ffc107; margin-top: 30px;">Bus Driver</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 15px 0; line-height: 1.4;"> <<print _npc.jobs.join(", ")>> </p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> <</if>> </div> <!-- Walk Option --> <div style="text-align: center; margin-top: 30px;"> <p style="color: #aaa; font-size: 14px; margin-bottom: 10px;">Or you can walk for free (takes longer)</p> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Go back</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> /* Criminal Heat-Based Arrest Check */ <<if $jobs && $jobs.includes("Criminal")>> <<if !$heat>> <<set $heat = 0>> <</if>> /* Calculate arrest chance: 1% at 0 heat, 90% at 100 heat */ <<set _arrestChance = 1 + ($heat * 0.89)>> <<set _arrestRoll = random(1, 100)>> <<if _arrestRoll <= _arrestChance>> <<goto "CaughtByPolice">> <</if>> <</if>> <<if !setup.isMallOpen()>> <<goto "MallClosed">> <</if>> <<set $lastLocation = "Mall">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Mall")>> <<run $visitedLocations.push("Mall")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">🛍️ Sunfish City Mall</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> A sprawling shopping complex filled with stores, restaurants, and people. The air conditioning is a welcome relief from the outside heat. </p> </div> <h2 style="color: #9b59b6;">Mall Directory</h2> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Fitness Shop --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">💪 Barracuda Fitness</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Workout equipment, supplements, and athletic wear.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Shop</div>">> <<goto "FitnessShop">> <</link>> </div> <!-- Ecentric Shop --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🌙 Lionfish Boutique</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Alternative fashion, dark clothing, and unique accessories.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Shop</div>">> <<goto "EcentricShop">> <</link>> </div> <!-- Beauty Salon --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💄 Angelfish Beauty Salon</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Hair styling, makeup, and beauty services.</p> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Salon</div>">> <<goto "BeautySalon">> <</link>> </div> <!-- Tech Store --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💻 Hammerhead Tech</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Electronics, computers, and technical support.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Store</div>">> <<goto "TechStore">> <</link>> </div> <!-- Adult Store --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🔞 Stingray Adult Emporium</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Adult products and toys. 18+ only.</p> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Store</div>">> <<goto "AdultStore">> <</link>> </div> <!-- Bakery --> <div style="border: 3px solid #d2691e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #d2691e; margin: 0 0 10px 0;">🥐 Seahorse Bakery</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Fresh baked goods, pastries, and bread.</p> <<link "<div style='background: #d2691e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bakery</div>">> <<goto "Bakery">> <</link>> </div> </div> <br> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #9b59b6; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Go to Floor 2 ⬆️</div>">> <<goto "MallFloor2">> <</link>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Mall</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Mall")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="color: #9b59b6; margin-top: 30px;">🛍️ People at the Mall</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 20px 0;">Some people are shopping at the mall.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <</if>> <!-- Add after the floor navigation, before NPCs section --> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "Mall">> <<goto "CrimeHub">> <</link>> <</if>> </div> </div> <</nobr>>
:: ImageManager <<nobr>><style>.image-manager{padding:20px;background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);min-height:100vh}.manager-container{max-width:1400px;margin:0 auto;background:white;border-radius:15px;padding:30px;box-shadow:0 10px 40px rgba(0,0,0,0.3)}.manager-title{text-align:center;color:#667eea;font-size:2.5em;margin-bottom:30px}.section-tabs{display:flex;gap:10px;margin-bottom:30px;border-bottom:3px solid #e9ecef;flex-wrap:wrap}.tab-button{padding:15px 30px;border:none;background:#f8f9fa;cursor:pointer;font-size:16px;font-weight:600;border-radius:10px 10px 0 0;transition:all 0.3s}.tab-button:hover{background:#e9ecef}.tab-button.active{background:#667eea;color:white}.tab-content{display:none}.tab-content.active{display:block}.skin-tone-filter{display:flex;gap:10px;margin-bottom:20px;padding:15px;background:#f8f9fa;border-radius:10px;flex-wrap:wrap}.tone-button{padding:10px 20px;border:2px solid #dee2e6;background:white;cursor:pointer;font-weight:600;border-radius:5px;transition:all 0.3s}.tone-button:hover{border-color:#667eea}.tone-button.active{background:#667eea;color:white;border-color:#667eea}.image-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:20px;margin-top:20px}.image-card{border:2px solid #dee2e6;border-radius:10px;padding:15px;background:#f8f9fa;transition:all 0.3s}.image-card:hover{border-color:#667eea;box-shadow:0 5px 15px rgba(102,126,234,0.2)}.image-card h3{color:#667eea;margin-bottom:10px;font-size:14px;text-transform:capitalize}.image-preview{width:100%;height:180px;background:#e9ecef;border-radius:8px;margin-bottom:10px;display:flex;align-items:center;justify-content:center;overflow:hidden}.image-preview img{max-width:100%;max-height:100%;object-fit:contain}.image-preview.empty{color:#999;font-style:italic;font-size:12px}.url-input{width:100%;padding:8px;border:2px solid #dee2e6;border-radius:5px;font-size:12px;margin-bottom:8px}.url-input:focus{outline:none;border-color:#667eea}.btn-group{display:flex;gap:5px}.btn{flex:1;padding:8px;border:none;border-radius:5px;cursor:pointer;font-weight:600;font-size:11px;transition:all 0.3s}.btn-save{background:#28a745;color:white}.btn-save:hover{background:#218838}.btn-clear{background:#dc3545;color:white}.btn-clear:hover{background:#c82333}.btn-test{background:#17a2b8;color:white}.btn-test:hover{background:#138496}.back-link{display:inline-block;margin-top:30px;padding:15px 30px;background:#6c757d;color:white;text-decoration:none;border-radius:8px;font-weight:600;transition:all 0.3s}.back-link:hover{background:#5a6268;transform:translateY(-2px)}.export-section{margin-top:30px;padding:20px;background:#f8f9fa;border-radius:10px;border:2px solid #667eea}.export-section h3{color:#667eea;margin-bottom:15px}.code-output{background:#2d2d2d;color:#00ff00;padding:15px;border-radius:5px;font-family:'Courier New',monospace;font-size:11px;max-height:300px;overflow-y:auto;white-space:pre-wrap;word-wrap:break-word}.filename-hint{font-size:11px;color:#6c757d;font-style:italic;margin-bottom:5px}</style><div class="image-manager"><div class="manager-container"><h1 class="manager-title">🖼️ Body Part Image Manager</h1><div class="section-tabs"><button class="tab-button active" onclick="switchTab('chest')">Chest Sizes</button><button class="tab-button" onclick="switchTab('butt')">Butt Sizes</button><button class="tab-button" onclick="switchTab('face')">Face Images</button></div><div id="chest-tab" class="tab-content active"><h2>Chest Size Images</h2><div class="skin-tone-filter"><span style="font-weight:600;margin-right:10px;">Skin Tone:</span><button class="tone-button active" onclick="filterByTone('chest','bronzed')">Bronzed</button><button class="tone-button" onclick="filterByTone('chest','pale')">Pale</button><button class="tone-button" onclick="filterByTone('chest','dark')">Dark</button></div><div class="image-grid" id="chest-grid"></div></div><div id="butt-tab" class="tab-content"><h2>Butt Size Images</h2><div class="skin-tone-filter"><span style="font-weight:600;margin-right:10px;">Skin Tone:</span><button class="tone-button active" onclick="filterByTone('butt','bronzed')">Bronzed</button><button class="tone-button" onclick="filterByTone('butt','pale')">Pale</button><button class="tone-button" onclick="filterByTone('butt','dark')">Dark</button></div><div class="image-grid" id="butt-grid"></div></div><div id="face-tab" class="tab-content"><h2>Face Images</h2><div class="skin-tone-filter"><span style="font-weight:600;margin-right:10px;">Hair Color:</span><button class="tone-button active" onclick="filterFaceByHair('Black')">Black</button><button class="tone-button" onclick="filterFaceByHair('Brown')">Brown</button><button class="tone-button" onclick="filterFaceByHair('Blonde')">Blonde</button><button class="tone-button" onclick="filterFaceByHair('Red')">Red</button><button class="tone-button" onclick="filterFaceByHair('PlatinumBlonde')">Platinum Blonde</button></div><div class="image-grid" id="face-grid"></div></div><div class="export-section"><h3>📋 Export Image Data</h3><p style="margin-bottom:10px;">Copy this code and paste it into your StoryInit to save your image assignments:</p><div class="code-output" id="export-output"></div><button class="btn btn-test" onclick="copyExportCode()" style="margin-top:10px;width:auto;">Copy to Clipboard</button></div><a href="javascript:void(0)" class="back-link" onclick="Engine.backward()">← Back to Game</a></div></div><script>const bodyPartSizes={chest:["flat masculine","flat","small","medium","big","huge","gigantic"],butt:["flat masculine","flat","small","medium","big","huge","gigantic"]},skinTones=["bronzed","pale","dark"],hairColors=['Black','Brown','Blonde','Red','PlatinumBlonde'],hairStyles=['styled','messy'];let currentTone={chest:"bronzed",butt:"bronzed"},currentFaceHair='Black';function switchTab(t){document.querySelectorAll(".tab-content").forEach(t=>{t.classList.remove("active")}),document.querySelectorAll(".tab-button").forEach(t=>{t.classList.remove("active")}),document.getElementById(t+"-tab").classList.add("active"),event.target.classList.add("active")}function filterByTone(t,e){currentTone[t]=e;const n=document.querySelectorAll(`#${t}-tab .tone-button`);n.forEach(t=>t.classList.remove("active")),event.target.classList.add("active");const a=document.getElementById(`${t}-grid`);a.innerHTML="",bodyPartSizes[t].forEach(n=>{a.appendChild(createImageCard(t,n,e))})}function filterFaceByHair(t){currentFaceHair=t;const e=document.querySelectorAll('#face-tab .tone-button');e.forEach(btn=>btn.classList.remove('active')),event.target.classList.add('active');const n=document.getElementById('face-grid');n.innerHTML='';const genders=['female','male'],maturities=[false,true];maturities.forEach(mature=>{hairStyles.forEach(style=>{skinTones.forEach(tone=>{genders.forEach(gender=>{n.appendChild(createFaceCard(t,style,tone,gender,mature))})})})})}function getFilenameSuggestion(t,e,n){let a=e.replace(/\s+/g,"").toLowerCase();return a=a.replace("masculine",""),`${a}${n}${t}`}function createImageCard(t,e,n){const a=document.createElement("div");a.className="image-card";const s=document.createElement("h3");s.textContent=`${e} - ${n}`,a.appendChild(s);const r=document.createElement("div");r.className="filename-hint";const o=getFilenameSuggestion(t,e,n);r.textContent=`Suggested: ${o}.webp`,a.appendChild(r);const c=document.createElement("div");c.className="image-preview",c.id=`preview-${t}-${e.replace(/\s+/g,"_")}-${n}`;const i=`${e}_${n}`,l=setup.bodyPartImages[t][i]||"";if(l){const t=document.createElement("img");t.src=l,c.appendChild(t)}else c.classList.add("empty"),c.textContent="No image";a.appendChild(c);const d=document.createElement("input");d.type="text",d.className="url-input",d.placeholder="Enter image URL...",d.value=l,d.id=`input-${t}-${e.replace(/\s+/g,"_")}-${n}`,a.appendChild(d);const u=document.createElement("div");u.className="btn-group";const m=document.createElement("button");m.className="btn btn-save",m.textContent="Save",m.onclick=()=>saveImage(t,e,n),u.appendChild(m);const g=document.createElement("button");g.className="btn btn-clear",g.textContent="Clear",g.onclick=()=>clearImage(t,e,n),u.appendChild(g);const p=document.createElement("button");return p.className="btn btn-test",p.textContent="Test",p.onclick=()=>testImage(t,e,n),u.appendChild(p),a.appendChild(u),a}function createFaceCard(hairColor,hairStyle,skinTone,gender,isMature){const card=document.createElement('div');card.className='image-card';const maturePrefix=isMature?'m':'';const title=document.createElement('h3');title.textContent=`${isMature?'Mature ':''}${hairColor} - ${hairStyle} - ${skinTone} - ${gender}`;card.appendChild(title);const hint=document.createElement('div');hint.className='filename-hint';hint.style.color='#28a745';hint.style.fontWeight='bold';hint.textContent=`File Path: Images/Face/${maturePrefix}${hairColor.toLowerCase()}_${hairStyle}_${skinTone}_${gender}.webp`;card.appendChild(hint);const preview=document.createElement('div');preview.className='image-preview';preview.id=`preview-face-${maturePrefix}${hairColor}_${hairStyle}_${skinTone}_${gender}`;const filePath=`Images/Face/${maturePrefix}${hairColor.toLowerCase()}_${hairStyle}_${skinTone}_${gender}.webp`;const img=document.createElement('img');img.src=filePath;img.onerror=function(){preview.innerHTML='';preview.classList.add('empty');preview.textContent='No image found'};img.onload=function(){preview.classList.remove('empty')};preview.appendChild(img);card.appendChild(preview);const infoText=document.createElement('div');infoText.style.fontSize='11px';infoText.style.color='#6c757d';infoText.style.marginTop='10px';infoText.style.fontStyle='italic';infoText.textContent='Face images load automatically from Images/Face/ folder';card.appendChild(infoText);return card}function saveImage(t,e,n){const a=document.getElementById(`input-${t}-${e.replace(/\s+/g,"_")}-${n}`).value.trim(),s=`${e}_${n}`;setup.bodyPartImages[t][s]=a,updatePreview(t,e,n,a),updateExportCode();const r=event.target,o=r.textContent;r.textContent="✓ Saved!",r.style.background="#218838",setTimeout(()=>{r.textContent=o,r.style.background=""},1500)}function clearImage(t,e,n){document.getElementById(`input-${t}-${e.replace(/\s+/g,"_")}-${n}`).value="";const a=`${e}_${n}`;setup.bodyPartImages[t][a]="",updatePreview(t,e,n,""),updateExportCode()}function testImage(t,e,n){const a=document.getElementById(`input-${t}-${e.replace(/\s+/g,"_")}-${n}`).value.trim();a?updatePreview(t,e,n,a):alert("Please enter a URL first")}function updatePreview(t,e,n,a){const s=document.getElementById(`preview-${t}-${e.replace(/\s+/g,"_")}-${n}`);if(s.innerHTML="",a){s.classList.remove("empty");const t=document.createElement("img");t.src=a,t.onerror=()=>{s.innerHTML="",s.classList.add("empty"),s.textContent="❌ Invalid URL"},s.appendChild(t)}else s.classList.add("empty"),s.textContent="No image"}function updateExportCode(){const t=`setup.bodyPartImages = ${JSON.stringify(setup.bodyPartImages,null,2).replace(/"([^"]+)":/g,"$1:")};`;document.getElementById("export-output").textContent=t}function copyExportCode(){const t=document.getElementById("export-output").textContent;navigator.clipboard.writeText(t).then(()=>{const t=event.target,e=t.textContent;t.textContent="✓ Copied!",setTimeout(()=>{t.textContent=e},2e3)})}function initializeGrids(){const t=document.getElementById("chest-grid");bodyPartSizes.chest.forEach(e=>{t.appendChild(createImageCard("chest",e,"bronzed"))});const e=document.getElementById("butt-grid");bodyPartSizes.butt.forEach(t=>{e.appendChild(createImageCard("butt",t,"bronzed"))});const n=document.getElementById('face-grid'),genders=['female','male'],maturities=[false,true];maturities.forEach(mature=>{hairStyles.forEach(style=>{skinTones.forEach(tone=>{genders.forEach(gender=>{n.appendChild(createFaceCard('Black',style,tone,gender,mature))})})})}),updateExportCode()}initializeGrids();</script><</nobr>>
<<nobr>> <<set $lastLocation = "FitnessShop">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("FitnessShop")>> <<run $visitedLocations.push("FitnessShop")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e74c3c; text-align: center;">💪 Barracuda Fitness</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e74c3c;"> <p style="color: white; font-size: 18px; margin: 0;"> A sleek fitness equipment store with weights, yoga mats, and protein supplements lining the shelves. The smell of rubber and determination fills the air. </p> </div> <h2 style="color: #e74c3c;">🥤 Drinks (Gift or Drink)</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _fitnessGifts = [ {id: "energy_drink_gift", name: "Energy Drink", price: 3, icon: "⚡", desc: "A can of electrifying energy", buffId: "vending_energy", buffDuration: 360}, {id: "protein_shake_gift", name: "Protein Shake", price: 5, icon: "💪", desc: "A thick, nutritious protein shake", buffId: "vending_protein", buffDuration: 480}, {id: "smoothie", name: "Smoothie", price: 8, icon: "🥤", desc: "A fresh tropical fruit smoothie", buffId: "vending_refresh", buffDuration: 240} ]>> <<for _item range _fitnessGifts>> <<capture _item>> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; border: 2px solid #e74c3c; display: flex; justify-content: space-between; align-items: center; gap: 10px;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #e74c3c; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> </div> <div style="display: flex; gap: 8px;"> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #4dabf7; color: white; padding: 8px 14px; border-radius: 6px; font-weight: bold;'>🥤 Buy to Drink</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$foodInventory>><<set $foodInventory = []>><</if>> <<run $foodInventory.push({name: _item.name, buffId: _item.buffId, buffDuration: _item.buffDuration, cookedTime: $timeInMinutes || 0})>> <<goto "FitnessShop">> <</link>> <<link "<span style='background: #e74c3c; color: white; padding: 8px 14px; border-radius: 6px; font-weight: bold;'>🎁 Buy as Gift</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<goto "FitnessShop">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> </div> <</capture>> <</for>> </div> <h2 style="color: #e74c3c;">Services</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Back to Mall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Return to the mall directory.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Shop</div>">> <<goto "Mall">> <</link>> </div> <!-- Work Area (Only shows if player has the job) --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Fitness Shop Clerk">> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Work Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Clock in for your shift. (Work hours: 9 AM - 6 PM, max 8 hours/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work Shift</div>">> <<goto "UniversalWork">> <</link>> </div> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("FitnessShop")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="margin-top: 30px; color: #e74c3c;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e74c3c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="margin-top: 30px; color: #e74c3c;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The shop is quiet right now. No one is working here. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BeautySalon">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("BeautySalon")>> <<run $visitedLocations.push("BeautySalon")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💇 Angelfish Beauty Salon</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A pristine salon with mirrors lining the walls, styling chairs, and the pleasant scent of hair products. Soft music plays as stylists work their magic. </p> </div> <!-- Check job availability --> <<set _alreadyHasStylistJob = $jobs && $jobs.includes("Beauty Salon Stylist")>> <<set _hasHairStylingSkill = $skills && $skills.includes("Hair Styling")>> <<set _stylistNPCs = setup.getNPCsByJob("Beauty Salon Stylist")>> <<set _stylistCount = _stylistNPCs ? _stylistNPCs.length : 0>> <<set _canHire = _stylistCount < 5>> <!-- Hair Styling Service --> <h2 style="color: #e91e63;">Services</h2> <<set _hasEmployedStylist = false>> <<set _npcsHere = setup.getNPCsByJob("Beauty Salon Stylist")>> <<if _npcsHere && _npcsHere.length > 0>> <<for _npc range _npcsHere>> <<if setup.isNPCAvailable(_npc.name)>> <<set _hasEmployedStylist = true>> <<break>> <</if>> <</for>> <</if>> <<set _playerIsEmployee = $jobs && $jobs.length > 0 && $jobs[0] === "Beauty Salon Stylist">> <<set _stylingCost = _playerIsEmployee ? 0 : 50>> <<set _haircutCost = _playerIsEmployee ? 0 : 50>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- Hair Styling --> <<if _hasEmployedStylist>> <<if $appearance.hairStyle === "messy">> <<set _canAffordStyling = _stylingCost === 0 || setup.canAffordTotal(_stylingCost)>> <<if !_canAffordStyling>> <!-- Can't afford --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">✨ Style Hair</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Get your hair professionally styled.</p> <p style="font-size: 14px; color: #dc3545; margin-bottom: 15px;">Cost: $<<print _stylingCost>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Enough Money</div> </div> <<else>> <!-- Can afford or free --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">✨ Style Hair</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Get your hair professionally styled.</p> <<if _stylingCost > 0>> <p style="font-size: 14px; color: #ffc107; margin-bottom: 15px;">Cost: $<<print _stylingCost>></p> <<else>> <p style="font-size: 14px; color: #51cf66; margin-bottom: 15px;">Employee Discount: FREE</p> <</if>> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Style Hair</div>">> <<if _stylingCost > 0>> <<set _payment = setup.payAmount(_stylingCost)>> <</if>> <<set $appearance.hairStyle = "styled">> <<run setup.achievements.unlock("style_hair")>> <<goto "BeautySalon">> <</link>> </div> <</if>> <<else>> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">✨ Style Hair</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Your hair is already styled!</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Already Styled</div> </div> <</if>> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">✨ Style Hair</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">No stylist available.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Unavailable</div> </div> <</if>> <!-- Hair Cut Service (Long to Short) --> <<if _hasEmployedStylist>> <<set _hasLongHair = false>> <<if $physicalTraits && $physicalTraits.length > 0>> <<for _i to 0; _i lt $physicalTraits.length; _i++>> <<if $physicalTraits[_i] === "Long Hair">> <<set _hasLongHair = true>> <<break>> <</if>> <</for>> <</if>> <<if _hasLongHair>> <<set _canAffordHaircut = _haircutCost === 0 || setup.canAffordTotal(_haircutCost)>> <<if !_canAffordHaircut>> <!-- Can't afford --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">✂️ Cut Hair</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Get your hair cut short.</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 10px;">Changes: Long Hair → Short Hair</p> <p style="font-size: 14px; color: #dc3545; margin-bottom: 15px;">Cost: $<<print _haircutCost>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Enough Money</div> </div> <<else>> <!-- Can afford or free --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">✂️ Cut Hair</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Get your hair cut short.</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 10px;">Changes: Long Hair → Short Hair</p> <<if _haircutCost > 0>> <p style="font-size: 14px; color: #ffc107; margin-bottom: 15px;">Cost: $<<print _haircutCost>></p> <<else>> <p style="font-size: 14px; color: #51cf66; margin-bottom: 15px;">Employee Discount: FREE</p> <</if>> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Cut Hair Short</div>">> <<if _haircutCost > 0>> <<set _payment = setup.payAmount(_haircutCost)>> <</if>> <<set $appearance.hairLength = "short">> <<for _i to 0; _i lt $physicalTraits.length; _i++>> <<if $physicalTraits[_i] === "Long Hair">> <<set $physicalTraits.deleteAt(_i)>> <<break>> <</if>> <</for>> <<if !$physicalTraits.includes("Short Hair")>> <<set $physicalTraits.push("Short Hair")>> <</if>> <<goto "BeautySalon">> <</link>> </div> <</if>> <<else>> <!-- Already has short hair --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">✂️ Cut Hair</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">You don't have long hair to cut.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Available</div> </div> <</if>> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">✂️ Cut Hair</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">No stylist available.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Unavailable</div> </div> <</if>> <!-- Permanent Hair Dye --> <<if $physicalTraits && $physicalTraits.indexOf("Oni") !== -1>> <div style="border: 3px solid #cccccc; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.85;"> <h3 style="color: #cccccc; margin: 0 0 10px 0;">🎨 Permanent Hair Dye</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0;">Your silver Oni hair resists the dye. Whatever color the stylist works in fades before the rinse is done, the silver bleeding back through every strand.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Locked by Oni Form</div> </div> <<elseif $possessionActive>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.85;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🎨 Permanent Hair Dye</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0;">The Sunfish Cuff is on. Anything the stylist puts in your hair lands on Roisin, not you. Come back when you are yourself.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Locked by Possession</div> </div> <<elseif _hasEmployedStylist>> <<set _dyeCost = _playerIsEmployee ? 0 : 100>> <<set _canAffordDye = _dyeCost === 0 || setup.canAffordTotal(_dyeCost)>> <<set _curColor = ($appearance && $appearance.hairColor) ? $appearance.hairColor : "Black">> <<set _dyeColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]>> <div style="border: 3px solid #a855f7; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #a855f7; margin: 0 0 10px 0;">🎨 Permanent Hair Dye</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 6px 0;">Change your hair color to one of the salon's standard shades. The dye lasts.</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Current color: <strong style="color: #eee;">$appearance.hairColor</strong></p> <<if _dyeCost > 0>> <p style="font-size: 14px; color: #ffc107; margin: 0 0 12px 0;">Cost: $<<print _dyeCost>></p> <<else>> <p style="font-size: 14px; color: #51cf66; margin: 0 0 12px 0;">Employee Discount: FREE</p> <</if>> <<if !_canAffordDye>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Enough Money</div> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(110px, 1fr)); gap: 6px;"> <<for _dc range _dyeColors>> <<capture _dc>> <<if _curColor === _dc>> <div style="background: #1a1a1a; color: #51cf66; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; border: 1px solid #51cf66; opacity: 0.75; font-size: 13px;">_dc (current)</div> <<else>> <<link "<div style='background: #a855f7; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>_dc</div>">> <<if _dyeCost > 0>><<set _payment = setup.payAmount(_dyeCost)>><</if>> <<set $appearance.hairColor = _dc>> <<goto "BeautySalon">> <</link>> <</if>> <</capture>> <</for>> </div> <</if>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🎨 Permanent Hair Dye</h3> <p style="font-size: 14px; color: #666; margin: 0 0 10px 0;">No stylist available.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Unavailable</div> </div> <</if>> <!-- Apply for Job --> <<if _alreadyHasStylistJob>> <!-- Already working here --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">💼 Employment</h3> <p style="font-size: 14px; color: #51cf66; margin-bottom: 15px;">You're already employed here as a stylist!</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Already Employed</div> </div> <<elseif !_hasHairStylingSkill>> <!-- Doesn't have the skill --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">💼 Apply for Job</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">Requires: Hair Styling skill</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif !_canHire>> <!-- Salon is fully staffed --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">💼 Apply for Job</h3> <p style="font-size: 14px; color: #ff6b6b; margin-bottom: 10px;">The salon is fully staffed (<<print _stylistCount>>/5 stylists)</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <!-- Can apply for the job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Apply for Job</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Join the salon as a stylist!</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 6px;">Pay: $18/hour | Hours: 9 AM - 6 PM</p> <p style="font-size: 13px; color: #ffd43b; margin-bottom: 15px;">Requires: Hair Styling skill</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "BeautySalonJobOffer">> <</link>> </div> <</if>> <!-- Back to Mall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; margin-bottom: 15px;">Return to the mall directory.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Leave Salon</div>">> <<goto "Mall">> <</link>> </div> <!-- Work Area (Only shows if player has the job) --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Beauty Salon Stylist">> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Work Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Clock in for your shift. (Work hours: 9 AM - 6 PM, max 8 hours/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work Shift</div>">> <<goto "UniversalWork">> <</link>> </div> <</if>> </div> <!-- NPCs Section --> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="margin-top: 30px; color: #e91e63;">Stylists Working</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="margin-top: 30px; color: #e91e63;">Stylists Working</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The salon is quiet right now. No one is working here. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "EcentricShop">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("EcentricShop")>> <<run $visitedLocations.push("EcentricShop")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">🌙 Lionfish Boutique</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #6a1b9a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> A dark, mysterious shop filled with gothic clothing, occult items, and alternative fashion. Incense smoke curls through the air as dark music plays softly. </p> </div> <h2 style="color: #9b59b6;">🎁 Trinkets & Oddities for Sale</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _eccentricGifts = [ {id: "trinket_charm", name: "Lucky Charm", price: 5, icon: "🔮", desc: "A mysterious charm said to bring good fortune"}, {id: "trinket_oddity", name: "Curious Oddity", price: 12, icon: "🗿", desc: "A strange object with an unknown purpose"}, {id: "trinket_relic", name: "Ancient Relic", price: 20, icon: "⚱️", desc: "An artifact from an era long forgotten"} ]>> <<for _item range _eccentricGifts>> <<capture _item>> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; border: 2px solid #9b59b6; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #9b59b6; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> </div> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #9b59b6; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<goto "EcentricShop">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <</capture>> <</for>> </div> <h2 style="color: #9b59b6;">Services</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Back to Mall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Return to the mall directory.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Shop</div>">> <<goto "Mall">> <</link>> </div> <!-- Work Area (Only shows if player has the job) --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Ecentric Shop Worker">> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Work Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Clock in for your shift. (Work hours: 9 AM - 6 PM, max 8 hours/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work Shift</div>">> <<goto "UniversalWork">> <</link>> </div> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("EcentricShop")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="margin-top: 30px; color: #9b59b6;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="margin-top: 30px; color: #9b59b6;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The shop is quiet right now. No one is working here. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "AdultStore">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("AdultStore")>> <<run $visitedLocations.push("AdultStore")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">🔞 Stingray Adult Emporium</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b6b 0%, #d63031 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: white; font-size: 18px; margin: 0;"> A discreet shop with tinted windows, offering adult toys, lingerie, and other intimate products. The atmosphere is mature but welcoming. </p> </div> <!-- Shop Inventory --> <h2 style="color: #ff6b6b;">Shop Inventory</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- Dildo --> <<set _canAffordDildo = setup.canAffordTotal(45)>> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🍆 Dildo</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;"> A realistic silicone toy. Available in various sizes and colors. Perfect for solo play. </p> <div style="color: #4ade80; font-weight: bold; font-size: 18px; margin: 10px 0;">$45</div> <<if $ownsDildo>> <div style="background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Owned</div> <<elseif _canAffordDildo>> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Purchase ($45)</div>">> <<set _payment = setup.payAmount(45)>> <<if _payment.success>> <<set $ownsDildo = true>> <</if>> <<goto "AdultStore">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Not Enough Money</div> <</if>> </div> <!-- Fleshlight --> <<set _canAffordFleshlight = setup.canAffordTotal(50)>> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🔦 Fleshlight</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;"> A discreet sleeve toy designed for men. Soft, realistic material with various textures available. </p> <div style="color: #4ade80; font-weight: bold; font-size: 18px; margin: 10px 0;">$50</div> <<if $ownsFleshlight>> <div style="background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Owned</div> <<elseif _canAffordFleshlight>> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Purchase ($50)</div>">> <<set _payment = setup.payAmount(50)>> <<if _payment.success>> <<set $ownsFleshlight = true>> <</if>> <<goto "AdultStore">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Not Enough Money</div> <</if>> </div> </div> <h2 style="color: #ff6b6b;">Services</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Back to Mall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Return to the mall directory.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Store</div>">> <<goto "Mall">> <</link>> </div> <!-- Work Area (Only shows if player has the job) --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Adult Store Clerk">> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Work Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Clock in for your shift. (Work hours: 9 AM - 6 PM, max 8 hours/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work Shift</div>">> <<goto "UniversalWork">> <</link>> </div> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("AdultStore")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="margin-top: 30px; color: #ff6b6b;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="margin-top: 30px; color: #ff6b6b;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The store is quiet right now. No one is working here. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Bakery">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Bakery")>> <<run $visitedLocations.push("Bakery")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #d2691e; text-align: center;">🥐 Seahorse Bakery</h1> <div style="padding: 20px; background: linear-gradient(135deg, #d2691e 0%, #a0522d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #d2691e;"> <p style="color: white; font-size: 18px; margin: 0;"> The warm, inviting scent of fresh bread and pastries fills the air. Display cases showcase croissants, cakes, and artisan loaves. </p> </div> <!-- Donuts Deliverer Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Donuts Deliverer")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🍩 Apply: Donuts Deliverer</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Donuts Deliverer")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🍩 Apply: Donuts Deliverer</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #d2691e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #d2691e; margin: 0 0 10px 0;">🍩 Apply: Donuts Deliverer</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $12/hour</p> <<link "<div style='background: #d2691e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "DonutsDelivererJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Donuts Deliverer Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Donuts Deliverer">> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">🍩 Donut Delivery Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Pick up a fresh batch and deliver across the city! Keep them hot for better tips. (Max 8 hrs/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Delivery Shift</div>">> <<goto "DonutsDelivererWork">> <</link>> </div> <</if>> <h2 style="color: #d2691e;">🎁 Gifts for Sale</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _bakeryGifts = [ {id: "fresh_bread", name: "Fresh Bread", price: 4, icon: "🍞", desc: "A warm loaf of fresh-baked bread"}, {id: "pastries", name: "Pastries", price: 5, icon: "🥐", desc: "Assorted flaky pastries"}, {id: "cake_slice", name: "Cake Slice", price: 8, icon: "🍰", desc: "A decadent slice of layered cake"} ]>> <<for _item range _bakeryGifts>> <<capture _item>> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; border: 2px solid #d2691e; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #d2691e; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> </div> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #d2691e; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<goto "Bakery">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <</capture>> <</for>> </div> <h2 style="color: #d2691e;">Services</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Back to Mall --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Return to the mall directory.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Bakery</div>">> <<goto "Mall">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Bakery")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="margin-top: 30px; color: #d2691e;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #d2691e; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #d2691e; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #d2691e; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #d2691e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="margin-top: 30px; color: #d2691e;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The bakery is quiet right now. No one is working here. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "TechStore">> <<if !setup.diving.QUESTLINES_DISABLED && $sunfishDayAccepted && !$queshaRecruitState.techStore>> <div style="background: linear-gradient(135deg, #2a1f08 0%, #1a1408 100%); border: 2px solid #ffd700; border-radius: 10px; padding: 14px; margin: 10px 0;"> <h3 style="color: #ffd700; margin: 0 0 8px 0;">🌅 Sunfish Day: Sound and Lights</h3> <p style="color: #ddd; line-height: 1.5; margin: 0 0 10px 0;">Quesha needs speakers and strings of lights for the festival.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask about a festival package</div>">> <<goto "QueshaRecruitTechStore">> <</link>> </div> <</if>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("TechStore")>> <<run $visitedLocations.push("TechStore")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">💻 Hammerhead Tech</h1> <div style="padding: 20px; background: linear-gradient(135deg, #17a2b8 0%, #138496 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> A modern electronics store showcasing the latest gadgets, computers, and accessories. Blue LED lighting gives everything a futuristic glow. </p> </div> <!-- Leave --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🚪 Exit</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Return to the mall directory.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Store</div>">> <<goto "Mall">> <</link>> </div> </div> <h2 style="color: #17a2b8;">Electronics for Sale</h2> <div style="margin-bottom: 25px;"> <!-- Laptop Purchase --> <<if !$hasLaptop>> <<set _laptopColor = ($hasApartment || $ownsHouse) ? "#17a2b8" : "#666">> <<set _laptopTextColor = ($hasApartment || $ownsHouse) ? "#aaa" : "#888">> <<set _canAffordLaptop = setup.canAffordTotal(500)>> <div style="border: 2px solid <<print _laptopColor>>; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px; margin-bottom: 12px;"> <h3 style="color: <<print _laptopColor>>; margin: 0 0 10px 0; font-size: 16px;">💻 Laptop</h3> <p style="font-size: 14px; color: <<print _laptopTextColor>>; margin: 0 0 10px 0; line-height: 1.4;">A decent laptop for work and entertainment.</p> <div style="flex-grow: 1;"></div> <<if $hasApartment || $ownsHouse>> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$500</p> <<if _canAffordLaptop>> <<link "<div style='background: #17a2b8; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Purchase Laptop</div>">> <<set _payment = setup.payAmount(500)>> <<if _payment.success>> <<set $hasLaptop = true>> <</if>> <<goto "TechStore">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Not Enough Money</div> <</if>> <<else>> <p style="font-size: 16px; color: #888; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$500</p> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Requires Housing</div> <</if>> </div> <</if>> <!-- TV Purchase --> <<if !$hasTV>> <<set _tvColor = ($hasApartment || $ownsHouse) ? "#667eea" : "#666">> <<set _tvTextColor = ($hasApartment || $ownsHouse) ? "#aaa" : "#888">> <<set _canAffordTV = setup.canAffordTotal(300)>> <div style="border: 2px solid <<print _tvColor>>; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px; margin-bottom: 12px;"> <h3 style="color: <<print _tvColor>>; margin: 0 0 10px 0; font-size: 16px;">📺 Flatscreen TV</h3> <p style="font-size: 14px; color: <<print _tvTextColor>>; margin: 0 0 10px 0; line-height: 1.4;">A 42-inch flatscreen TV.</p> <div style="flex-grow: 1;"></div> <<if $hasApartment || $ownsHouse>> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$300</p> <<if _canAffordTV>> <<link "<div style='background: #667eea; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Purchase TV</div>">> <<set _payment = setup.payAmount(300)>> <<if _payment.success>> <<set $hasTV = true>> <</if>> <<goto "TechStore">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Not Enough Money</div> <</if>> <<else>> <p style="font-size: 16px; color: #888; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$300</p> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Requires Housing</div> <</if>> </div> <</if>> <!-- Internet Router Purchase --> <<if !$hasRouter>> <<set _routerColor = ($hasApartment || $ownsHouse) ? "#f39c12" : "#666">> <<set _routerTextColor = ($hasApartment || $ownsHouse) ? "#aaa" : "#888">> <<set _canAffordRouter = setup.canAffordTotal(70)>> <div style="border: 2px solid <<print _routerColor>>; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px; margin-bottom: 12px;"> <h3 style="color: <<print _routerColor>>; margin: 0 0 10px 0; font-size: 16px;">📡 Internet Router</h3> <p style="font-size: 14px; color: <<print _routerTextColor>>; margin: 0 0 10px 0; line-height: 1.4;">A high-speed wireless router for your home internet.</p> <div style="flex-grow: 1;"></div> <<if $hasApartment || $ownsHouse>> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$70</p> <<if _canAffordRouter>> <<link "<div style='background: #f39c12; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Purchase Router</div>">> <<set _payment = setup.payAmount(70)>> <<if _payment.success>> <<set $hasRouter = true>> <</if>> <<goto "TechStore">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Not Enough Money</div> <</if>> <<else>> <p style="font-size: 16px; color: #888; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$70</p> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Requires Housing</div> <</if>> </div> <</if>> <!-- Webcam Purchase --> <<if !$hasWebcam>> <<set _webcamColor = $hasLaptop ? "#e74c3c" : "#666">> <<set _webcamTextColor = $hasLaptop ? "#aaa" : "#888">> <<set _canAffordWebcam = setup.canAffordTotal(200)>> <div style="border: 2px solid <<print _webcamColor>>; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px; margin-bottom: 12px;"> <h3 style="color: <<print _webcamColor>>; margin: 0 0 10px 0; font-size: 16px;">📷 HD Webcam</h3> <p style="font-size: 14px; color: <<print _webcamTextColor>>; margin: 0 0 10px 0; line-height: 1.4;">A high-quality 1080p webcam for video calls and streaming.</p> <div style="flex-grow: 1;"></div> <<if $hasLaptop>> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$200</p> <<if _canAffordWebcam>> <<link "<div style='background: #e74c3c; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Purchase Webcam</div>">> <<set _payment = setup.payAmount(200)>> <<if _payment.success>> <<set $hasWebcam = true>> <</if>> <<goto "TechStore">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Not Enough Money</div> <</if>> <<else>> <p style="font-size: 16px; color: #888; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$200</p> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Requires Laptop</div> <</if>> </div> <</if>> <!-- Smartphone Purchase --> <<if !$hasSmartphone>> <<set _canAffordSmartphone = setup.canAffordTotal(500)>> <div style="border: 2px solid #3b82f6; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px; margin-bottom: 12px;"> <h3 style="color: #3b82f6; margin: 0 0 10px 0; font-size: 16px;">📱 Smartphone</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">A modern smartphone with all the latest features.</p> <div style="flex-grow: 1;"></div> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center;">$500</p> <<if _canAffordSmartphone>> <<link "<div style='background: #3b82f6; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Purchase Smartphone</div>">> <<set _payment = setup.payAmount(500)>> <<if _payment.success>> <<set $hasSmartphone = true>> <<run setup.achievements.unlock("purchase_phone")>> <</if>> <<goto "TechStore">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Not Enough Money</div> <</if>> </div> <</if>> </div> <!-- WiFi Service Section --> <<if $hasRouter && ($hasApartment || $ownsHouse)>> <h2 style="color: #17a2b8;">Internet Service</h2> <!-- Initialize WiFi variables if not set --> <<if $wifiDaysRemaining === undefined>> <<set $wifiDaysRemaining = 0>> <</if>> <<if $wifiDaysRemaining > 0>> <div style="border: 2px solid #51cf66; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 12px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0; font-size: 16px;">✅ WiFi Active</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Your internet service is active. Days remaining: <<print $wifiDaysRemaining>></p> <p style="font-size: 14px; color: #51cf66; margin: 0; text-align: center;">Monthly Rate: $40 (per 30 days)</p> </div> <<else>> <div style="border: 2px solid #dc3545; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 12px;"> <h3 style="color: #dc3545; margin: 0 0 10px 0; font-size: 16px;">❌ No Active Service</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">You need to set up internet service to use your router.</p> <p style="font-size: 14px; color: #51cf66; margin: 0; text-align: center;">Monthly Rate: $40 (per 30 days)</p> </div> <</if>> <!-- Pay for WiFi --> <<set _canAffordWifi = setup.canAffordTotal(40)>> <div style="border: 2px solid #28a745; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h3 style="color: #28a745; margin: 0 0 10px 0; font-size: 16px;">💳 Pay for Internet Service</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Add 30 days of internet service for $40. You can pay in advance for multiple months.</p> <div style="flex-grow: 1;"></div> <<if _canAffordWifi>> <<link "<div style='background: #28a745; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Pay $40 for 30 Days</div>">> <<set _payment = setup.payAmount(40)>> <<if _payment.success>> <<set $wifiDaysRemaining += 30>> <</if>> <<goto "TechStore">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Not Enough Money</div> <</if>> </div> <</if>> <!-- NPC Interaction --> <<set _npcsHere = setup.getNPCsAtLocation("TechStore")>> <<if _npcsHere && _npcsHere.length > 0>> <<for _npc range _npcsHere>> <<capture _npc>> <h2 style="color: #17a2b8;">Store Clerk</h2> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 15px 0; line-height: 1.4;"> <<print _npc.jobs.join(", ")>> </p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> <!-- WiFi Setup Option --> <<if $hasRouter && !$wifiSetupComplete>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask About WiFi Setup</div>">> <<set $wifiSetupComplete = true>> <<goto "TechStoreWiFiSetup">> <</link>> <</if>> </div> <</capture>> <</for>> <</if>> <!-- Work Area (Only shows if player has the job) --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Tech Store Clerk">> <h2 style="color: #17a2b8;">Work Options</h2> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Work Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 15px 0; line-height: 1.4;">Clock in for your shift. (Work hours: 9 AM - 6 PM, max 8 hours/day)</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Start Work Shift</div>">> <<goto "UniversalWork">> <</link>> <!-- Self-Setup WiFi (if you work here) --> <<if $hasRouter && !$wifiSetupComplete>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Set Up Your Own WiFi</div>">> <<set $wifiSetupComplete = true>> <<goto "TechStoreWiFiSetup">> <</link>> <</if>> </div> <</if>> </div> <</nobr>>
<<silently>> <<nobr>> <!-- Ensure all mayors have Perverted trait --> <<run setup.addPervertedTraitToMayors()>> /* Backwards compatibility: generate obelisk codes for old saves */ <<if typeof $obeliskCodes === "undefined" || !$obeliskCodes || $obeliskCodes.length < 7>> <<set $obeliskCodes = [[1, 8, 3, 7], [4, 5, 2, 3], [8, 1, 6, 7], [7, 3, 9, 6], [3, 0, 5, 2], [9, 7, 1, 4], [1, 9, 0, 1]]>> <</if>> <<if typeof $volcanoRedHerring === "undefined" || !$volcanoRedHerring>> <<set $volcanoRedHerring = [1, 0, 9, 1]>> <</if>> <<if typeof $codexPrice === "undefined" || !$codexPrice>> <<set $codexPrice = 1837>> <</if>> /* Set current and previous passage variables */ <<set _currentPassage = passage()>> <<set _previousPassage = previous()>> <<if $tradingWithNPC && _currentPassage === "NPCInteraction">> <<run setup.meetNPC($tradingWithNPC)>> <</if>> <<if $money >= 10000000>> <<run setup.achievements.unlock("earn_10_million")>> <</if>> <<if $money >= 1000000000>> <<run setup.achievements.unlock("billionaire")>> <</if>> <<if $stats && ($stats.charisma >= 100 || $stats.dexterity >= 100 || $stats.strength >= 100 || $stats.intelligence >= 100)>> <<run setup.achievements.unlock("stat_100")>> <</if>> /* Only update lastLocation if this is a real game location */ /* _excludedPassages moved to setup.excludedPassages Set in Story JavaScript */ /* Debug/Cheat menu passages are never real locations. The prefix guard stops any newly added cheat passage from becoming $lastLocation and trapping the player in a Debug -> submenu -> Debug loop when they hit "Return to Game". */ <<if !setup.excludedPassages.has(_currentPassage) && _currentPassage !== "" && !_currentPassage.startsWith("Debug") && !_currentPassage.startsWith("Cheat")>> <<set $lastLocation = _currentPassage>> <</if>> /* Heal saves whose $lastLocation was already poisoned by a cheat passage */ <<if $lastLocation && ($lastLocation.startsWith("Debug") || $lastLocation.startsWith("Cheat"))>> <<set $lastLocation = "The Nest">> <</if>> /* Check if we should skip time advancement */ <<if $skipTimeAdvancement>> <<set $skipTimeAdvancement = false>> <<else>> <<if !setup.timePassages>> <<set setup.timePassages = { main: new Set(["BusinessDistrict", "Downtown", "ResidentialArea", "Park", "Beach", "University", "Hospital", "Library", "Gym", "Alleyway", "RedLightDistrict", "Docks", "Outskirts", "SeabassPark"]), sublocations: new Set(["Gym", "DanceStudio", "Cafe", "TrainingCenter", "Apartments", "TownHall", "ShadyShop", "Brothel", "StripClub", "Casino", "LampreyTomes", "AquariumEntrance", "AquariumGiftShop", "AquariumCafe", "CoralReef", "Bank"]), mall: new Set(["Mall", "FitnessShop", "EcentricShop", "BeautySalon", "TechStore", "AdultStore", "Bakery", "FoodCourt", "MallAtrium", "MallFloor2"]), patrol: new Set(["PatrolDowntown", "PatrolBusinessDistrict", "PatrolRedLightDistrict", "PatrolDocks", "PatrolAlleyway", "PatrolSeabassPark", "PatrolOutskirts"]), noTime: new Set([ "Start", "CharacterCreation", "StoryInit", "Summary", "NPCFirstMeeting", "NPCEncounter", "NPCChat", "NPCSkillTalk", "NPCInterestTalk", "TradingInterface", "ProcessTrade", "TradeSuccess", "TradeFailure", "Body", "Debug", "DebugDateTime", "DebugStatsAppearance", "DebugHousingTech", "DebugStreaming", "DebugRelationships", "DebugTraitsSkillsJobs", "DebugArtifacts", "DebugAchievementandSkillTree", "CheatMenuSexualSkills", "BusStop", "PrawnHub", "PrawnHubStream", "PrawnHubLiveStream", "PrawnHubStreamEnd", "PrawnHub_Action01", "PrawnHub_Action02", "PrawnHub_Action03", "PrawnHub_Action04", "PrawnHub_Action05", "PrawnHub_Action06", "PrawnHub_Action07", "PrawnHub_Action08", "PrawnHub_Action09", "PrawnHub_Action10", "PrawnHub_Action11", "PatrolOfficerWork", "Teleport", "NPCInteraction", "NPCTalk", "NPCTalkResponse", "TradeInterface", "TradeSelectItems", "TradeResult", "SellTraits", "SellTraitsComplete", "DebugBank", "DebugQuests", /* Menu Passages */ "Achievements", "SkillTree", "Quests", /* Phone App Passages */ "Phone", "Gallery", "Notes", "Maps", "BankApp", "InstaFin", "SunfishNet", "Messages", "Contacts", "Settings", /* ATM Passages */ "ATM", /* Brothel Passages - NEW */ "BrothelClientSelection", "BrothelSession", "BrothelSessionResults", "BrothelManagement", /* Strip Club Passages - NEW */ "StripClubWorkStripper", "StripClubStage", "StripClubPerformRemoveTop", "StripClubPerformStripFull", "StripClubPerformPole", "StripClubPerformFreestyle", "StripClubMingleCustomers", "StripClubMingleInteraction", "StripClubPrivateShows", "StripClubPrivateShowPerform", /* Crime Passages - NEW */ "CrimeHub", "ScoutForTarget", "SelectTraitToSteal", "AttemptTraitTheft", "TraitTheftSuccess", "CaughtByPolice", "SurrenderArrest", "ResistArrest", "EscapeSuccess", "EscapeFailed", /* Beach/Sunfish Event Passages */ "SunfishTank", "SunfishTankSwim", "SunfishTankTunnel", "UnderWaterCave", "ArtifactRoom", "ArtifactClaimed", /* Old Crime Passages */ "CrimeScene", "CrimeResponse", "CrimeResolution", "OfficerCrimeAttempt", "OfficerCrimeResult", "TraitTheftResult", /* Casino/Gambling Passages */ "RouletteRoom", "RouletteSpinResult", "SlotMachine", "SlotMachineResult", "ForcedGambling", /* Dream State Passages */ "DreamIntro", "DreamGenderSelect", "DreamGenderOptions", "DreamAppearanceOptions", "DreamNegativeTraits", "DreamIdentitySummary", "DreamContinueButton", "DreamTrading", "DreamSummary", "DreamAwakening", "DreamStateStyles", /* Work Complete Passages */ "WorkCompleteTraitResult", "WorkCompleteEarnings", "UniversalWorkComplete", /* Inventory/Menu Passages */ "Inventory", /* Fishing Passages */ "FishingDocks", "FishingBeach", "FishingPond", "FishingCoralReef", "FishingUnderwaterCave", "FishingDealership", "FishingTrip", "FishingResult", "FishingQTE", "FishingQTEResult", "FishEncyclopedia", "FishingCast", "OceanFishing", "DealershipRepair", "DebugFishingQTE", "DebugFishingQTEResult" ]) }>> <</if>> <<if !setup.timePassages.noTime.has(_currentPassage) && _previousPassage !== _currentPassage && _previousPassage !== "">> <<if setup.timePassages.main.has(_currentPassage)>> <<set $timeInMinutes += 15>> <<if $timeInMinutes >= 1440>> <<run setup.advanceDay()>> <</if>> <<elseif setup.timePassages.sublocations.has(_currentPassage)>> <<set $timeInMinutes += 5>> <<if $timeInMinutes >= 1440>> <<run setup.advanceDay()>> <</if>> <<elseif setup.timePassages.mall.has(_currentPassage)>> <<if _previousPassage === "Mall">> <<set $timeInMinutes += 2>> <<else>> <<set $timeInMinutes += 5>> <</if>> <<if $timeInMinutes >= 1440>> <<run setup.advanceDay()>> <</if>> <<elseif setup.timePassages.patrol.has(_currentPassage)>> <<set $timeInMinutes += 30>> /* Check if shift is complete (8 hours = 480 minutes) */ <<if $onPatrol && $patrolStartTime !== undefined>> <<set _minutesWorked = $timeInMinutes - $patrolStartTime>> <<set $patrolHoursWorked = _minutesWorked / 60>> <<if _minutesWorked >= 480>> /* Shift complete - end patrol and set cooldown */ <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> /* Calculate pay */ <<set _totalPay = Math.floor(8 * 35)>> <<set $money += _totalPay>> /* Show shift complete message */ <<run UI.alert("✅ Shift Complete!\n\nYou worked 8 hours and earned $" + _totalPay + ".\n\nYou must wait 16 hours before your next shift.")>> /* Auto-return to police station */ <<if _currentPassage !== "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <</if>> <</if>> <<if $timeInMinutes >= 1440>> <<run setup.advanceDay()>> <</if>> <</if>> <</if>> <</if>> <<if $tradingWithNPC && _currentPassage === "TradeInterface">> <<run setup.meetNPC($tradingWithNPC)>> <</if>> <</nobr>> <</silently>>
:: InitPlayerData <<silently>> /* ---------------------------------- */ /* --- PLAYER STATS --- */ /* ---------------------------------- */ <<set $stats = { charisma: 5, dexterity: 5, strength: 5, intelligence: 5 }>> <<set $statMaxCaps = { charisma: 100, dexterity: 100, strength: 100, intelligence: 100 }>> /* ---------------------------------- */ /* --- CERBERUS THREE-HEAD SYSTEM --- */ /* ---------------------------------- */ <<set $cerberusHeadNames = { left: "", right: "" }>> <<set $cerberusNamed = false>> <<set $cerberusHeadMap = {}>> <<set $discoveredWolfStatue = false>> <<set $cerberusAltarPrimed = false>> <<set $cerberusAltarProgress = {}>> /* ---------------------------------- */ /* --- PLAYER APPEARANCE --- */ /* ---------------------------------- */ <<if !$appearance>> <<set $appearance = { skinTone: "pale", hairColor: "Black", hairStyle: "messy", physique: "average", age: "Adult" }>> <</if>> /* Make sure age exists */ <<if !$appearance.age>> <<set $appearance.age = "Adult">> <</if>> /* Make sure hairStyle is messy */ <<if !$appearance.hairStyle>> <<run setup.setHairMessy()>> <</if>> /* ---------------------------------- */ /* --- PLAYER BODY PARTS --- */ /* ---------------------------------- */ <<set $bodyParts = { gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis" }>> <<run setup.identity && setup.identity.ensureOriginalBody && setup.identity.ensureOriginalBody()>> /* ---------------------------------- */ /* --- PLAYER TRAITS & SKILLS --- */ /* ---------------------------------- */ <<set $physicalTraits = []>> <<set $mentalTraits = []>> <<set $selectedTraits = []>> <<set $skills = []>> <<set $discoveredTraits = {physical: [], mental: [], skills: [], voice: []}>> /* Available physical traits */ <<set setup.availablePhysicalTraits = { "Tall": "Above average height", "Short": "Below average height", "Curvy": "Curved body shape", "Lean": "Thin and fit", "Muscular": "Well-defined muscles", "Soft": "Soft body texture", "Sharp Features": "Defined facial features", "Smooth Skin": "Very smooth skin", "Scarred": "Visible scars", "Pierced": "Body piercings", "Youthful": "Young appearance", "Mature": "Mature appearance", "Tan Skin": "Tanned complexion", "Dark Skin": "Dark complexion", "Pale Skin": "Pale complexion", "Attractive": "Very attractive appearance", "Plain": "Unremarkable appearance", "Ugly": "Unattractive appearance", "Fit": "In good physical shape", "Overweight": "Above healthy weight", "Underweight": "Below healthy weight", "Graceful": "Moves with elegance", "Clumsy": "Accident-prone", "Strong": "Physically powerful", "Weak": "Physically frail", "Flexible": "Very limber", "Stiff": "Poor flexibility", "Blemished": "Visible skin imperfections", "Freckled": "Freckled complexion", "Tattooed": "Has tattoos", "Athletic Build": "Sporty physique", "Petite": "Small frame", "Voluptuous": "Full figure", "Blue Hair": "Striking blue hair, cosmetic only", "Snow Fox": "A snow fox's silver coat, ears, and tail. Cosmetic only.", "Broad-shouldered": "Wide shoulders", "Quick": "Fast movements", "Sturdy": "Solid build", "Fashionable": "Stylish appearance", "Striking": "Commanding presence that turns heads", "Unphotogenic": "Looks awkward on camera", "Quick Reflexes": "Fast reactions", "Fast": "High speed", "Slow": "Low speed", /* Transformation Ingredient Traits */ "Fangs": "Sharp canine teeth", "Pointed Ears": "Elven or fae-like ears", "Glowing Eyes": "Supernatural eye luminescence", "Claws": "Sharp retractable claws", "Wings": "Small decorative wings", "Tail": "A tail", "Lactating": "Produces milk", "Cog": "Infused with ancient mechanical energy", "Mystic": "Blessed by the nine-tailed fox spirit", "Heart": "A warmth kindled by true friendship", "Guardian": "Anointed protector of the desert altar", "Darkness": "Consumed by an orb of pure darkness found at the bottom of a cliff", "Alcoholic": "Compelled to drink from a mysterious goblet found at the bottom of a cliff", "Disturbed": "Shattered by the pitch-black elixir that combines darkness and vice into pure torment", "Mirrored": "Touched by the spectral mirror in the manor attic", "Thirsty": "An unquenchable thirst burns within you", "Blood": "The scent of blood is intoxicating", "Burnt": "Scarred by a bath in molten lava", "Inferno": "Immune to extreme temperatures from a volcanic fruit", "Scaled": "Iridescent scales cover patches of your skin, shimmering in the light", "Divine Sunfish": "Blessed by the convergence of all seven sunfish artifacts at the oasis altar", "Electrified": "Struck by lightning atop a mountain peak, crackling energy courses through your body", "Totally not a Vampire": "You are definitely, absolutely, totally not a vampire. Nope.", "Fish": "You smell faintly of the ocean and your eyes have a strange aquatic glint", /* Gender Traits */ "Cuntboy": "A male with female genitalia", "Dickgirl": "A female with male genitalia", "Futanari": "Has both male and female genitalia", "Ojou": "A refined heiress with golden drill curls and aristocratic bearing" }>> /* Available voice traits */ <<set setup.availableVoiceTraits = { "Smooth Voice": "Pleasant vocal quality", "Soft-Spoken": "Quiet speaker", "Warm Tone": "Friendly vocal warmth", "Gentle Voice": "Soothing speech", "Soothing Tone": "Calming voice", "Silky Voice": "Smooth vocal texture", "Clear Enunciation": "Precise pronunciation", "Articulate Speech": "Well-spoken", "Smooth Talker": "Persuasive speaker", "Friendly Tone": "Welcoming voice", "Charismatic Voice": "Captivating speech", "Steady Voice": "Consistent tone", "Pleasant Cadence": "Nice rhythm", "Calm Voice": "Peaceful tone", "Expressive Voice": "Emotional speech", "Animated Tone": "Lively speaking", "Lively Tone": "Energetic voice", "Charming Tone": "Appealing speech", "Hushed Intimate Voice": "Soft private tone", "Balanced Neutral Tone": "Even speaking", "Sing-Songy Voice": "Musical speech", "Eager Tone": "Enthusiastic voice", "Bouncy Tone": "Upbeat speaking", "Melodic Voice": "Song-like quality", "Clear Pronunciation": "Easy to understand", "Even-Paced Voice": "Steady rhythm", "Understated Voice": "Subtle tone", "Soft Monologue Style": "Narrative speech", "Fast Talker": "Rapid speech", "Rapid-Fire Speech": "Very quick talking", "Deep Voice": "Low pitch", "High-Pitched Tone": "High voice", "Raspy Voice": "Rough vocal quality", "Gravelly Voice": "Coarse tone", "Croaky Voice": "Hoarse speech", "Breathy Voice": "Airy speaking", "Nasally Tone": "Nasal quality", "Stoic Tone": "Unemotional voice", "Measured Speech": "Careful speaking", "Choppy Speech": "Broken rhythm", "Interruptive Tone": "Cuts in often", "Sharp Voice": "Pointed tone", "Snappy Tone": "Curt speech", "Flat Voice": "Monotonous", "Monotone": "No variation", "Deadpan Delivery": "Expressionless speech", "Detached Voice": "Distant tone", "Emotionless Tone": "No feeling", "Slow Calm Voice": "Unhurried speech", "Lazy Drawl": "Slow drawling", "Mumbly Voice": "Unclear speech", "Stuttering Speech": "Hesitant talking", "Grim Tone": "Dark voice", "Robotic Tone": "Mechanical speech", "Shaky Voice": "Trembling speech" }>> /* Available mental traits */ <<set setup.availableMentalTraits = { "Extroverted": "Outgoing and social", "Introverted": "Reserved and quiet", "Bitchy": "Abrasive personality", "Kind": "Compassionate nature", "Sly": "Cunning and deceptive", "Honest": "Truthful and direct", "Dominant": "Assertive personality", "Submissive": "Compliant nature", "Confident": "Self-assured", "Shy": "Timid and reserved", "Aggressive": "Confrontational", "Passive": "Non-confrontational", "Optimistic": "Positive outlook", "Pessimistic": "Negative outlook", "Cruel": "Enjoys causing pain", "Empathetic": "Understanding of others", "Stubborn": "Refuses to change", "Flexible": "Adapts easily", "Jealous": "Envious of others", "Supportive": "Helpful to others", "Friendly": "Warm and approachable", "Competitive": "Driven to win", "Logical": "Rational thinker", "Shrewd": "Clever and calculating", "Lazy": "Avoids work", "Hardworking": "Diligent and dedicated", "Arrogant": "Overly proud", "Humble": "Modest and unassuming", "Paranoid": "Overly suspicious", "Trusting": "Believes in others", "Ambitious": "Driven to succeed", "Complacent": "Satisfied with mediocrity", "Creative": "Imaginative thinker", "Dull": "Lacks imagination", "Brave": "Courageous", "Cowardly": "Fearful and timid", "Mature": "Acts with maturity", "Patient": "Tolerant and calm", "Impatient": "Quick to anger", "Wise": "Shows good judgment", "Foolish": "Makes poor decisions", "Intelligent": "Smart and quick-witted", "Analytical": "Logical problem solver", "Outgoing": "Sociable and talkative", "Curious": "Eager to learn", "Witty": "Clever and humorous", "Calm": "Composed and peaceful", "Energetic": "Full of energy", "Thoughtful": "Considerate of others", "Chill": "Relaxed and easy-going", "Nonchalant": "Casually calm", "Charming": "Naturally appealing", "Diplomatic": "Tactful negotiator", "Organized": "Well-structured", "Resourceful": "Finds solutions", "Focused": "Concentrates well", "Disciplined": "Self-controlled", "Determined": "Won't give up", "Steadfast": "Unwavering", "Considerate": "Thoughtful of others", "Polite": "Well-mannered", "Funny": "Makes others laugh", "Reassuring": "Comforting presence", "Loyal": "Faithful and devoted", "Talkative": "Speaks a lot", "Direct": "Straightforward", "Efficient": "Gets things done", "Negotiator": "Skilled bargainer", "Crafty": "Cleverly creative", "Workaholic": "Works excessively", "High Stamina": "Great endurance", "Flirty": "Playfully romantic", "Seductive": "Sexually appealing", "Alluring": "Mysteriously attractive", "Warm": "Emotionally welcoming", "Bookworm": "Loves reading", "Lucky": "Good fortune", "Unlucky": "Bad fortune", "Bad Luck": "Cursed with misfortune", "Caffeine Addict": "Coffee-fueled learning", "Blunt": "Brutally honest", "Perfectionist": "Demands perfection", "Overthinker": "Analyzes too much", "Moody": "Unpredictable emotions", "Unpredictable": "Erratic behavior", "Risk Taker": "Embraces danger", "Impulsive": "Acts without thinking", "Cynical": "Distrustful pessimist", "Quiet": "Doesn't talk much", "Awkward": "Socially uncomfortable", "Tone Deaf": "Can't read situations", "Tease": "Playfully mocking", "Clingy": "Overly attached", "Sensitive": "Easily hurt", "Corporate Drone": "Bland office worker", "Forgetful": "Poor memory", "Disorganized": "Messy and chaotic", "Selfish": "Self-centered", "Deceitful": "Dishonest and lying", "Erratic": "Unstable behavior", "Obsessive": "Fixates unhealthily", "Insecure": "Lacks confidence", "Short Tempered": "Easily angered", "Rude": "Disrespectful", "Unreliable": "Can't be trusted", "Slow Learner": "Struggles to learn", "Reckless": "Dangerously careless", "Cold": "Emotionally distant", "Insensitive": "Doesn't care", "Unskilled": "Lacks abilities", "High Energy": "Constantly energetic", "Deep Thinker": "Philosophical mind", "Monotone Expression": "Shows no emotion", "Sarcastic": "Uses irony often", "Artistic": "Creative vision", "Relaxed": "Laid-back attitude", "Humorous": "Funny personality", "Perceptive": "Notices details", "Detail-Oriented": "Focuses on specifics", "Customer-Focused": "Service-minded", "Punctual": "Always on time", "Naive": "Innocent and trusting", "Photogenic": "Naturally looks great on camera", "Poised": "Composed and graceful under pressure", /* Transformation Ingredient Traits */ "Mischievous": "Loves pranks and chaos", "Docile": "Calm and easily led", "Feral": "Wild animal instincts", "Predatory": "Hunting instincts", "Maternal": "Strong nurturing instincts", "Paternal": "Strong fatherly instincts", "Breeding Obsessed": "Fixated on reproduction", "Heat Cycles": "Periodic intense arousal", "Pack Minded": "Loyal to group hierarchy", "Nocturnal": "Active at night, sleepy by day", "Territorial": "Protective of space and partners", "Shameless": "No embarrassment about sexuality", "Insatiable": "Never satisfied sexually", "Praise Seeking": "Craves approval and praise", "Obedient": "Follows orders without question", "Collar Loving": "Enjoys being collared or owned", "Rebellious": "Defies authority", "Corrupted": "Tainted by dark influences", "Cunning": "Sly and clever", "Blessed": "Touched by a mysterious divine light", "Wild": "Untamed primal instincts", "Chosen": "Anointed by the ancient desert altar", "Honey": "Coated in a golden sheen of wild jungle honey", "Cog": "Infused with ancient mechanical energy from a steampunk artifact", "Mystic": "Blessed by the nine-tailed fox spirit of the mountain shrine", "Heart": "A warmth kindled by the bonds of true friendship", "Guardian": "Anointed protector of the desert altar, forged through loyalty and sacrifice", "Darkness": "Consumed by an orb of pure darkness found at the bottom of a cliff", "Alcoholic": "Compelled to drink from a mysterious goblet found at the bottom of a cliff", "Disturbed": "Shattered by the pitch-black elixir that combines darkness and vice into pure torment", "Mirrored": "Touched by the spectral mirror in the manor attic — something came through with you", "Thirsty": "An unquenchable thirst burns within you since the manor basement", "Blood": "The scent of blood is intoxicating since you opened that coffin", "Burnt": "Scarred by a bath in molten lava — you survived the fire", "Inferno": "A volcanic fruit burns within you, granting immunity to extreme temperatures", /* Mining mastery traits — earned from milestone completions in the mines and forge */ "Ore Reader": "Reads ore veins like a map; +1 surface glint per grid", "Forge Lore": "Trained in every smelting pattern; +10% smelt yield and pickaxe quality", "Gem Eye": "Cuts gems with surgical precision; +15% bonus chance per cut", "Master Craftsman": "Has wielded every tier of pickaxe; 15% chance of bonus stat on crafted pickaxes" }>> /* ---------------------------------- */ /* --- TRAIT COMBINATIONS --- */ /* ---------------------------------- */ /* Format: "Trait1|Trait2": { result: "NewTrait", critSuccess: "EnhancedVersion", critFail: "CursedVersion" } */ /* Combinations work both ways - "A|B" also matches "B|A" */ <<set setup.traitCombinations = { /* ================================== */ /* TIER 2: THREE-TRAIT COMBINATIONS */ /* (Creates full transformations) */ /* Keys sorted alphabetically */ /* ================================== */ /* DEMONIC */ "Curvy|Imp|Sexually Skilled": { result: "Succubus", isFullTransformation: true }, "Succubus|Tall|Voluptuous": { result: "Voluptuous Succubus", isFullTransformation: true, isSecret: true }, /* "Charming|Horns|Temptress": { result: "Incubus", isFullTransformation: true }, // temporarily disabled */ "Attractive|Cynical|Short": { result: "Imp", isFullTransformation: true }, /* WERE-CREATURES */ "Impatient|Intelligent|Risk Taker": { result: "Werecat", isFullTransformation: true }, "Fit|Leadership|Scarred": { result: "Werewolf", isFullTransformation: true }, "Extroverted|Fast|Flexible": { result: "Werebunny", isFullTransformation: true }, "Attractive|Quick Learner|Sly": { result: "Werefox", isFullTransformation: true }, "Curvy|Kind|Warm": { result: "Weresheep", isFullTransformation: true }, "Cowardly|Lactating|Voluptuous": { result: "Hucow", isFullTransformation: true }, /* AESTHETIC */ "High Heels Proficient|Submissive|Voluptuous": { result: "Trophy Wife", isFullTransformation: true }, "Athletic Build|Competitive|Fit": { result: "Gym Bunny", isFullTransformation: true }, "Fashionable|Flirty|Tech-Savvy": { result: "E-Girl", isFullTransformation: true }, "Bitchy|Extroverted|Prep": { result: "Gyaru", isFullTransformation: true }, "Goth|Pierced|Tattooed": { result: "Punk", isFullTransformation: true }, /* SUPERNATURAL */ "Fishimon Master|Singing|Swimmer": { result: "Siren", isFullTransformation: true, requiresTier4Rod: true }, "Fishimon Master|Singing|Swimming": { result: "Siren", isFullTransformation: true, requiresTier4Rod: true }, "Corporate Drone|Occult Expert|Stiff": { result: "Living Doll", isFullTransformation: true }, /* DOMINANT */ "Cruel|Dominant|Seductive": { result: "Dominatrix", isFullTransformation: true }, /* CORRUPTION */ "High Stamina|Sexually Skilled|Trophy Wife": { result: "Slut", isFullTransformation: true }, "Chill|Heavy Lifting|Muscular": { result: "Himbo", isFullTransformation: true }, /* NEW SUPERNATURAL TRANSFORMATIONS */ "Blessed|Humble|Lucky": { result: "Angel", isFullTransformation: true }, "Divine Sunfish|Siren|Sunfish": { result: "Naiad", isFullTransformation: true }, "Cog|Living Doll|Soul": { result: "Automaton", isFullTransformation: true }, "Dragon|Gyaru|Soul": { result: "Half-Dragon Gyaru", isFullTransformation: true }, "Darkness|Disturbed|Unlucky": { result: "Banshee", isFullTransformation: true }, "Lucky|Mirrored|Werecat": { result: "Cheshire Cat", isFullTransformation: true }, "Angel|Charming|Heart": { result: "Cupid", isFullTransformation: true }, "Blessed|Darkness|Unlucky": { result: "Dark Angel", isFullTransformation: true }, "Energetic|Honey|Loyal": { result: "Honeybee", isFullTransformation: true }, "Combat|Were-Creature|Wild": { result: "Jinko", isFullTransformation: true }, "Energetic|Fit|Wild": { result: "Kakuen", isFullTransformation: true }, "Blunt|Scaled|Sturdy": { result: "Lizardman", isFullTransformation: true }, "Werecat|Wild|Wise": { result: "Ocelomeh", isFullTransformation: true }, "Imp|Inferno|Sexually Skilled": { result: "Pyrow", isFullTransformation: true }, "Electrified|Slut|Were-Creature": { result: "Raiju", isFullTransformation: true }, "Inferno|Lizardman|Wild": { result: "Salamander", isFullTransformation: true }, "Alcoholic|Music|Weresheep": { result: "Satyros", isFullTransformation: true }, "Blood|Definitely not a Vampire|Thirsty": { result: "Vampire", isFullTransformation: true }, "Blood|Thirsty|Totally not a Vampire": { result: "Vampire", isFullTransformation: true }, "Mystic|Soul|Werefox": { result: "Kitsune", isFullTransformation: true }, "Guardian|Loyal|Werewolf": { result: "Anubis", isFullTransformation: true }, "Chosen|Dominant|Leadership": { result: "Pharaoh", isFullTransformation: true } }>> /* ---------------------------------- */ /* --- FULL TRANSFORMATIONS --- */ /* ---------------------------------- */ /* These override appearance and grant/remove traits automatically */ <<set setup.fullTransformations = { /* DEMONIC */ "Succubus": { type: "supernatural", category: "physical", description: "A seductive demon that feeds on sexual energy", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Succubus", grantsPhysical: ["Succubus"], grantsMental: [], removesOnGain: ["Innocent", "Naive", "Shy", "Imp", "Cynical"], removesPhysicalOnGain: ["Curvy", "Attractive", "Short"], removesSkillsOnGain: ["Sexually Skilled"], blocksTraits: ["Innocent", "Naive", "Shy", "Imp", "Cynical"], blocksPhysical: ["Curvy", "Attractive", "Short"], blocksSkills: ["Sexually Skilled"], setsChest: "large", setsGenitals: "vagina", genderLock: "female" }, "Voluptuous Succubus": { type: "supernatural", category: "physical", description: "A towering, impossibly curvy succubus radiating overwhelming sensuality. Her voluptuous form defies mortal proportions.", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Succubus", grantsPhysical: ["Voluptuous Succubus", "Succubus"], grantsMental: [], removesOnGain: ["Innocent", "Naive", "Shy", "Imp", "Cynical"], removesPhysicalOnGain: ["Tall", "Voluptuous"], removesSkillsOnGain: [], blocksTraits: ["Innocent", "Naive", "Shy", "Imp", "Cynical"], blocksPhysical: ["Tall", "Voluptuous"], blocksSkills: [], setsChest: "gigantic", setsButt: "gigantic", setsGenitals: "vagina", genderLock: "female", isSecretVariant: true, baseTransformation: "Succubus", locksBodySize: true }, "Incubus": { type: "supernatural", category: "physical", description: "A seductive demon that feeds on sexual energy", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Incubus", grantsPhysical: ["Incubus"], grantsMental: [], removesOnGain: ["Innocent", "Naive", "Shy"], genderLock: "male" }, "Imp": { type: "supernatural", category: "physical", description: "A small mischievous demon", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Imp", grantsPhysical: ["Imp"], grantsMental: [], removesOnGain: ["Cynical"], removesPhysicalOnGain: ["Attractive", "Short"], blocksTraits: ["Cynical"], blocksPhysical: ["Attractive", "Short"], setsChest: "small", setsGenitals: "tight vagina", genderLock: "female" }, "Cerberus": { type: "supernatural", category: "physical", description: "A fierce demonic wolf with boundless energy and supernatural luck", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Cerberus", grantsPhysical: ["Cerberus"], grantsMental: [], removesOnGain: ["Energetic", "Lucky", "Werewolf", "Scarred", "Fit"], removesSkillsOnGain: ["Leadership"], blocksTraits: ["Energetic", "Lucky", "Werewolf", "Scarred", "Fit"], blocksSkills: ["Leadership"], sleepImmunity: true, gymMultiplier: 4, setsChest: "large", setsChestMinimum: true, setsButt: "huge", setsGenitals: "vagina", setsHairColor: "Black", setsSkinTone: "pale", genderLock: "female" }, "Half-Dragon Gyaru": { type: "supernatural", category: "physical", description: "A muscular, stacked half-dragon gyaru, brash and blazing with draconic power.", overridesAppearance: true, imagePath: "Images/Faces/Laboratory/Dragon_Gyaru", grantsPhysical: ["Half-Dragon Gyaru", "Muscular"], grantsMental: [], removesOnGain: ["Gyaru", "Dragon"], setsChest: "huge", setsChestMinimum: true, setsButt: "huge", setsGenitals: "vagina", setsHairColor: "Platinum Blonde", genderLock: "female" }, /* WERE-CREATURES */ "Werecat": { type: "supernatural", category: "physical", description: "A cunning feline were-creature with razor-sharp instincts", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Werecat", grantsPhysical: ["Werecat"], grantsMental: [], removesOnGain: ["Impatient", "Intelligent", "Risk Taker"], blocksTraits: ["Impatient", "Intelligent", "Risk Taker"], setsChest: "medium", setsButt: "medium", setsGenitals: "tight vagina", genderLock: "female" }, "Werewolf": { type: "supernatural", category: "physical", description: "A fierce pack leader with wolf-like instincts", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Werewolf", grantsPhysical: ["Werewolf"], grantsMental: [], removesOnGain: ["Scarred", "Fit"], removesSkillsOnGain: ["Leadership"], blocksTraits: ["Scarred", "Fit"], blocksSkills: ["Leadership"], sleepImmunity: true, setsChest: "large", setsButt: "large", setsGenitals: "vagina", genderLock: "female" }, "Werebunny": { type: "supernatural", category: "physical", description: "A quick and agile rabbit were-creature", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Werebunny", grantsPhysical: ["Werebunny"], grantsMental: [], removesOnGain: ["Extroverted"], removesPhysicalOnGain: ["Flexible", "Fast"], blocksTraits: ["Extroverted"], blocksPhysical: ["Flexible", "Fast"], setsChest: "medium", setsButt: "large", setsGenitals: "tight vagina", genderLock: "female" }, "Werefox": { type: "supernatural", category: "physical", description: "A cunning and sly fox were-creature with quick wits", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Werefox", grantsPhysical: ["Werefox"], grantsMental: [], removesOnGain: ["Sly"], removesPhysicalOnGain: ["Attractive"], removesSkillsOnGain: ["Quick Learner"], blocksTraits: ["Sly"], blocksPhysical: ["Attractive"], blocksSkills: ["Quick Learner"], stealingBonus: 20, tradeBonus: 10, fishSellingBonus: 10, setsChest: "large", setsButt: "medium", setsGenitals: "loose vagina", genderLock: "female" }, "Weresheep": { type: "supernatural", category: "physical", description: "A gentle and warm-hearted sheep were-creature", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Weresheep", grantsPhysical: ["Weresheep"], grantsMental: [], removesOnGain: ["Kind", "Warm"], removesPhysicalOnGain: ["Curvy"], blocksTraits: ["Kind", "Warm"], blocksPhysical: ["Curvy"], relationshipMultiplier: 2, setsChest: "huge", setsButt: "large", setsGenitals: "vagina", genderLock: "female" }, "Hucow": { type: "supernatural", category: "physical", description: "A fully domesticated human cow", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Hucow", grantsPhysical: ["Hucow"], grantsMental: [], removesOnGain: ["Intelligent", "Ambitious"], setsChest: "gigantic", setsButt: "gigantic", setsGenitals: "loose vagina", genderLock: "female" }, /* AESTHETIC */ "Trophy Wife": { type: "aesthetic", category: "physical", description: "A pampered arm candy with refined tastes and sexual expertise", overridesAppearance: true, imagePath: "Images/Faces/Transformations/TrophyWife", grantsPhysical: ["Trophy Wife"], grantsMental: [], removesOnGain: ["Submissive"], removesPhysicalOnGain: ["Voluptuous"], removesSkillsOnGain: ["High Heels Proficient"], blocksTraits: ["Submissive"], blocksPhysical: ["Voluptuous"], blocksSkills: ["High Heels Proficient"], brothelXpMultiplier: 2, secretarySexCashMultiplier: 2, sexualXpMultiplier: 2, guaranteedClappingSuccess: true, guaranteedPrawnhubSuccess: true, setsChest: "giant", setsButt: "giant", setsGenitals: "loose vagina", genderLock: "female" }, "Ojou": { type: "aesthetic", category: "physical", description: "A refined heiress with golden drill curls, pale skin, and aristocratic bearing", overridesAppearance: true, imagePath: "Images/Transformation/Ojou", grantsPhysical: ["Ojou"], grantsMental: [], removesOnGain: ["Crude", "Tomboy", "Lazy"], removesPhysicalOnGain: ["Punk", "Gyaru", "Slut", "Trophy Wife", "Bimbo"], blocksTraits: ["Crude", "Tomboy"], blocksPhysical: ["Punk", "Gyaru", "Slut", "Trophy Wife", "Bimbo"], setsChest: "large", setsChestFloorOnly: true, genderLock: "female", hairColorLock: "blonde", hairStyleLock: "long", skinToneLock: "pale" }, "Gym Bunny": { type: "aesthetic", category: "physical", description: "A fitness-obsessed individual who replaces sleep with workouts", overridesAppearance: true, imagePath: "Images/Faces/Transformations/GymBunny", grantsPhysical: ["Gym Bunny"], grantsMental: [], removesOnGain: ["Lazy", "Competitive"], removesPhysicalOnGain: ["Athletic Build", "Fit"], blocksTraits: ["Competitive"], blocksPhysical: ["Athletic Build", "Fit"], gymMultiplier: 4, sleepImmunity: true, setsChest: "large", setsButt: "huge", setsGenitals: "tight vagina", genderLock: "female" }, "E-Girl": { type: "aesthetic", category: "physical", description: "An internet personality with a devoted online following", overridesAppearance: true, imagePath: "Images/Faces/Transformations/EGirl", grantsPhysical: ["E-Girl"], grantsMental: [], removesOnGain: ["Flirty", "Tech-Savvy"], removesPhysicalOnGain: ["Fashionable"], blocksTraits: ["Flirty", "Tech-Savvy"], blocksPhysical: ["Fashionable"], streamingSubMultiplier: 2, setsChest: "large", setsButt: "large", setsGenitals: "tight vagina", genderLock: "female" }, "Punk": { type: "aesthetic", category: "physical", description: "An anti-establishment rebel with a unique style", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Punk", grantsPhysical: ["Punk"], grantsMental: [], removesOnGain: ["Goth"], removesPhysicalOnGain: ["Pierced", "Tattooed"], blocksTraits: ["Goth"], blocksPhysical: ["Pierced", "Tattooed"], roisinSellBonus: 1.5, setsChest: "small", setsButt: "medium", setsGenitals: "vagina", genderLock: "female" }, "Gyaru": { type: "aesthetic", category: "physical", description: "A flashy party girl with tanned skin and bold makeup", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Gyaru", grantsPhysical: ["Gyaru"], grantsMental: [], removesOnGain: ["Prep", "Extroverted", "Bitchy", "Shy", "Reserved"], blocksTraits: ["Prep", "Extroverted", "Bitchy", "Shy", "Reserved"], gyaruRelationships: true, gyaruPrawnhub: true, gyaruStripClub: true, setsChest: "large", setsButt: "giant", setsGenitals: "vagina", genderLock: "female" }, /* SUPERNATURAL */ "Siren": { type: "supernatural", category: "physical", description: "A mythical sea creature with an enchanting voice that lures sailors to their doom. Can only catch legendary treasure and the rarest fish.", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Siren", grantsPhysical: ["Siren"], grantsMental: [], removesOnGain: ["Fishimon Master"], removesSkillsOnGain: ["Singing", "Swimmer", "Swimming"], blocksTraits: ["Fishimon Master"], blocksSkills: ["Singing", "Swimmer", "Swimming"], tradeBonus: 30, sexualXpMultiplier: 1.5, fishSellingMultiplier: 2, sirenFishing: true, setsChest: "huge", setsButt: "huge", setsGenitals: "loose vagina", genderLock: "female" }, "Living Doll": { type: "supernatural", category: "physical", description: "A perfect, doll-like being", overridesAppearance: true, imagePath: "Images/Faces/Transformations/LivingDoll", grantsPhysical: ["Living Doll"], grantsMental: [], removesOnGain: ["Rebellious"], setsChest: "medium", setsGenitals: "tight vagina", genderLock: "female" }, /* DOMINANT */ "Dominatrix": { type: "aesthetic", category: "physical", description: "A commanding female dominant who takes control. Earns 3x cash for dominant acts at the brothel and clients ignore their preferences when you dominate them.", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Dominatrix", grantsPhysical: ["Dominatrix"], grantsMental: [], removesOnGain: ["Cruel", "Dominant", "Seductive", "Submissive", "Kind"], blocksTraits: ["Cruel", "Dominant", "Seductive", "Submissive", "Kind"], dominatrixBrothel: true, setsChest: "huge", setsButt: "huge", setsGenitals: "loose vagina", genderLock: "female" }, /* CORRUPTION */ "Slut": { type: "corruption", category: "physical", description: "An insatiable sexual being. Gains 3x sexual skill XP, 2x cash from all sexual jobs. Doesn't get exhausted from lack of sleep, but must satisfy sexual needs daily or suffer penalties. Gains Well Rested from sex acts instead of sleeping. Includes all Trophy Wife bonuses.", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Slut", grantsPhysical: ["Slut"], grantsMental: [], removesOnGain: ["High Stamina", "Trophy Wife", "Shy", "Prudish"], removesSkillsOnGain: ["Sexually Skilled"], blocksTraits: ["High Stamina", "Trophy Wife", "Shy", "Prudish"], blocksSkills: ["Sexually Skilled"], slutSexualNeeds: true, sexualSkillMultiplier: 3, sexualJobCashMultiplier: 2, /* Trophy Wife bonuses included */ brothelXpMultiplier: 2, secretarySexCashMultiplier: 2, guaranteedClappingSuccess: true, guaranteedPrawnhubSuccess: true, setsChest: "giant", setsButt: "giant", setsGenitals: "loose vagina", genderLock: "female" }, "Himbo": { type: "corruption", category: "physical", description: "A lovable but dim muscular man", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Himbo", grantsPhysical: ["Himbo"], grantsMental: [], removesOnGain: ["Chill"], removesPhysicalOnGain: ["Muscular"], removesSkillsOnGain: ["Heavy Lifting"], blocksTraits: ["Chill"], blocksPhysical: ["Muscular"], blocksSkills: ["Heavy Lifting"], gymMultiplier: 2, maleRelationshipMultiplier: 2, setsChest: "flat masculine", setsButt: "flat masculine", setsGenitals: "big penis", genderLock: "male" }, /* NEW LABORATORY TRANSFORMATIONS */ "Angel": { type: "supernatural", category: "physical", description: "A radiant celestial being of divine purity and grace", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Angel", grantsPhysical: ["Angel"], grantsMental: [], removesOnGain: ["Blessed", "Humble", "Lucky"], removesPhysicalOnGain: [], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "medium", setsButt: "medium", setsGenitals: "tight vagina", setsHairColor: "blonde", setsChestMinimum: true, setButtMinimum: true, genderLock: "female", matureAdultBump: true }, "Naiad": { type: "supernatural", category: "physical", description: "A celestial water nymph blessed by the convergence of sunfish divinity and siren song", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Naiad", grantsPhysical: ["Naiad"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["Divine Sunfish", "Siren", "Sunfish"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Automaton": { type: "supernatural", category: "physical", description: "A mechanical being of clockwork precision and tireless efficiency", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Automaton", grantsPhysical: ["Automaton"], grantsMental: [], removesOnGain: ["Soul"], removesPhysicalOnGain: ["Cog", "Living Doll"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "tight vagina", genderLock: "female", matureAdultBump: true }, "Banshee": { type: "supernatural", category: "physical", description: "A wailing spirit born from pure despair and darkness", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Banshee", grantsPhysical: ["Banshee"], grantsMental: [], removesOnGain: ["Unlucky"], removesPhysicalOnGain: ["Darkness", "Disturbed"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "giant", setsButt: "large", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Cheshire Cat": { type: "supernatural", category: "physical", description: "A mischievous feline trickster with an ever-present grin", overridesAppearance: true, imagePath: "Images/Faces/Transformations/CheshireCat", grantsPhysical: ["Cheshire Cat"], grantsMental: [], removesOnGain: ["Lucky"], removesPhysicalOnGain: ["Mirrored", "Werecat"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Cupid": { type: "supernatural", category: "physical", description: "A divine archer of love whose presence ignites passion in all who meet her", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Cupid", grantsPhysical: ["Cupid"], grantsMental: [], removesOnGain: ["Charming"], removesPhysicalOnGain: ["Angel", "Heart"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "giant", setsButt: "giant", setsGenitals: "loose vagina", genderLock: "female", matureAdultBump: true }, "Dark Angel": { type: "supernatural", category: "physical", description: "A fallen celestial corrupted by darkness yet still touched by the divine", overridesAppearance: true, imagePath: "Images/Faces/Transformations/DarkAngel", grantsPhysical: ["Dark Angel"], grantsMental: [], removesOnGain: ["Blessed", "Unlucky"], removesPhysicalOnGain: ["Darkness"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Honeybee": { type: "supernatural", category: "physical", description: "A sweet and industrious bee-girl who produces enchanted honey", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Honeybee", grantsPhysical: ["Honeybee"], grantsMental: [], removesOnGain: ["Loyal", "Energetic"], removesPhysicalOnGain: ["Honey"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "giant", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Slime": { type: "supernatural", category: "physical", description: "A busty, mischievous slime girl who cannot help acting like a gremlin", overridesAppearance: true, imagePath: "Images/Faces/Laboratory/Slime", grantsPhysical: ["Slime"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["slime"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "huge", setsButt: "large", setsGenitals: "vagina", genderLock: "female", matureAdultBump: false }, "Jinko": { type: "supernatural", category: "physical", description: "A fierce tiger warrior with incredible strength and predatory instincts", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Jinko", grantsPhysical: ["Jinko"], grantsMental: [], removesOnGain: ["Wild"], removesPhysicalOnGain: ["Werecat"], removesSkillsOnGain: ["Combat"], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Kakuen": { type: "supernatural", category: "physical", description: "A wild and agile monkey-girl brimming with untamed energy", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Kakuen", grantsPhysical: ["Kakuen"], grantsMental: [], removesOnGain: ["Wild", "Energetic"], removesPhysicalOnGain: ["Fit"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Lizardman": { type: "supernatural", category: "physical", description: "A tough reptilian warrior with hardened scales and unyielding endurance", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Lizardman", grantsPhysical: ["Lizardman"], grantsMental: [], removesOnGain: ["Blunt"], removesPhysicalOnGain: ["Scaled", "Sturdy"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Ocelomeh": { type: "supernatural", category: "physical", description: "A cunning jaguar warrior with supernatural wisdom and lethal grace", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Ocelomeh", grantsPhysical: ["Ocelomeh"], grantsMental: [], removesOnGain: ["Wild", "Wise"], removesPhysicalOnGain: ["Werecat"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "giant", setsButt: "huge", setsGenitals: "loose vagina", genderLock: "female", matureAdultBump: true }, "Pyrow": { type: "supernatural", category: "physical", description: "A blazing imp infused with volcanic fire, immune to all temperatures", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Pyrow", grantsPhysical: ["Pyrow"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["Imp", "Inferno"], removesSkillsOnGain: ["Sexually Skilled"], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "tight vagina", genderLock: "female", matureAdultBump: true }, "Raiju": { type: "supernatural", category: "physical", description: "A lightning beast crackling with electric energy and feral lust", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Raiju", grantsPhysical: ["Raiju"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["Electrified", "Slut", "Were-Creature"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "loose vagina", setsChestMinimum: true, setButtMinimum: true, genderLock: "female", matureAdultBump: true }, "Salamander": { type: "supernatural", category: "physical", description: "A fire-forged lizard warrior immune to flames who can cook anywhere", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Salamander", grantsPhysical: ["Salamander"], grantsMental: [], removesOnGain: ["Wild"], removesPhysicalOnGain: ["Lizardman", "Inferno"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Satyros": { type: "supernatural", category: "physical", description: "A musical sheep-girl whose enchanting melodies captivate all who listen", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Satyros", grantsPhysical: ["Satyros"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["Alcoholic", "Weresheep"], removesSkillsOnGain: ["Music"], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Vampire": { type: "supernatural", category: "physical", description: "An immortal creature of the night who drains life from the living", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Vampire", grantsPhysical: ["Vampire"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["Thirsty", "Blood", "Definitely not a Vampire", "Totally not a Vampire"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "tight vagina", genderLock: "female", matureAdultBump: true }, "Kitsune": { type: "supernatural", category: "physical", description: "A mystical fox spirit with hypnotic powers and ancient wisdom", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Kitsune", grantsPhysical: ["Kitsune"], grantsMental: [], removesOnGain: ["Soul"], removesPhysicalOnGain: ["Mystic", "Werefox"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "huge", setsButt: "huge", setsGenitals: "tight vagina", setsChestMinimum: true, setButtMinimum: true, genderLock: "female", matureAdultBump: true }, "Anubis": { type: "supernatural", category: "physical", description: "A jackal-headed guardian of the dead, loyal and unyielding", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Anubis", grantsPhysical: ["Anubis"], grantsMental: [], removesOnGain: ["Loyal"], removesPhysicalOnGain: ["Guardian", "Werewolf"], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "large", setsGenitals: "vagina", genderLock: "female", matureAdultBump: true }, "Pharaoh": { type: "supernatural", category: "physical", description: "An all-powerful divine ruler who commands the very elements", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Pharaoh", grantsPhysical: ["Pharaoh"], grantsMental: [], removesOnGain: ["Chosen", "Dominant"], removesPhysicalOnGain: [], removesSkillsOnGain: ["Leadership"], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "large", setsButt: "huge", setsGenitals: "tight vagina", setsChestMinimum: true, setButtMinimum: true, genderLock: "female", matureAdultBump: true }, "Witch": { type: "supernatural", category: "physical", description: "A powerful witch, reborn through ancient ritual. Grants all traits given to Xantria.", overridesAppearance: true, imagePath: "Images/Faces/Transformations/Witch", grantsPhysical: ["Witch"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: [], removesSkillsOnGain: [], blocksTraits: [], blocksPhysical: [], blocksSkills: [], setsChest: "huge", setsButt: "giant", setsGenitals: "vagina", genderLock: "female", setsHairColor: "Black", setsSkinTone: "pale", questLocked: true, requiresQuest: "xanithar_rebirth" }, "Oni": { type: "supernatural", category: "physical", description: "A horned demon of the Sakazuki cup. Long silver hair, fangs, claws, and the strength of mountain spirits.", overridesAppearance: true, imagePath: "Images/Transformation/Oni_Female", grantsPhysical: ["Oni"], grantsMental: [], removesOnGain: [], removesPhysicalOnGain: ["Gym Bunny", "Athletic Build", "Fit"], removesSkillsOnGain: [], blocksTraits: ["Submissive"], blocksPhysical: ["Gym Bunny"], blocksSkills: [], setsChest: "huge", setsButt: "large", setsGenitals: "vagina", genderLock: "female", setsHairColor: "Silver", hairColorLock: "Silver", setsSkinTone: "pale", skinToneLock: "pale", matureAdultBump: true, questLocked: true, requiresQuest: "oni_ritual" }, "Femboy": { type: "lifestyle", category: "physical", description: "A soft, feminine boy.", overridesAppearance: true, imagePath: "Images/Faces/Laboratory/Femboy_Portrait", grantsPhysical: ["Femboy"], setsChest: "flat masculine", setsGenitals: "penis", genderLock: "male", setsHairColor: "Light Purple", setsSkinTone: "pale", setsAge: "Adult", lockedBodyParts: ["gender", "skinTone", "hairColor", "genitals", "age"] }, }>> <<set setup.miklaLines = {"none":["So thou comest to me bare of borrowed shapes. Good. I like to see the ember that freed me wearing nothing but itself.","No horns, no scales, no fur today. Only the small stubborn thing that walked into my grave and pulled me out of it. That is shape enough.","Thou wearest thine own face, and I confess I have grown fond of it. Sit. Warm thyself. The mountain is thine to visit whenever it pleases thee."],"Succubus":["A succubus in my hall. Careful where thou pointest all that hunger, little one, or I shall teach thee whose fire is older.","That silhouette could unmake kingdoms, and thou wearest it to visit an old dragon. I am flattered.","I can smell the want that comes off thee. Sit a while. Even I remember what it is to burn for a thing."],"Voluptuous Succubus":["More of thee to adore than the last time thou camest calling. The shape suits thine appetites.","Thou hast leaned wholly into ruin and desire and made it lush. I approve, as a queen approves of excess.","Every step thou takest is a temptation with a heartbeat. Do not let it go to thy head, ember. Mine is bigger."],"Incubus":["So the hunger wears a harder jaw today. A handsome ruin all the same.","An incubus at my hearth. Thy charm would work on lesser things than a dragon, but I enjoy watching thee try.","Thou art all appetite in a fine frame. Sit. Tell me whose dreams thou hast been walking through."],"Imp":["A little imp, all mischief and sharp teeth. Thou remindest me of my own smaller centuries. Do not set fire to my hall.","Small and wicked and grinning. I could hold thee in one claw, and yet thou freed me. Never let size fool a soul.","That crooked little smile has trouble written under it. Go on then. Amuse me."],"Cerberus":["Three heads and one loyal heart. Guard well, hound. There is nothing a dragon respects more than a thing that will not let go.","I hear thee before I see thee, all snarl and devotion. Come. Even queens keep good beasts close.","Thou art built to hold a threshold against the dark. I held one alone for centuries. We understand each other."],"Half-Dragon Gyaru":["There she is. The piece of me thou wearest, worn loud and bright and utterly without shame. I could not have chosen better.","Come closer, little flame. Let me look at what my fire made of thee. Magnificent. Absolutely mine.","Scales and swagger both. Thou tookest the oldest thing in the world and made it strut. I am so proud I could roar.","Every soul on this island will feel the heat come off thee now, and none of them will know it began as my debt paid.","Half of thee is dragon, and it is the half that grins the widest. Good. That is exactly the half I meant to give.","Thou wearest my gift as though it were always thine. It was, in a way. I only handed thee the match.","Look at those wings. I remember when they were mine alone. It gladdens me to see them carried by one who earned them.","Come sit at thy queen's side, kin. For that is what thou art now, whether either of us planned it.","The fire in thy belly answers the fire in mine whenever thou art near. Dost thou feel it? That is family, in the oldest tongue.","Thou art brash and bright and burning and a little bit dragon, and I find I am jealous of no one who gets to stand near thee.","Wear it proudly, and wear it always. There is no shame in being the loudest fire in the room when the fire is this good.","I gave thee a seed and thou grew a wildfire. This is the finest debt I have ever paid, and I have paid some grand ones.","My blood runs warm in thee. Should any creature ever raise a hand against thee, remember thou hast a dragon who calls thee kin.","Strut for me, ember. Let me see the whole ridiculous glorious shape of what we made together. Yes. Just so.","Of all the forms thou couldst wear into my hall, this is the one that makes an old cold queen feel warm. Stay a while, kin."],"Werecat":["A cat today. Restless and clever and pleased with thyself. I have known a hundred of thy kind and liked most of them.","Thou movest as though every surface belongs to thee. It does not, but I admire the certainty.","Purr if thou wilt. Even a dragon can appreciate a warm predator that chooses comfort over the hunt."],"Werewolf":["A wolf in my hall, all shoulders and duty. Good. Those with a pack in their heart make the finest friends and the worst foes.","I smell the wild on thee and the loyalty under it. Thou wouldst die for thine own. So would I, now that I have my own again.","Stand tall, wolf. Thou hast the frame to hold a hard night off weaker backs. Use it kindly."],"Werebunny":["Soft ears and a heart that will not sit still. Thou art quicker than anything in this mountain, myself included.","A rabbit at a dragon's hearth, and unafraid. That is either great courage or great folly. With thee I never can tell.","All that energy. If I could bottle what comes off thee I would never need the sun again."],"Werefox":["A fox. Sly eyes and a smile that has already counted my treasure. I would be cross if I were not charmed.","Thou hast the look of a soul three steps ahead of everyone else. Careful. I have had longer to learn that game.","Cunning suits thee. Sit and scheme by my fire. It is warmer than whatever hedge thou wast plotting in."],"Weresheep":["Soft wool and a softer heart. Thou art kindness given a body, and the world is cruel to such things. Let it not dull thee.","Warm and gentle and calm. Dost thou know how rare it is to walk into a dragon's lair carrying no edge at all?","Come, gentle one. Even old fire likes something soft to look upon between the centuries."],"Hucow":["Heavy and warm and made to nurture. There is an old power in that, older than my flame. Let no soul call it lesser.","Thou art abundance walking. I ruled the burning heart of the world and I still find that a wonder.","Sit, and rest thy weight. Thy body was shaped to give. See that thou takest, now and then, as well."],"Trophy Wife":["Draped and adorned and lovely to behold. Someone has made an ornament of thee. I hope thou choosest to be worn.","Every jewel on thee begs to be looked at, and thou wearest them as though thou knowest it. Vanity is a small honest sin.","Beauty as a lifelong craft. I respect the discipline. A dragon knows the labor of maintaining a legend."],"Ojou":["Such refinement. Thou lookest down thy nose at my hall, and I let thee, for thou hast the bearing to earn it.","A highborn air on the very one who dragged me out of a grave. The contrast delights me endlessly.","Poise like a drawn blade. Sit, my lady, and let two proud creatures share a fire."],"Gym Bunny":["All muscle and cheerful sweat. Thou treatest thy body like a temple thou art gleefully rebuilding. I approve.","Strong and bright and bouncing with it. I could set thee to hauling boulders and thou wouldst thank me for the fun.","There is a joy in thy strength that has nothing to prove. Rare. Most power I have known was hungry. Thine simply plays."],"E-Girl":["Painted in strange bright colors and glowing from within. Thou art a creature of an age I do not wholly understand, and I like thee anyway.","All attitude and neon. In my day we frightened villages. Thou frightenest them differently, I think, and enjoyest it more.","Come here, little spark of neon light. Show the old dragon what passes for mischief these days."],"Punk":["Studs and ink and a snarl at the world. Thou and I both know what it is to refuse a cage. Wear thy defiance loud.","Every spike on thee says come no closer, and yet here thou art at my hearth. I am honored by the exception.","Rage suits thee when thou aimest it well. I ruled on anger for a while. It burns clean if thou dost not let it eat the roots."],"Gyaru":["Bronzed and loud and gloriously certain of thyself. This is the shape that becomes half of my own gift. It was always going to dazzle.","All that shine and swagger. Thou struttest into a dragon's lair as though thou ownest the light. Keep that. It will serve thee.","Bright hair, brighter attitude. I find I cannot look away, and I am not a creature accustomed to being upstaged."],"Siren":["A voice beneath thy voice, made to pull ships onto rocks. Sing for me sometime. I should like to hear what could rival my roar.","Thou movest like water and soundest like longing. Even my old heart leans toward that song. Use it gently, or do not. I shall not judge.","The sea gave thee a weapon dressed as a gift. I know that shape of thing. Wield it knowing what it is."],"Living Doll":["Smooth and still and perfect, a soul poured into porcelain. There is a strange peace in thee that I almost envy.","Thou hast made thyself a lovely stillness. I was bound in stillness for centuries and hated every moment. That thou choosest it fascinates me.","Every joint of thee is deliberate. A crafted thing that walked in of its own will. Sit, little doll, and be admired."],"Dominatrix":["Thou wearest command like a second skin. I know that feeling. A word from thee bends spines. A word from me once bent a mountain.","Leather and certainty. Thou hast learned that power is mostly the nerve to claim it. I taught myself that over a longer life.","Kneel, thou sayest to the world, and the world considers it. Not to me, ember. But I do enjoy watching thee try it on lesser things."],"Slut":["Shameless and glowing with it. Thou hast made appetite into an art and refused to apologize for a single stroke. Good.","Thou wantest, openly, always, and the wanting makes thee radiant. The prudish will never understand. I do.","Come in, come in. There is no hunger thou couldst bring into my hall that would scandalize a creature as old as fire."],"Himbo":["Broad and beautiful and untroubled by a single thought. There is a sweetness in that I would not trade for all my cunning.","Thou art built like a wall and kind as a summer. The world does not deserve so gentle a mountain of a soul.","Not much stirring behind those bright eyes, and I mean it fondly. Sit, big one. Rest is thy natural state and it looks well on thee."],"Angel":["Light comes off thee, clean and near unbearable. I dwelt in the dark a long time. Come only as near as is kind, and I shall be glad of thee.","A winged and blessed thing at my hearth. My fire and thy halo should not sit so well together, and yet they do.","Thou art mercy given feathers. I have known little of it. Teach me sometime how thou carriest so much and dost not tire."],"Naiad":["Water born and singing of the deep. Thy nature and mine were made to quarrel, fire and flood, yet here we share a quiet fire.","The old sea moves in thee. I ruled the burning heart; thou carriest the drowned one. Between us we hold the whole wild world.","Cool and deep and patient. Thou art the one element that could put me out, and thou choosest instead to sit and talk. I remember that kindness."],"Automaton":["So thou hast donned the clockwork shell again, the very shape that unmade my chains. I shall never look on it without gratitude.","Gears where a heart should be, and yet thou freed me with it. Cold hands did a warm thing. I do not forget.","That form broke my binding. Wear it before me and I see again the moment the pale fire died. Thou art always welcome in it."],"Banshee":["A wail lives in thy throat, the sound of endings. I have caused a few. We shall get along, thou and I.","Sorrow and dread wear thee like a shroud, and still thou camest to sit with an old dragon. Even grief seeks warmth.","Thou art the cry the dying hear. Fearsome. Yet to me thou art only a guest, and a quiet one. Stay as long as thou wilt."],"Cheshire Cat":["Now thou art here and now thou art nearly not. That grin arrives before the rest of thee. It unnerves better creatures than me and amuses this one.","A riddle wearing whiskers. I never know if I speak to thee or to the space thou hast left. Delightful.","Thou fadest at the edges, mischief made half of moonlight. Do not vanish entirely. I have grown to like the conversation."],"Cupid":["Little bearer of arrows, thou aimest at hearts and rarely missest. Point that bow away from an old dragon. Mine is a long way to fall.","Love follows thee about like a lost hound. A gentler power than fire, and harder to govern. I do not envy thee the aim of it.","Thou makest souls adore one another with a look. I could rule the world with that, and thou usest it to make matches. There is a lesson in thee."],"Dark Angel":["Fallen light, and lovelier for the falling. I know the shape of a thing cast out. Sit by one who was buried and rose.","Blackened wings and a blessing turned bitter. The world made thee cruel and thou wearest it like finery. I respect the alchemy.","Thou art the beautiful ruin of something holy. We are cut from a similar cloth, thou and I. Neither of us stayed where we were put."],"Honeybee":["Golden and busy and sweet, with a sting held in reserve. The best gentle things keep an edge. Thou dost.","Thou hummest with purpose, ever building, ever giving. I ruled by taking. Thy way looks the warmer one.","Sweetness and industry both. Bring me honey sometime, little worker, and I shall tell thee secrets older than thy hive."],"Slime":["Thou hast no fixed edge today, only a bright wobbling will. Fascinating. I could not pour myself into a cup, and thou art half liquid by choice.","Formless and glistening and grinning through it. There is a freedom in having no shape to defend. I almost envy the goo of thee.","Poke thee and thou ripples. A dragon made of fire and a soul made of slime, sharing a hearth. The world is stranger than my prison let me recall."],"Jinko":["A striped huntress, all coiled muscle and old jungle wisdom. Thou movest like the ambush before it happens. I do love a proper predator.","Fierce and warm at once, with the blood of the tiger. Thou couldst pin most things in this world. Not me, but I enjoy the confidence.","The wild sits easy on thee, disciplined into grace. Sit, huntress. Two apex things can share a fire without a quarrel."],"Kakuen":["Quick and clever and never still, all mischief in a nimble frame. Thou wouldst have the run of my hoard in a heartbeat if I let thee.","Thou hast the bright restless spirit of the high branches. It wearies me to watch and gladdens me at once.","Play, climb, chatter. Thou remindest a heavy old creature what lightness looks like. Do not stop on my account."],"Lizardman":["Scaled and blunt and near unbreakable. A distant lesser cousin of mine own kind, and I say that with fondness, not scorn.","Sturdy as a wall and twice as patient. Thou and I share the old cold blood. Come sit where it is warm and let it run quick a while.","Thou dost not flinch and thou dost not fuss. I have met dragons with less spine. Well met, scaled one."],"Ocelomeh":["A wise hunter wearing spots and old knowing. There is the jaguar's sight in thee, the kind that reads a soul before it speaks.","Fierce and thoughtful both, a rare pairing. Thou wouldst have been a priest or a killer in the old days. Perhaps both.","Thou carriest the jungle's memory in thine eyes. Tell me a piece of it sometime. I have been underground too long."],"Pyrow":["Fire in thy blood, like mine. Dost thou feel the kinship of it, that low roar under the skin? I do, every time thou enterest.","Thou burnest, little one, truly burnest, and the heat off thee greets mine like an old friend. Welcome, ember. Truly.","Flame answers flame. Of all who visit, thou of the fire come nearest to grasping what I am. Sit close. The heat will harm neither of us."],"Raiju":["Lightning in a lithe frame, crackling with too much life. Thou art storm where I am furnace, the sky and the mountain sharing a hearth.","Thou movest faster than sight and spark where thou passest. Careful near an old dragon's hoard. It is flammable, and so am I fond of it.","All that voltage barely held in skin. I like a creature that hums with power it can scarcely contain. I was such a one, once."],"Salamander":["Kin of the flame, born of embers as I was. The mountain knows thee. Feel how the lava leans toward thee when thou passest.","Fire lizard, thou art the nearest thing to mine own blood that walks this island. Come warm thyself where the warmth is truest.","Thou wast made in heat and made for it. In my hall thou art no guest but a homecoming. Stay."],"Satyros":["Wine and music and hooves that will not stop dancing. Thou bringest a festival into a place that knew only silence. Bless thee for it.","Thou art revelry given legs. Play me something, hooved one, and I shall try to recall how to be merry.","Drink, dance, sing. Thou remindest me the world went on being joyful while I lay bound. I am glad of the reminder, truly."],"Vampire":["A drinker of blood, deathless and pale. Two immortals sharing a fire. Do not eye my throat. Mine would be a poor and scalding vintage.","Elegant and hungry and old, though not so old as me. I have watched empires that thy kind merely fed upon. Sit, night thing. Talk.","Thou wearest death like evening finery. There is a discipline in an eternity of appetite. I know it well. We shall get on."],"Kitsune":["Foxfire and many tails and older magic than thy face admits. Do not weave thine illusions on a dragon, trickster. I invented a few of them.","A spirit fox in my hall, all mystery and mischief. I feel the enchantment come off thee, and I let it, for I am curious what thou wilt try.","Thy fires are cold and blue and clever; mine are red and honest. Between us we could fool or burn the whole world. Let us not. Let us talk instead."],"Anubis":["Guardian of the dead, with the head of the jackal and a solemn heart. Thou hast the bearing of one who weighs souls. Weigh mine gently. It has carried much.","Thou standest as the old lords of tombs stood, patient and unafraid of endings. I respect a soul that has made its peace with the dark.","Keeper of thresholds. I was kept at one for centuries, on the wrong side of it. That thou guard them fairly means more to me than thou knowest."],"Pharaoh":["A crown sits on thee as though the sun itself set it there. I know the weight of ruling. Wear it straighter than most kings I have outlived.","Thou bearest the old sovereign light, touched by gods and certain of it. Two monarchs in one hall. Let us share the throne of this conversation.","Divine and imperious and lovely. In another age our peoples might have warred or wed. Today we merely talk, and I prefer it."],"Witch":["Steeped in borrowed power and clever with it. Do not test thy little cantrips against dragon fire, but I do enjoy an ambitious mind.","Thou hast bent the hidden arts to thy hand. I bent the earth to mine, once. We are both thieves of forces larger than ourselves. Sit, colleague.","Herbs and hexes and a knowing look. There is real craft in thee. Show me something small and clever sometime. I have grown bored of grand things."],"Oni":["Horned and red and roaring, a demon of the old mountains. Very nearly mine own aesthetic, ember. I approve of the horns especially.","Thou wearest wrath as armor and it becomes thee. I know that heat. Let it guard thee, but never let it drive.","Fearsome and fanged and grinning through it. In another telling thou and I would be the monsters of the story. I have made peace with the role. Hast thou?"],"Femboy":["Soft and pretty and untroubled by anyone's notion of what thou ought to be. That defiance is quieter than most and no less brave.","Thou wearest thine own grace and lets the world sort out its confusion. I ruled a burning kingdom on less certainty than that.","Lovely as thou art, and exactly as thou choosest to be. A dragon of all creatures will not tell thee to be otherwise. Sit, pretty one."]}>> /* ---------------------------------- */ /* --- COMBINATION-ONLY TRAITS --- */ /* ---------------------------------- */ /* These traits can ONLY be obtained via trait combination, not character creation */ <<set setup.combinationOnlyTraits = [ /* Transformation Ingredient Physical Traits */ "Fangs", "Pointed Ears", "Glowing Eyes", "Claws", "Wings", "Tail", /* "Lactating" - now available at Lamprey's Tomes */ /* Transformation Ingredient Mental Traits */ "Mischievous", "Docile", "Feral", "Predatory", "Maternal", "Paternal", "Breeding Obsessed", "Heat Cycles", "Pack Minded", "Nocturnal", "Territorial", "Shameless", "Insatiable", "Praise Seeking", "Obedient", "Collar Loving", "Rebellious", "Corrupted", "Cunning", /* Intermediate Combination Traits (Tier 1) */ "Temptress", "Sadist", "Masochist", "Milky", "Neko", "Inu", "Imp-Touched", "Mommy Energy", "Devoted", "Exhibitionist", "Savage", "Genius", /* Full Transformation Traits (Tier 2) */ "Succubus", "Imp", "Cerberus", /* "Incubus", - temporarily disabled */ "Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep", "Hucow", "Trophy Wife", "Gym Bunny", "E-Girl", "Punk", "Gyaru", "Ojou", "Siren", "Living Doll", "Dominatrix", "Slut", "Himbo", /* New Laboratory Transformations */ "Angel", "Naiad", "Automaton", "Banshee", "Cheshire Cat", "Cupid", "Dark Angel", "Honeybee", "Jinko", "Kakuen", "Lizardman", "Ocelomeh", "Pyrow", "Raiju", "Salamander", "Satyros", "Vampire", "Kitsune", "Anubis", "Pharaoh", /* Secret Variant Transformations */ "Voluptuous Succubus", /* Quest-locked supernatural transformations */ "Oni", /* Laboratory full transformation */ "Half-Dragon Gyaru" ]>> /* Stereotype traits */ <<set setup.stereotypeTraits = { "Nerd": "Academically focused", "Geek": "Obsessed with hobbies", "Prep": "Popular and preppy", "Tomboy": "Masculine interests", "Femboy": "Feminine presentation", "Diva": "Demanding personality", "Goth": "Dark aesthetic" }>> /* Available skills */ <<set setup.availableSkills = { "Math Skills": "Good with numbers", "Coding": "Programming ability", "Dancing": "Skilled dancer", "Plumbing": "Fix pipes and drains", "High Heels Proficient": "Walk in heels easily", "Swimmer": "Strong swimming ability", "Swimming": "Strong swimming ability", "Sexually Skilled": "Experienced in intimacy", "Modeling": "Posing and presentation", "Makeup": "Cosmetics application", "Cooking": "Culinary skills", "Photography": "Camera and composition", "Maid": "Cleaning and service", "Singing": "Vocal talent", "Serving": "Food and beverage service", "Hair Styling": "Hair cutting and styling", "Cleaning": "Tidying and organizing", "Combat": "Fighting skills", "Persuasion": "Convincing others", "Medicine": "Medical knowledge", "Trading": "Negotiation skills", "Stealth": "Moving unseen", "Driving": "Vehicle operation", "Lock Picking": "Opening locks", "First Aid": "Basic medical care", "Gardening": "Plant cultivation", "Construction": "Building skills", "Heavy Lifting": "Moving heavy objects", "Social Media": "Online presence management", "Baking": "Pastry and bread making", "Public Speaking": "Confident speaker", "Writing": "Creative and technical writing", "Art": "Artistic ability", "Painting": "Visual art creation", "Music": "Musical talent", "Guitar": "String instrument", "Piano": "Keyboard instrument", "Acting": "Performance skills", "Teaching": "Educating others", "Sales": "Selling products", "Management": "Leadership skills", "Accounting": "Financial management", "Legal Knowledge": "Understanding of law", "Foreign Language": "Speaks another language", "Languages": "Multilingual ability", "Martial Arts": "Combat training", "Athletics": "Physical sports", "Yoga": "Flexibility and balance", "Retail": "Store operations", "Tech-Savvy": "Technology expertise", "Troubleshooting": "Problem diagnosis", "Forklift Certified": "Heavy machinery", "Product Knowledge": "Item expertise", "Inventory Management": "Stock control", "Customer Service": "Client assistance", "Meditation": "Mindfulness practice", "Business": "Commercial acumen", "Finance": "Money management", "Investigation": "Research skills", "Fishing": "Angling ability", "Mechanical Repair": "Fix machines", "Basketball": "Court sports", "Performance": "Stage presence", "Gaming": "Video game skills", "Leadership": "Guiding others", "Combat Training": "Fight instruction", "Quick Learner": "Learn skills faster. Gain +50% experience from all activities." }>> /* ---------------------------------- */ /* --- PLAYER STATUS --- */ /* ---------------------------------- */ <<set $homeless = true>> <<set $ownsHouse = false>> <<set $houseLocation = null>> <<set $housePurchaseDate = null>> <<set $jobs = []>> <<set $money = 0>> <<set $musicianRep = 0>> <<set $influencerData = {followers: 0, posts: 0, brandDeals: 0}>> <<set $negotiatorRep = 0>> <<set $negotiatorCasesToday = {day: 0, count: 0}>> <<set $modelData = {tier: 1, xp: 0, totalShoots: 0}>> <<set $pornStarData = {rep: 0, scenes: 0, earnings: 0}>> <<set $busDriverData = {tier: 1, xp: 0, totalShifts: 0, totalTips: 0, actionCounts: {kind: 0, dominant: 0, submissive: 0, aggressive: 0, patient: 0, confident: 0, flirty: 0, professional: 0}}>> <<set $fitnessTrainerData = {tier: 1, xp: 0, totalSessions: 0, totalEarnings: 0, sexualEncounters: 0, actionCounts: {encourage: 0, pushHard: 0, spotCarefully: 0, jokeAround: 0, compete: 0, flirt: 0, intimidate: 0, physicalAssist: 0}}>> <<set $discoveredJobs = []>> <<set $sideJobs = []>> <<set $questData = {active: {}, completed: {}, failed: {}, discovered: []}>> <<set $questUnlocks = []>> /* --- CAFE OWNERSHIP SYSTEM --- */ <<set $cafeOwnership = {owned: false, cafeName: "Maid Cafe", questsCompleted: [], dayPurchased: 0, upgrades: {decor: 0, kitchen: 0, furniture: 0, entertainment: 0, vipRoom: 0, staffRoom: 0}, staff: [], hasManager: false, finances: {totalRevenue: 0, totalExpenses: 0, totalProfit: 0, yesterdayRevenue: 0, yesterdayExpenses: 0, yesterdayProfit: 0}, reputation: 0, customersToday: 0, menuItems: [], inventory: {flour: 0, sugar: 0, teaLeaves: 0, butter: 0, eggs: 0, freshFish: 0, vegetables: 0, coffeeBeans: 0, milk: 0, chocolate: 0, berries: 0, cream: 0, exoticSpices: 0, honey: 0, vanilla: 0, edibleFlowers: 0}, playerCookingProf: 0, lastMilkProduced: 0, lastHoneyProduced: 0, pendingSupplierOrder: null, pendingSupplierOrders: []}>> <<set $totalDonatedToCity = 0>> <<set $totalHoursWorked = 0>> <<set $totalMoneyEarned = 0>> <<set $constructionCompleted = 0>> /* ---------------------------------- */ /* --- CONSTRUCTION SYSTEM --- */ /* ---------------------------------- */ <<set $constructionProjects = {}>> <<set $gardenBuilt = true>> <<set $homeRenovated = false>> <<set $lastConstructionCost = 0>> <<set $lastConstructionProject = "">> <<set $lastConstructionLabor = 0>> <<set $lastConstructionProjectCompleted = false>> /* ---------------------------------- */ /* --- HOME GARDEN SYSTEM --- */ /* ---------------------------------- */ <<set $gardenData = {plots: [], maxPlots: 0, gardenEvents: []}>> <<set $seedInventory = {}>> /* --- VENDING MACHINE SYSTEM (owner system removed) --- */ /* ---------------------------------- */ /* --- FISHING INVENTORY & BOAT --- */ /* ---------------------------------- */ <<set $fishInventory = []>> <<set $fishBucketCount = 0>> <<set $giantChickenUnlocked = false>> <<set $giantChickenRideCount = 0>> <<set $fishBucketBlackoutPending = false>> /* ---------------------------------- */ /* --- JUNGLE SYSTEM --- */ /* ---------------------------------- */ <<set $jungleMaterials = 0>> <<set $jungleCampBuilt = false>> <<set $foundMysteriousBeam = false>> <<set $foundRuins = false>> <<set $discoveredOvergrownLab = false>> <<set $overgrownLabUnlocked = false>> <<set $labSecurityDisabled = false>> <<set $slimeTubeBroken = false>> <<set $blueOrbCount = 0>> <<set $blueOrbFound = false>> <<set $craftedTraitBonuses = {}>> <<set $combinerIngredients = []>> <<set $cropInventory = {}>> <<set $brickCrafted = false>> <<set $discoveredRecipes = []>> <<set $ruinsPuzzleAttemptedToday = false>> <<set $ruinsPuzzleSolved = false>> <<set $foundStoneTablet = false>> <<set $discoveredHotSpring = false>> <<set $discoveredShrine = false>> <<set $discoveredCleanRoom = false>> <<set $discoveredOasis = false>> <<set $cursedEnergy = { count: 0, lastDay: -999 }>> <<set $slimeStored = 0>> <<set $slimeStorageMax = 100>> <<set $slimePossessionActive = false>> <<set $slimePossessionPreState = null>> <<set $slimePossessionTarget = null>> <<set $slimePossessionBodyLocation = null>> <<set $discoveredManor = false>> <<set $discoveredHiddenLagoon = false>> <<set $queshaIntroComplete = false>> <<set $diveBreath = 0>> <<set $diveStamina = 0>> <<set $diveLoot = []>> <<set $diveCurrentSite = "">> <<set $diveCurrentDepth = 0>> <<set $diveLastResult = null>> <<set $queshaSwimmingTaught = false>> <<set $diveGear = []>> <!-- DIVE_OVERHAUL_INIT_START --> <<set $diveMaterials = {}>> <<set $diveScrap = 0>> <<set $diveConsumables = []>> <<set $diveUpgrades = []>> <<set $diveGearSet = null>> <<set $sunfishGoldStash = []>> <<set $palidEyeActive = false>> <<set $palidTouchExpireDay = 0>> <<set $traitAbilityCharges = {}>> <<set $darkAngelExhaustionPending = false>> <<set $diveCombat = null>> <<set $diveCombatResult = null>> <<set $tamedCreature = null>> <<set $tamedCreatureCharges = 0>> <<set $blockNextPredatorHit = false>> <<set $pendingTameCreature = null>> <<set $diveNewTraits = []>> <<set $combatAbilityCharges = {}>> <!-- DIVE_OVERHAUL_PHASE6_INIT_START --> <<set $pendingLoot = []>> <<set $sunfishGoldRevealed = []>> <!-- DIVE_OVERHAUL_PHASE6_INIT_END --> <!-- DIVE_OVERHAUL_INIT_END --> <<set $queshaAckedFeline = false>> <<set $queshaSinkerRescued = false>> <<set $queshaAckedTraits = []>> <<set $queshaAckedFire = false>> <<set $shrineGlyphsFound = []>> <<set $shrineFound = false>> <<set $shrinePilgrim = false>> <<set $shrineQuestAccepted = false>> <<set $shrineTriangulationDone = false>> <<set $queshaTrenchPermit = false>> <<set $shrineLastVisitDay = 0>> <<set $sunfishDayUnlocked = false>> <<set $sunfishDayAccepted = false>> <<set $sunfishDayYear = 0>> <<set $sunfishDayLastFiredDay = 0>> <<set $queshaRecruitState = { maidCafe: false, techStore: false, docks: false }>> <<set $discoveredCliff = false>> <<set $discoveredCragside = false>> <<set $discoveredFrostspire = false>> <<set $discoveredIronBowl = false>> <<set $flawlessGemInventory = {}>> <<set $dragonAltarGems = []>> <<set $dragonEntranceOpen = false>> <<set $metDragonQueen = false>> <<set $veradinMet = false>> <<set $veradinTrust = false>> <<set $foundVeradinHeirloom = false>> <<set $discoveredForge = false>> <<set $discoveredDesertRuins = false>> <<set $relicInventory = []>> <<set $islandLoreAsked = []>> <<set $islandLoreViewing = "">> <<set $islandLoreReported = false>> <<set $hasClawToothNecklace = false>> <<set $veradinHasClawTooth = false>> <<set $miklaArrivalAnswer = "">> <<set $miklaTownHallInvestigated = false>> <<set $miklaChildCheckLocations = []>> <<set $miklaChildCheckLast = "">> <<set $miklaCityReported = false>> <<set $supplyWarehouseDays = []>> <<set $supplyShipDepartDay = -1>> <<set $supplyShipReturned = false>> <<set $supplyVoyageCount = 0>> <<set $supplyVoyageDone = false>> <<set $supplyDocksReported = false>> <<set $supplyReported = false>> <<set $skyObservedRegions = []>> <<set $skyObserveDay = -1>> <<set $skyWatchedFlip = false>> <<set $skyDesertLie = false>> <<set $skyReported = false>> <<set $skyRiteUnlocked = false>> <<set $skyRiteLastDay = 0>> <<set $forcedWeather = null>> <<set $skyObserveReturn = "">> <<set $skyLastRealLocation = "">> <<set $dragonDirectiveGiven = false>> <<set $dragonReleaseStep = 0>> <<set $dragonFreed = false>> <<set $supplyCaptainAsked = false>> <<set $relicFindsToday = 0>> <<set $relicFindsDay = -1>> <<set $lastRefine = null>> <<set $discoveredTundra = false>> <<set $flonaMet = false>> <<set $discoveredFrozenLake = false>> <<set $discoveredStandingStones = false>> <<set $discoveredFlonaTent = false>> <<set $discoveredTundraCave = false>> <<set $discoveredTaiga = false>> <<set $discoveredMist = false>> <<set $hasManorKey = false>> <<set $manorUnlocked = false>> <<set $manorMirrorShattered = false>> <<set $cleanRoomSolved = false>> <<set $cleanRoomProgress = 0>> <<set $ojou_refinement = 0>> <<set $ojou_refinementLifetime = 0>> <<set $ojou_hasCellarKey = false>> <<set $ojou_descended = false>> <<set $ojou_journalEntriesRead = 0>> <<set $ojou_transformed = false>> <<set $ojou_wineVaultRestored = false>> <<set $ojou_drawingRoomRestored = false>> <<set $ojou_libraryRestored = false>> <<set $ojou_teaRoomRestored = false>> <<set $ojou_bedchamberRestored = false>> <<set $ojou_libraryBooksRead = []>> <<set $ojou_teaActiveDay = 0>> <<set $ojou_lastTeaDay = 0>> <<set $ojou_lastVanityDay = 0>> <<set $ojou_wineInventory = []>> <<set $ojou_lastRecitalDay = -7>> <<set $ojou_lastRecitalPayout = 0>> /* Generate random obelisk codes for this playthrough */ <<set $obeliskCodes = []>> <<for _oi = 0; _oi < 7; _oi++>> <<set _code = [random(0, 9), random(0, 9), random(0, 9), random(0, 9)]>> /* Ensure code isn't 0000 */ <<if _code[0] === 0 && _code[1] === 0 && _code[2] === 0 && _code[3] === 0>> <<set _code[0] = random(1, 9)>> <</if>> <<run $obeliskCodes.push(_code)>> <</for>> /* Generate volcano red herring code */ <<set $volcanoRedHerring = [random(0, 9), random(0, 9), random(0, 9), random(0, 9)]>> /* Generate random codex price between 1000 and 3000 */ <<set $codexPrice = (Math.floor(random(10, 30)) * 100) + random(1, 99)>> <<set $lastObeliskWeek_jungle = -1>> <<set $lastObeliskWeek_desert = -1>> <<set $lastObeliskWeek_mountain = -1>> <<set $lastObeliskWeek_manor = -1>> <<set $lastObeliskWeek_volcano = -1>> <<set $ownsCogBook = false>> <<set $ownsSlimeRecipe = false>> <<set $codexEntry_jungle = "">> <<set $codexEntry_desert = "">> <<set $codexEntry_mountain = "">> <<set $codexEntry_manor = "">> <<set $shrineOfferCount = 0>> <<set $shrineLastOfferDay = -1>> <<set $shrineMysticAwarded = false>> <<set $shrineTotalDeposited = 0>> <<set $ruinsPathOrder = []>> <<set $volcanoHeatSteps = 0>> <<set $desertExposureSteps = 0>> <<set $oasisAltarDeposits = []>> <<set $oasisAltarConsumed = []>> <<set $divineSunfishAwarded = false>> <<set $fishTank = null>> <<set $boat = null>> <<set $boatUpgrades = []>> <<set $tackle = { hook: null, line: null }>> <</silently>> /* ---------------------------------- */ /* --- SHADY SHOP TRACKING --- */ /* ---------------------------------- */ <<set $shadyDealsToday = 0>> <<set $lastFenRisTrainingDay = -1>> /* ---------------------------------- */ /* --- TRAIT COMBINATION TRACKING --- */ /* ---------------------------------- */ <<set $failedTraitCombinations = []>> /* ---------------------------------- */ /* --- RELATIONSHIP SYSTEM --- */ /* ---------------------------------- */ <<set setup.relationshipLevels = [ {level: -1, name: "Disliked", minPoints: -50, maxPoints: -1, color: "#ff4444"}, {level: 0, name: "Stranger", minPoints: 0, maxPoints: 24, color: "#666666"}, {level: 1, name: "Acquaintance", minPoints: 25, maxPoints: 74, color: "#51cf66"}, {level: 2, name: "Friend", minPoints: 75, maxPoints: 174, color: "#4dabf7"}, {level: 3, name: "Close Friend", minPoints: 175, maxPoints: 424, color: "#9b59b6"}, {level: 4, name: "Best Friend", minPoints: 425, maxPoints: 599, color: "#ff6b9d"}, {level: 5, name: "Confidant", minPoints: 600, maxPoints: 9999, color: "#ffd700"} ]>> /* Helper to get relationship level data by level number */ <<set setup.getRelationshipLevelData = function(level) { for (var i = 0; i < setup.relationshipLevels.length; i++) { if (setup.relationshipLevels[i].level === level) { return setup.relationshipLevels[i]; } } return setup.relationshipLevels[1]; /* Default to Stranger */ }>> /* Calculate level from points */ <<set setup.calculateRelationshipLevel = function(points) { if (points < 0) return -1; /* Disliked */ if (points < 25) return 0; /* Stranger */ if (points < 75) return 1; /* Acquaintance */ if (points < 175) return 2; /* Friend */ if (points < 425) return 3; /* Close Friend */ if (points < 600) return 4; /* Best Friend */ return 5; /* Confidant */ }>> /* Initialize relationships for ALL NPCs */ <<set $npcRelationships = {}>> /* Add all NPCs from the $npcs array to relationships */ <<for _i = 0; _i < $npcs.length; _i++>> <<set _npcName = $npcs[_i].name>> <<set $npcRelationships[_npcName] = { level: 0, points: 0, levelName: "Stranger", bestFriendUnlocked: false }>> <</for>> /* Initialize NPC memory and evolution systems */ <<set $npcMemory = {}>> <<set $npcDialogueHistory = {}>> <<set $npcEvolution = {}>> <<set $npcRomance = {}>> <<set $homeVisitor = null>> /* ---------------------------------- */ /* --- NPC-TO-NPC RELATIONSHIPS --- */ /* ---------------------------------- */ /* Initialize NPC-to-NPC relationship matrix */ <<set $npcToNpcRelationships = {}>> <<set $npcSocialEvents = []>> <<set $discoveredNpcBonds = {}>> <<set $socialPanelOpen = false>> /* NPC-to-NPC Relationship Types */ <<set setup.npcRelationshipTypes = { "family_sibling": { name: "Sibling", basePoints: 200, color: "#ff6b9d" }, "family_parent": { name: "Parent", basePoints: 250, color: "#ff6b9d" }, "family_child": { name: "Child", basePoints: 250, color: "#ff6b9d" }, "friends": { name: "Friends", basePoints: 100, color: "#4dabf7" }, "best_friends": { name: "Best Friends", basePoints: 300, color: "#51cf66" }, "rivals": { name: "Rivals", basePoints: -25, color: "#ff4444" }, "enemies": { name: "Enemies", basePoints: -50, color: "#cc0000" }, "romantic": { name: "Romantic Partner", basePoints: 350, color: "#e91e63" }, "ex_romantic": { name: "Ex-Partner", basePoints: -10, color: "#9e9e9e" }, "coworkers": { name: "Coworkers", basePoints: 50, color: "#ffd43b" }, "acquaintances": { name: "Acquaintances", basePoints: 25, color: "#666666" }, "strangers": { name: "Strangers", basePoints: 0, color: "#444444" } }>> /* Generate NPC-to-NPC relationship key */ <<set setup.getNpcRelationshipKey = function(npc1Name, npc2Name) { /* Sort names alphabetically to ensure consistent key */ var names = [npc1Name, npc2Name].sort(); return names[0] + "_" + names[1]; }>> /* Set relationship between two NPCs */ <<set setup.setNpcToNpcRelationship = function(npc1Name, npc2Name, relationshipType) { var v = State.variables; var key = setup.getNpcRelationshipKey(npc1Name, npc2Name); var typeData = setup.npcRelationshipTypes[relationshipType]; if (!typeData) { typeData = setup.npcRelationshipTypes["strangers"]; relationshipType = "strangers"; } v.npcToNpcRelationships[key] = { npc1: npc1Name, npc2: npc2Name, type: relationshipType, typeName: typeData.name, points: typeData.basePoints, level: setup.calculateRelationshipLevel(typeData.basePoints), color: typeData.color }; return v.npcToNpcRelationships[key]; }>> /* Get relationship between two NPCs */ <<set setup.getNpcToNpcRelationship = function(npc1Name, npc2Name) { var v = State.variables; var key = setup.getNpcRelationshipKey(npc1Name, npc2Name); if (v.npcToNpcRelationships[key]) { return v.npcToNpcRelationships[key]; } /* Default to strangers */ return { npc1: npc1Name, npc2: npc2Name, type: "strangers", typeName: "Strangers", points: 0, level: 0, color: "#444444" }; }>> /* Get all relationships for a specific NPC */ <<set setup.getNpcRelationships = function(npcName) { var v = State.variables; var relationships = []; for (var key in v.npcToNpcRelationships) { var rel = v.npcToNpcRelationships[key]; if (rel.npc1 === npcName || rel.npc2 === npcName) { var otherNpc = (rel.npc1 === npcName) ? rel.npc2 : rel.npc1; relationships.push({ npcName: otherNpc, relationship: rel }); } } return relationships; }>> /* Check if two NPCs know each other (have a relationship) */ <<set setup.npcsKnowEachOther = function(npc1Name, npc2Name) { var rel = setup.getNpcToNpcRelationship(npc1Name, npc2Name); return rel.type !== "strangers"; }>> /* ---------------------------------- */ /* --- HOUSING INFRASTRUCTURE --- */ /* ---------------------------------- */ /* Housing locations and their properties */ <<set setup.housingLocations = { "OutskirtsHousing": { name: "Outskirts Housing", area: "Outskirts", type: "rundown", description: "Rundown houses in the outskirts of town", accessLevel: 2, rent: 200 }, "BusinessDistrictHousing": { name: "Business District Apartments", area: "BusinessDistrict", type: "upscale", description: "Upscale apartments in the business district", accessLevel: 3, rent: 800 }, "RedLightHousing": { name: "Red Light District Apartments", area: "RedLightDistrict", type: "seedy", description: "Seedy apartments in the red light district", accessLevel: 2, rent: 350 }, "ApartmentPenthouse": { name: "Penthouse Suite", area: "Apartments", type: "luxury", description: "Luxury penthouse that can be rented", accessLevel: 4, rent: 2000 }, "BeachMansion": { name: "Beach Mansion", area: "Beach", type: "mansion", description: "Luxurious mansion by the beach", accessLevel: 4, rent: 5000 }, "BrothelPrivateChambers": { name: "Brothel Private Chambers", area: "Brothel", type: "private", description: "Private chambers within the brothel", accessLevel: 4, rent: 0 }, "ResidentialNormalHomes": { name: "Normal Homes", area: "ResidentialDistrict", type: "suburban", description: "Middle-class suburban homes in the residential district", accessLevel: 2, rent: 400 }, "ResidentialExpensiveHomes": { name: "Expensive Homes", area: "ResidentialDistrict", type: "upscale", description: "Upper-class homes in the nicer part of the residential district", accessLevel: 3, rent: 1200 }, "ResidentialMansions": { name: "Residential Mansions", area: "ResidentialDistrict", type: "mansion", description: "Gated mansion community for the wealthy elite", accessLevel: 4, rent: 4000 } }>> /* Set NPC residence */ <<set setup.setNPCResidence = function(npcName, housingKey) { var v = State.variables; var npc = setup.getNPCByName(npcName); if (!npc) return false; if (setup.housingLocations[housingKey]) { npc.residence = housingKey; return true; } return false; }>> /* Get NPC residence information */ <<set setup.getNPCResidence = function(npcName) { var npc = setup.getNPCByName(npcName); if (!npc || !npc.residence) return null; var housing = setup.housingLocations[npc.residence]; if (housing) { return { key: npc.residence, name: housing.name, area: housing.area, type: housing.type, description: housing.description }; } return null; }>> /* Check if player can access NPC's home */ <<set setup.canAccessNPCHome = function(npcName) { var v = State.variables; var residence = setup.getNPCResidence(npcName); if (!residence) return false; var housing = setup.housingLocations[residence.key]; if (!housing) return false; /* Get relationship level */ var rel = v.relationships[npcName]; if (!rel) return false; /* Check if relationship level meets access requirement */ /* Level 3 (Close Friend) or higher for most homes */ /* Level 4 (Best Friend) for luxury/private homes */ if (rel.level >= housing.accessLevel) { return true; } return false; }>> /* Get NPCs who live in a specific housing location */ <<set setup.getNPCsAtResidence = function(housingKey) { var v = State.variables; var residents = []; for (var i = 0; i < v.npcs.length; i++) { var npc = v.npcs[i]; if (npc.residence === housingKey) { residents.push(npc); } } return residents; }>> /* Get all NPCs who have residences */ <<set setup.getNPCsWithResidences = function() { var v = State.variables; var npcsWithHomes = []; for (var i = 0; i < v.npcs.length; i++) { var npc = v.npcs[i]; if (npc.residence && setup.housingLocations[npc.residence]) { npcsWithHomes.push({ npc: npc, residence: setup.housingLocations[npc.residence] }); } } return npcsWithHomes; }>> /* Default NPC residence assignments based on jobs and social status */ <<set setup.npcDefaultResidences = { /* Outskirts Housing - Rundown, low-income */ "Jake Steel": "OutskirtsHousing", "Tommy Blake": "OutskirtsHousing", "Mason Reed": "OutskirtsHousing", "Hank Briggs": "OutskirtsHousing", "Rusty Nails": "OutskirtsHousing", "David O'Brien": "OutskirtsHousing", "Xanithar Galdenentri": "OutskirtsHousing", /* Business District Housing - Upscale professionals */ "Elena Romero": "BusinessDistrictHousing", "Grimm Patel": "BusinessDistrictHousing", "Scarlett Vex": "BusinessDistrictHousing", "Nina Sato": "BusinessDistrictHousing", "Zara Quinn": "BusinessDistrictHousing", "Clara Chen": "BusinessDistrictHousing", "Lena Cross": "BusinessDistrictHousing", "Amber Cole": "BusinessDistrictHousing", "Evelyn Marsh": "BusinessDistrictHousing", "Naomi Sato": "BusinessDistrictHousing", /* Red Light District Housing - Adult industry workers (non-brothel) */ "Jade Nightshade": "RedLightHousing", "Apollo Sterling": "RedLightHousing", "Tanya West": "RedLightHousing", "Ruby Lane": "RedLightHousing", "Diamond Murphy": "RedLightHousing", "Raven Delacroix": "RedLightHousing", /* Brothel Private Chambers - Brothel workers live at the brothel */ "Candace Luxe": "BrothelPrivateChambers", "Ruby Becker": "BrothelPrivateChambers", "Sapphire Wallace": "BrothelPrivateChambers", "Jasmine Abrams": "BrothelPrivateChambers", "Ebony Vasquez": "BrothelPrivateChambers", "Amber Skye": "BrothelPrivateChambers", "Selkira Onyxia": "BrothelPrivateChambers", "Revna McKraken": "BrothelPrivateChambers", /* Residential Normal Homes - Middle class */ "Marcus Carter": "ResidentialNormalHomes", "Silva Silva": "ResidentialNormalHomes", "Rex Harmon": "ResidentialNormalHomes", "Cass Morgan": "ResidentialNormalHomes", "Ivy Brooks": "ResidentialNormalHomes", "Drake Lawson": "ResidentialNormalHomes", "Daisy Flores": "ResidentialNormalHomes", "Milo Hart": "ResidentialNormalHomes", "Wendy Parker": "ResidentialNormalHomes", "Spencer Kim": "ResidentialNormalHomes", "Victor Reyes": "ResidentialNormalHomes", "Oscar Grant": "ResidentialNormalHomes", "Penny Shaw": "ResidentialNormalHomes", "Felix Dunn": "ResidentialNormalHomes", "Jenna Hartwell": "ResidentialNormalHomes", "Lila Monroe": "ResidentialNormalHomes", "Megan Holt": "ResidentialNormalHomes", "Tara Bloom": "ResidentialNormalHomes", "Kira Wolfe": "ResidentialNormalHomes", "Nadia Petrova": "ResidentialNormalHomes", "Fiona Graves": "ResidentialNormalHomes", "Chelsea Bright": "ResidentialNormalHomes", "Maya Santos": "ResidentialNormalHomes", "Derek Stone": "ResidentialNormalHomes", "Ryan Mitchell": "ResidentialNormalHomes", "Kyle Jensen": "ResidentialNormalHomes", "Nolan Pierce": "ResidentialNormalHomes", "Quinn Taylor": "ResidentialNormalHomes", /* Residential Expensive Homes - Upper middle class */ "Vera Sinclair": "ResidentialExpensiveHomes", "Blair Hoffman": "ResidentialExpensiveHomes", "Celeste Fontaine": "ResidentialExpensiveHomes", "Vivian Cho": "ResidentialExpensiveHomes", "Bianca Moretti": "ResidentialExpensiveHomes", /* Residential Mansions - Wealthy elite */ "Maxine Delacour": "ResidentialMansions", /* Special/Story NPCs */ "Purple Wood": "ApartmentPenthouse", "Luna Snow": "ApartmentPenthouse", "Cid Cranberry": "MeetNeighbors", "Roisin Sullivan": "BeachMansion" }>> /* Maps housing keys to their schedule location (where NPCs go when "at home") */ <<set setup.housingToScheduleLocation = { "OutskirtsHousing": "OutskirtsHousing", "BusinessDistrictHousing": "BusinessDistrictHousing", "RedLightHousing": "RedLightHousing", "ApartmentPenthouse": "ApartmentPenthouse", "BeachMansion": "BeachMansion", "BrothelPrivateChambers": "BrothelPrivateChambers", "ResidentialNormalHomes": "ResidentialNormalHomes", "ResidentialExpensiveHomes": "ResidentialExpensiveHomes", "ResidentialMansions": "ResidentialMansions" }>> /* Get NPCs currently at a specific housing location */ <<set setup.getNPCsAtHousing = function(housingKey) { var v = State.variables; var npcsAtHousing = []; var currentHour = Math.floor(v.timeInMinutes / 60) % 24; var dayOfWeek = v.dayOfWeek; if (!v.npcs) return npcsAtHousing; for (var i = 0; i < v.npcs.length; i++) { var npc = v.npcs[i]; /* Check if NPC lives at this housing */ if (npc.residence === housingKey) { /* Check if NPC is currently at their home location */ var currentLocation = setup.getNPCLocation(npc, dayOfWeek, currentHour); var homeLocation = setup.housingToScheduleLocation[housingKey] || housingKey; /* NPC is home if at their housing location or ResidentialDistrict (for residential homes) */ if (currentLocation === homeLocation || (currentLocation === "ResidentialDistrict" && homeLocation.indexOf("Residential") === 0)) { npcsAtHousing.push(npc); } } } return npcsAtHousing; }>> /* Check if player can visit an NPC's home (relationship level 3+) */ <<set setup.canVisitNPCHome = function(npcName) { var v = State.variables; var rel = v.npcRelationships && v.npcRelationships[npcName]; if (!rel) return false; return rel.level >= 3; }>> /* Attempt to knock on a random door in a housing area - 25% chance someone answers */ <<set setup.knockRandomDoor = function(housingKey) { var npcsAtHousing = setup.getNPCsAtHousing(housingKey); if (npcsAtHousing.length === 0) { return { success: false, reason: "no_one_home", npc: null }; } /* 25% chance someone answers */ if (Math.random() < 0.25) { /* Random NPC from those at home answers */ var randomNPC = npcsAtHousing[Math.floor(Math.random() * npcsAtHousing.length)]; return { success: true, reason: "answered", npc: randomNPC }; } else { return { success: false, reason: "no_answer", npc: null }; } }>> /* Get all NPCs who live in a specific housing area (regardless of if they're home) */ <<set setup.getNPCsLivingAt = function(housingKey) { var v = State.variables; var residents = []; if (!v.npcs) return residents; for (var i = 0; i < v.npcs.length; i++) { var npc = v.npcs[i]; if (npc.residence === housingKey) { residents.push(npc); } } return residents; }>> /* Initialize all NPC residences on game start */ <<set setup.initializeAllNPCResidences = function() { var v = State.variables; if (!v.npcs) return; for (var i = 0; i < v.npcs.length; i++) { var npc = v.npcs[i]; var npcName = npc.permanentId || npc.name; /* Skip if NPC already has a residence */ if (npc.residence) continue; /* Check if NPC has a default residence assignment */ if (setup.npcDefaultResidences[npcName]) { npc.residence = setup.npcDefaultResidences[npcName]; } else { /* Assign based on job - check jobs array */ var jobs = npc.jobs || []; var job = Array.isArray(jobs) ? jobs[0] : jobs; if (job === "Brothel Worker") { npc.residence = "BrothelPrivateChambers"; } else if (job === "Stripper" || job === "Prostitute") { npc.residence = "RedLightHousing"; } else if (job === "Porn Star" || job === "Social Media Influencer") { npc.residence = "BusinessDistrictHousing"; } else if (job === "Farm Hand" || job === "Fisherman") { npc.residence = "OutskirtsHousing"; } else if (job === "Government Worker" || job === "Clinic Assistant") { npc.residence = "BusinessDistrictHousing"; } else { /* Default to normal residential homes */ npc.residence = "ResidentialNormalHomes"; } } } }>> /* Update residence when job changes (optional - maintains old residence if they can afford it) */ <<set setup.updateResidenceForJob = function(npcName, newJob, forceMove) { var npc = setup.findNPCByName(npcName); if (!npc) return; if (forceMove) { /* Force move to new residence based on job */ if (newJob === "Brothel Worker") { npc.residence = "BrothelPrivateChambers"; } else if (newJob === "Stripper" || newJob === "Prostitute") { npc.residence = "RedLightHousing"; } else if (newJob === "Porn Star" || newJob === "Social Media Influencer") { npc.residence = "BusinessDistrictHousing"; } else if (newJob === "Farm Hand" || newJob === "Fisherman") { npc.residence = "OutskirtsHousing"; } else if (newJob === "Government Worker" || newJob === "Clinic Assistant") { npc.residence = "BusinessDistrictHousing"; } else { npc.residence = "ResidentialNormalHomes"; } } /* If not forced, NPC keeps their current residence */ }>> /* Swap residences between two NPCs (for identity swap) */ <<set setup.swapNPCResidences = function(npc1Name, npc2Name) { var npc1 = setup.findNPCByName(npc1Name); var npc2 = setup.findNPCByName(npc2Name); if (npc1 && npc2) { var temp = npc1.residence; npc1.residence = npc2.residence; npc2.residence = temp; } }>> /* Get text describing how NPC1 refers to NPC2 based on their relationship */ <<set setup.getNpcRelationshipReference = function(npc1Name, npc2Name) { var rel = setup.getNpcToNpcRelationship(npc1Name, npc2Name); switch (rel.type) { case "family_sibling": return "my sibling"; case "family_parent": return (npc1Name === rel.npc1) ? "my parent" : "my child"; case "family_child": return (npc1Name === rel.npc1) ? "my child" : "my parent"; case "friends": return "my friend"; case "best_friends": return "my best friend"; case "rivals": return "my rival"; case "enemies": return "someone I don't get along with"; case "romantic": return "my partner"; case "ex_romantic": return "my ex"; case "coworkers": return "my coworker"; case "acquaintances": return "someone I know"; default: return npc2Name; } }>> /* Default NPC-to-NPC Relationships */ <<set setup.defaultNpcToNpcRelationships = [ /* Coworker relationships - Same workplace */ {npc1: "Jade Nightshade", npc2: "Apollo Sterling", type: "coworkers"}, {npc1: "Jade Nightshade", npc2: "Ruby Lane", type: "coworkers"}, {npc1: "Apollo Sterling", npc2: "Ruby Lane", type: "coworkers"}, {npc1: "Elena Romero", npc2: "Clara Chen", type: "coworkers"}, {npc1: "Scarlett Vex", npc2: "Amber Cole", type: "coworkers"}, {npc1: "Jake Steel", npc2: "Tommy Blake", type: "coworkers"}, {npc1: "Vera Sinclair", npc2: "Lena Cross", type: "coworkers"}, /* Friend relationships - Based on neighborhood/common interests */ {npc1: "Marcus Carter", npc2: "Rex Harmon", type: "friends"}, {npc1: "Silva Silva", npc2: "Cass Morgan", type: "friends"}, {npc1: "Ivy Brooks", npc2: "Daisy Flores", type: "friends"}, {npc1: "Nina Sato", npc2: "Zara Quinn", type: "friends"}, {npc1: "Wendy Parker", npc2: "Penny Shaw", type: "friends"}, {npc1: "Victor Reyes", npc2: "Tommy Blake", type: "friends"}, {npc1: "Milo Hart", npc2: "Spencer Kim", type: "friends"}, {npc1: "Oscar Grant", npc2: "Felix Dunn", type: "friends"}, /* Best friends */ {npc1: "Jade Nightshade", npc2: "Tanya West", type: "best_friends"}, {npc1: "Elena Romero", npc2: "Nina Sato", type: "best_friends"}, /* Romantic relationships */ {npc1: "Scarlett Vex", npc2: "Grimm Patel", type: "romantic"}, {npc1: "Blair Hoffman", npc2: "Drake Lawson", type: "romantic"}, /* Ex-romantic */ {npc1: "Apollo Sterling", npc2: "Jade Nightshade", type: "ex_romantic"}, {npc1: "Mason Reed", npc2: "Tanya West", type: "ex_romantic"}, /* Rivals */ {npc1: "Scarlett Vex", npc2: "Amber Cole", type: "rivals"}, {npc1: "Zara Quinn", npc2: "Daisy Flores", type: "rivals"}, /* Family relationships */ {npc1: "Ivy Brooks", npc2: "Wendy Parker", type: "family_sibling"}, /* Acquaintances - Neighborhood connections */ {npc1: "Marcus Carter", npc2: "Silva Silva", type: "acquaintances"}, {npc1: "Cass Morgan", npc2: "Ivy Brooks", type: "acquaintances"}, {npc1: "Jake Steel", npc2: "Mason Reed", type: "acquaintances"}, {npc1: "Grimm Patel", npc2: "Drake Lawson", type: "acquaintances"}, {npc1: "Ruby Lane", npc2: "Tanya West", type: "acquaintances"}, {npc1: "Vera Sinclair", npc2: "Blair Hoffman", type: "acquaintances"}, {npc1: "Lena Cross", npc2: "Clara Chen", type: "acquaintances"}, {npc1: "Oscar Grant", npc2: "Spencer Kim", type: "acquaintances"}, {npc1: "Milo Hart", npc2: "Felix Dunn", type: "acquaintances"} ]>> /* Initialize all default NPC-to-NPC relationships */ <<set setup.initializeNpcToNpcRelationships = function() { var relationships = setup.defaultNpcToNpcRelationships; for (var i = 0; i < relationships.length; i++) { var rel = relationships[i]; setup.setNpcToNpcRelationship(rel.npc1, rel.npc2, rel.type); } }>> /* Run the initialization to set up default NPC-to-NPC relationships */ <<run setup.initializeNpcToNpcRelationships()>> /* Get all NPCs an NPC considers friends or better */ <<set setup.getNpcFriends = function(npcName) { var allRels = setup.getNpcRelationships(npcName); var friends = []; for (var i = 0; i < allRels.length; i++) { var rel = allRels[i].relationship; /* Friends, best friends, romantic, family all count */ if (rel.type === "friends" || rel.type === "best_friends" || rel.type === "romantic" || rel.type.indexOf("family") === 0) { friends.push(allRels[i].npcName); } } return friends; }>> /* Get all NPCs an NPC has negative relations with */ <<set setup.getNpcEnemies = function(npcName) { var allRels = setup.getNpcRelationships(npcName); var enemies = []; for (var i = 0; i < allRels.length; i++) { var rel = allRels[i].relationship; if (rel.type === "rivals" || rel.type === "enemies") { enemies.push(allRels[i].npcName); } } return enemies; }>> /* Generate default relationships for an NPC (used in life swap) */ /* Returns an object of {npcName: {level: X, points: Y}} */ <<set setup.generateNPCDefaultRelationships = function(npcName) { var v = State.variables; var relationships = {}; /* * Define NPC relationships as PAIRS - relationships are always bidirectional. * Format: [[NPC1, NPC2, level, points, reason], ...] * Both NPCs will have this relationship with each other. */ var relationshipPairs = [ /* === MAYOR & CITY HALL === */ ["Dick Richardson", "Creo Applesauce", 2, 100], /* Mayor & Secretary */ ["Dick Richardson", "Grimm Patel", 1, 50], /* Uses enforcer */ ["Dick Richardson", "Marcus Carter", 0, 10], /* Security knows him */ ["Dick Richardson", "Tank Morrison", -1, -20], /* Bouncer dislikes corrupt mayor */ ["Dick Richardson", "Jake Steel", -1, -30], /* Construction screwed by policies */ ["Dick Richardson", "Elena Romero", -1, -25], /* Clinic underfunded */ ["Dick Richardson", "Keisha Jackson", -1, -35], /* Hates corruption */ ["Dick Richardson", "Rosa Otterino", -1, -20], /* Service worker ignored */ ["Dick Richardson", "Pheiffer Coms", 1, 40], /* Police connection */ ["Creo Applesauce", "Brad Icus", 1, 50], /* Office workers */ ["Creo Applesauce", "Elena Romero", 1, 40], /* Professional contact */ /* === STRIP CLUB WORKERS === */ ["Jade Nightshade", "Apollo Sterling", 2, 100], /* Coworkers */ ["Jade Nightshade", "Ruby Becker", 2, 80], /* Coworkers */ ["Jade Nightshade", "Tank Morrison", 3, 200], /* Bouncer protects her */ ["Jade Nightshade", "Trixie Rye", 2, 90], /* Club coworker */ ["Jade Nightshade", "Scarlett Vex", 1, 40], /* Industry connection */ ["Jade Nightshade", "Diamond Murphy", 1, 30], /* Knows from scene */ ["Apollo Sterling", "Ruby Becker", 2, 90], /* Coworkers */ ["Apollo Sterling", "Tank Morrison", 2, 85], /* Bouncer friend */ ["Apollo Sterling", "Scarlett Vex", 1, 50], /* Industry */ ["Apollo Sterling", "Marcus Carter", 1, 40], /* Gym buddy */ ["Apollo Sterling", "Trixie Rye", 2, 85], /* Club coworker */ ["Ruby Becker", "Tank Morrison", 2, 75], /* Bouncer */ ["Ruby Becker", "Trixie Rye", 2, 80], /* Club coworker */ ["Tank Morrison", "Trixie Rye", 2, 85], /* Bouncer protects waitress */ /* === BROTHEL - Kate Velvet owns it, knows all workers === */ ["Kate Velvet", "Candace Luxe", 3, 180], /* Owner & top worker */ ["Kate Velvet", "Sapphire Wallace", 2, 100], /* Owner & worker */ ["Kate Velvet", "Jasmine Abrams", 2, 95], /* Owner & worker */ ["Kate Velvet", "Ebony Vasquez", 2, 90], /* Owner & worker */ ["Kate Velvet", "Amber Skye", 2, 85], /* Owner & worker */ ["Kate Velvet", "Selkira Onyxia", 2, 85], /* Owner & worker */ ["Kate Velvet", "Diamond Murphy", 1, 50], /* Industry connection */ ["Kate Velvet", "Scarlett Vex", 1, 45], /* Industry connection */ ["Kate Velvet", "Grimm Patel", 1, 40], /* Business security */ ["Candace Luxe", "Sapphire Wallace", 3, 180], /* Close coworkers */ ["Candace Luxe", "Jasmine Abrams", 2, 100], /* Coworkers */ ["Candace Luxe", "Ebony Vasquez", 2, 95], /* Coworkers */ ["Candace Luxe", "Amber Skye", 2, 90], /* Coworkers */ ["Candace Luxe", "Selkira Onyxia", 2, 85], /* Coworkers */ ["Candace Luxe", "Diamond Murphy", 1, 50], /* Industry connection */ ["Sapphire Wallace", "Jasmine Abrams", 2, 100], /* Coworkers */ ["Sapphire Wallace", "Ebony Vasquez", 2, 90], /* Coworkers */ ["Sapphire Wallace", "Amber Skye", 2, 85], /* Coworkers */ ["Sapphire Wallace", "Selkira Onyxia", 2, 80], /* Coworkers */ ["Jasmine Abrams", "Ebony Vasquez", 2, 90], /* Coworkers */ ["Jasmine Abrams", "Amber Skye", 2, 85], /* Coworkers */ ["Jasmine Abrams", "Selkira Onyxia", 2, 80], /* Coworkers */ ["Ebony Vasquez", "Amber Skye", 2, 85], /* Coworkers */ ["Ebony Vasquez", "Selkira Onyxia", 2, 80], /* Coworkers */ ["Amber Skye", "Selkira Onyxia", 2, 80], /* Coworkers */ /* === CONSTRUCTION WORKERS === */ ["Jake Steel", "Marco Rodriguez", 3, 200], /* Close coworkers */ ["Jake Steel", "Tyrone Washington", 2, 100], /* Coworkers */ ["Jake Steel", "Sheryl Williams", 2, 90], /* Coworkers */ ["Jake Steel", "David O'Brien", 2, 85], /* Coworkers */ ["Jake Steel", "Mike Murphy", 2, 80], /* Cross-industry */ ["Jake Steel", "Carlos Mendez", 2, 85], /* Cross-industry */ ["Jake Steel", "Tank Morrison", 1, 50], /* Drinking buddies */ ["Marco Rodriguez", "Tyrone Washington", 2, 95], /* Coworkers */ ["Marco Rodriguez", "Sheryl Williams", 2, 85], /* Coworkers */ ["Marco Rodriguez", "David O'Brien", 2, 80], /* Coworkers */ ["Marco Rodriguez", "Carlos Mendez", 3, 175], /* Close friend */ ["Tyrone Washington", "Sheryl Williams", 2, 85], /* Coworkers */ ["Tyrone Washington", "David O'Brien", 2, 80], /* Coworkers */ ["Tyrone Washington", "Jamal Rivers", 3, 175], /* Close friend */ ["Sheryl Williams", "David O'Brien", 2, 85], /* Coworkers */ ["Sheryl Williams", "Keisha Jackson", 2, 85], /* Fellow workers */ ["Sheryl Williams", "Elena Romero", 2, 80], /* Clinic connection */ /* === DOCK WORKERS === */ ["Mike Murphy", "Carlos Mendez", 2, 90], /* Coworkers */ ["Mike Murphy", "Jamal Rivers", 2, 85], /* Coworkers */ ["Mike Murphy", "Rosa Otterino", 2, 80], /* Coworkers */ ["Mike Murphy", "Keisha Jackson", 2, 80], /* Coworkers */ ["Carlos Mendez", "Jamal Rivers", 2, 80], /* Coworkers */ ["Carlos Mendez", "Rosa Otterino", 2, 75], /* Coworkers */ ["Carlos Mendez", "Keisha Jackson", 2, 75], /* Coworkers */ ["Jamal Rivers", "Rosa Otterino", 2, 85], /* Coworkers */ ["Jamal Rivers", "Keisha Jackson", 2, 80], /* Coworkers */ ["Rosa Otterino", "Keisha Jackson", 2, 90], /* Fellow workers, friends */ /* === CLINIC === */ ["Elena Romero", "Naomi Light", 2, 80], /* Health-conscious connection */ /* === NEGOTIATORS/ENFORCERS === */ ["Silva Silva", "Grimm Patel", 2, 100], /* Work together */ ["Silva Silva", "Marcus Carter", 1, 45], /* Professional */ ["Grimm Patel", "Scarlett Vex", 4, 500], /* Romantic partners */ ["Grimm Patel", "Tank Morrison", 1, 40], /* Mutual respect */ /* === SECURITY === */ ["Marcus Carter", "Tank Morrison", 2, 90], /* Security bros */ ["Marcus Carter", "Pheiffer Coms", 2, 85], /* Law enforcement connection */ ["Marcus Carter", "Brad Icus", 1, 50], /* Gym connection */ /* === PORN INDUSTRY === */ ["Scarlett Vex", "Diamond Murphy", 1, 35], /* Industry connection */ ["Scarlett Vex", "Destiny Pumpkin", 1, 40], /* Adult industry */ ["Scarlett Vex", "Alex Passionfruit", 1, 35], /* Adult industry */ /* === ADULT STORE === */ ["Destiny Pumpkin", "Alex Passionfruit", 2, 100], /* Coworkers */ ["Destiny Pumpkin", "Diamond Murphy", 1, 45], /* Industry connection */ /* === BEAUTY SALON === */ ["Crystal Meffin", "Sophi Boris", 2, 100], /* Coworkers */ ["Crystal Meffin", "Naomi Light", 2, 95], /* Coworkers */ ["Crystal Meffin", "Bella Carver", 2, 80], /* Client/influencer */ ["Sophi Boris", "Naomi Light", 2, 90], /* Coworkers */ ["Sophi Boris", "Bella Carver", 2, 85], /* Client/influencer */ ["Naomi Light", "Luna Snow", 2, 80], /* Spiritual connection */ /* === FITNESS === */ ["Fen Ris", "Brad Icus", 2, 90], /* Fitness connection */ ["Fen Ris", "Marcus Carter", 1, 50], /* Gym regulars */ ["Brad Icus", "Tank Morrison", 1, 45], /* Fitness bros */ ["Brad Icus", "Dennis Fungi", 1, 50], /* Fitness industry */ /* === DANCING === */ ["Dennis Fungi", "Yvela Mushroom", 3, 180], /* Dance partners/coworkers */ ["Dennis Fungi", "Jade Nightshade", 1, 45], /* Dancers know each other */ ["Dennis Fungi", "Apollo Sterling", 1, 40], /* Dancers know each other */ ["Yvela Mushroom", "Jade Nightshade", 1, 40], /* Dancers know each other */ /* === BAKERS === */ ["Hannah Chuckins", "Janis Besser", 3, 180], /* Coworkers, close */ ["Hannah Chuckins", "Banana Banana", 1, 50], /* Cafe connection */ ["Janis Besser", "Banana Banana", 1, 45], /* Cafe connection */ /* === TECH/RETAIL === */ ["Kevin Oats", "Raven Bido", 1, 40], /* Nerd connection */ ["Kevin Oats", "Creo Applesauce", 1, 35], /* Tech/nerd connection */ ["Raven Bido", "Luna Snow", 1, 45], /* Alternative types */ /* === SOCIAL MEDIA/INFLUENCER === */ ["Bella Carver", "Scarlett Vex", 1, 40], /* Both public figures */ ["Bella Carver", "Roisin Sullivan", 2, 90], /* Friends */ /* === SUPERNATURAL/UNUSUAL === */ ["Xanithar Galdenentri", "Fen Ris", 2, 100], /* Supernatural beings */ ["Xanithar Galdenentri", "Revna McKraken", 1, 50], /* Knows of each other */ ["Xanithar Galdenentri", "Luna Snow", 1, 45], /* Mysterious types */ ["Fen Ris", "Luna Snow", 2, 90], /* Unusual beings */ ["Revna McKraken", "Roisin Sullivan", 3, 180], /* Close connection */ /* === ODDBALLS/QUIRKY NAMES === */ ["Banana Banana", "Bongo Bongo", 3, 200], /* Similar vibes */ ["Banana Banana", "Sunny Flipflop", 2, 85], /* Beach/fun vibes */ ["Bongo Bongo", "Sunny Flipflop", 2, 90], /* Fun people */ ["Bongo Bongo", "Poggies Name420", 2, 80], /* Quirky connection */ ["Sunny Flipflop", "Poggies Name420", 1, 50], /* Quirky connection */ /* === POLICE === */ ["Pheiffer Coms", "Tank Morrison", 1, 35], /* Security-adjacent */ /* === COCKTAIL/SERVICE === */ ["Trixie Rye", "Diamond Murphy", 1, 45], /* Night scene */ ["Trixie Rye", "Destiny Pumpkin", 1, 40], /* Adult scene connection */ /* === BUS DRIVER === */ ["Xenis Aku", "Rosa Otterino", 1, 35], /* Regular passenger */ ["Xenis Aku", "Keisha Jackson", 1, 30], /* Regular passenger */ /* === MISC CONNECTIONS === */ ["Purple Wood", "Luna Snow", 1, 40], /* Unusual types */ ["Boris Shorthead", "Butt Johnson", 1, 45], /* Odd name solidarity */ ["Mareregererrer Mayonnaise", "Banana Banana", 1, 40] /* Unusual names */ ]; /* Initialize all NPCs as strangers first */ if (v.npcs && v.npcs.length > 0) { v.npcs.forEach(function(otherNpc) { var otherName = otherNpc.originalName || otherNpc.name; if (otherName !== npcName) { relationships[otherName] = { level: 0, points: 0 }; } }); } /* Apply bidirectional relationships - check both directions for each pair */ for (var i = 0; i < relationshipPairs.length; i++) { var pair = relationshipPairs[i]; var npc1 = pair[0]; var npc2 = pair[1]; var level = pair[2]; var points = pair[3]; /* If this NPC is either side of the relationship, apply it */ if (npcName === npc1) { relationships[npc2] = { level: level, points: points }; } else if (npcName === npc2) { relationships[npc1] = { level: level, points: points }; } } return relationships; }>> /* Swap all NPC-to-NPC relationships between two NPCs (for identity swap) */ <<set setup.swapAllNpcRelationships = function(npc1Name, npc2Name) { var v = State.variables; var newRelationships = {}; /* Go through all relationships and swap the NPC names */ for (var key in v.npcToNpcRelationships) { var rel = v.npcToNpcRelationships[key]; var newRel = JSON.parse(JSON.stringify(rel)); /* Swap NPC1 name */ if (rel.npc1 === npc1Name) { newRel.npc1 = npc2Name; } else if (rel.npc1 === npc2Name) { newRel.npc1 = npc1Name; } /* Swap NPC2 name */ if (rel.npc2 === npc1Name) { newRel.npc2 = npc2Name; } else if (rel.npc2 === npc2Name) { newRel.npc2 = npc1Name; } /* Generate new key */ var newKey = setup.getNpcRelationshipKey(newRel.npc1, newRel.npc2); newRelationships[newKey] = newRel; } v.npcToNpcRelationships = newRelationships; }>> /* Function to add relationship XP (legacy - calls new points system) */ <<set setup.addRelationshipXP = function(npcName, xpAmount, skipAchievements) { /* Redirect to new points-based system */ return setup.addRelationshipPointsLegacy(npcName, xpAmount, skipAchievements); }>> /* Legacy points function for npcRelationships system */ <<set setup.addRelationshipPointsLegacy = function(npcName, pointsAmount, skipAchievements) { var v = State.variables; /* During Roisin possession, v.npcRelationships IS already her view (swapped in by setup.possession.applyRoisin). Writes land in her legacy tracker naturally. */ if (!v.npcRelationships[npcName]) { v.npcRelationships[npcName] = { level: 0, points: 0, levelName: "Stranger", bestFriendUnlocked: false }; } var rel = v.npcRelationships[npcName]; rel.points += pointsAmount; /* Clamp to minimum -50 */ if (rel.points < -50) { rel.points = -50; } /* Calculate new level from points */ var oldLevel = rel.level; rel.level = setup.calculateRelationshipLevel(rel.points); /* Update level name */ var levelData = setup.getRelationshipLevelData(rel.level); rel.levelName = levelData.name; /* Record milestone in memory system */ if (rel.level > oldLevel && setup.recordMilestone) { setup.recordMilestone(npcName, rel.level); } /* Relationship level achievements (skip if specified, e.g. during training) */ if (!skipAchievements) { if (rel.level >= 2 && oldLevel < 2) { setup.achievements.unlock("relationship_2"); } if (rel.level >= 4 && oldLevel < 4) { setup.achievements.unlock("relationship_4"); rel.bestFriendUnlocked = true; /* Award Heart trait on first level 4 relationship (skip if already have Heart or Cupid) */ if (!v.physicalTraits.includes("Heart") && !v.physicalTraits.includes("Cupid")) { v.physicalTraits.push("Heart"); } } } else if (rel.level >= 4 && oldLevel < 4) { /* Still unlock best friend status even when skipping achievements */ rel.bestFriendUnlocked = true; } return rel; }>> /* Function to unlock Best Friend status */ <<set setup.unlockBestFriendStatus = function(npcName) { var v = State.variables; if (v.npcRelationships[npcName] && v.npcRelationships[npcName].level === 4) { v.npcRelationships[npcName].bestFriendUnlocked = true; v.npcRelationships[npcName].levelName = "Best Friend"; } }>> /* Function to get relationship color */ <<set setup.getRelationshipColor = function(level) { var levelData = setup.getRelationshipLevelData(level); return levelData ? levelData.color : "#666666"; }>> /* Function to get relationship status text for an NPC */ <<set setup.getRelationshipStatus = function(npcName) { var v = State.variables; var rel = v.relationships[npcName]; if (!rel) { return "Stranger (Lv. 0)"; } var levelData = setup.getRelationshipLevelData(rel.level); var levelName = levelData ? levelData.name : "Unknown"; return levelName + " (Lv. " + rel.level + ")"; }>> /* Function to update relationship name when name is traded */ <<set setup.updateRelationshipName = function(oldName, newName) { var v = State.variables; if (v.npcRelationships && v.npcRelationships[oldName]) { v.npcRelationships[newName] = v.npcRelationships[oldName]; delete v.npcRelationships[oldName]; return true; } return false; }>> /* Track daily conversations */ <<set $dailyConversations = {}>> <<set $lastConversationDay = 0>> <<if $wifiDaysRemaining > 0>> <<set $wifiDaysRemaining -= 1>> <</if>> /* ---------------------------------- */ /* --- NPC INTERESTS SYSTEM --- */ /* ---------------------------------- */ /* Interest categories with topics */ <<set setup.npcInterests = { categories: { casual: ["weather", "sports", "food", "movies", "music", "fashion", "pets", "hobbies", "local_news", "travel"], personal: ["family", "dreams", "past", "fears", "relationships", "career_goals", "childhood", "regrets"], risque: ["dating_life", "crushes", "embarrassing_moments", "secrets", "gossip", "wild_nights", "exes"], sexual: ["fantasies", "kinks", "past_lovers", "body_preferences", "experiences", "turn_ons", "flirting_tips"], exotic: ["fetishes", "taboo_desires", "wild_experiences", "forbidden_attractions", "deepest_secrets"] }, unlockLevels: { casual: 0, personal: 1, risque: 2, sexual: 3, exotic: 4 } }>> /* Trait-to-interest mappings */ <<set setup.traitInterestMappings = { physical: { "Athletic": ["fitness", "sports", "nutrition", "workout_tips"], "Muscular": ["fitness", "weightlifting", "protein", "body_building"], "Fit": ["exercise", "health", "outdoor_activities"], "Attractive": ["fashion", "beauty", "dating_life", "attention"], "Beautiful": ["beauty_tips", "skincare", "modeling", "compliments"], "Handsome": ["grooming", "style", "confidence", "dating"], "Curvy": ["body_positivity", "fashion", "confidence"], "Petite": ["fashion", "cute_things", "being_underestimated"], "Tall": ["sports", "modeling", "standing_out"], "Short": ["heels", "being_cozy", "proving_people_wrong"] }, mental: { "Intelligent": ["science", "technology", "puzzles", "philosophy", "debates"], "Analytical": ["logic", "problem_solving", "data", "patterns"], "Nerd": ["gaming", "comics", "sci_fi", "collectibles", "conventions"], "Flirty": ["dating_tips", "attraction", "chemistry", "seduction"], "Seductive": ["body_language", "tension", "desire", "temptation"], "Perverted": ["fantasies", "kinks", "experiences", "desires"], "Shy": ["quiet_hobbies", "small_groups", "comfort_zones", "secret_talents"], "Introverted": ["reading", "solitude", "deep_conversations", "one_on_one"], "Ambitious": ["career_goals", "success_stories", "networking", "achievements"], "Driven": ["motivation", "goals", "self_improvement", "discipline"], "Artistic": ["art", "music", "creative_projects", "inspiration", "galleries"], "Creative": ["ideas", "imagination", "making_things", "expression"], "Gossip": ["rumors", "drama", "other_people", "scandals", "secrets"], "Talkative": ["stories", "conversations", "socializing", "news"], "Confident": ["self_assurance", "public_speaking", "leadership"], "Insecure": ["validation", "self_doubt", "seeking_approval"], "Friendly": ["making_friends", "social_events", "helping_others"], "Kind": ["charity", "animals", "volunteering", "compassion"], "Cold": ["efficiency", "boundaries", "privacy"], "Manipulative": ["psychology", "influence", "getting_what_they_want"], "Loyal": ["friendship", "trust", "commitment", "being_there"], "Jealous": ["possessiveness", "comparison", "insecurity"], "Adventurous": ["travel", "trying_new_things", "risks", "excitement"], "Cautious": ["safety", "planning", "avoiding_risks"], "Optimistic": ["positive_thinking", "hope", "silver_linings"], "Pessimistic": ["worst_case_scenarios", "realism", "preparing_for_bad"], "Humorous": ["jokes", "comedy", "making_people_laugh", "pranks"], "Serious": ["important_topics", "depth", "meaning"], "Romantic": ["love", "relationships", "romantic_gestures", "soulmates"], "Cynical": ["skepticism", "distrust", "questioning_motives"] }, jobs: { "Stripper": ["body_confidence", "performance", "admirers", "dancing", "tips"], "Porn Star": ["acting", "performance", "fans", "industry_gossip", "fame"], "Brothel Worker": ["clients", "techniques", "boundaries", "memorable_encounters", "regulars"], "Construction Worker": ["building_things", "physical_labor", "tools", "job_sites"], "Dock Worker": ["ships", "cargo", "early_mornings", "waterfront"], "Security Guard": ["safety", "vigilance", "incidents", "boring_shifts"], "Bus Driver": ["routes", "passengers", "traffic", "city_knowledge"], "Bartender": ["drinks", "drunk_stories", "tips", "regulars"], "Nurse": ["health", "patients", "medical_stories", "long_shifts"], "Doctor": ["medicine", "cases", "health_advice", "stress"], "Lawyer": ["cases", "justice", "legal_loopholes", "courtroom_drama"], "Model": ["photoshoots", "fashion", "diets", "industry_drama"], "Influencer": ["followers", "content", "brand_deals", "going_viral"] } }>> /* Generate interests for an NPC based on traits */ <<set setup.generateNPCInterests = function(npc) { var interests = { primary: [], secondary: [], hidden: [], sexual: [], exotic: [] }; var mappings = setup.traitInterestMappings; /* Physical traits */ if (npc.physicalTraits) { npc.physicalTraits.forEach(function(trait) { if (mappings.physical[trait]) { mappings.physical[trait].forEach(function(interest) { if (!interests.primary.includes(interest) && interests.primary.length < 3) { interests.primary.push(interest); } else if (!interests.secondary.includes(interest) && interests.secondary.length < 5) { interests.secondary.push(interest); } }); } }); } /* Mental traits */ if (npc.mentalTraits) { npc.mentalTraits.forEach(function(trait) { if (mappings.mental[trait]) { mappings.mental[trait].forEach(function(interest) { if (!interests.primary.includes(interest) && interests.primary.length < 3) { interests.primary.push(interest); } else if (!interests.secondary.includes(interest) && interests.secondary.length < 5) { interests.secondary.push(interest); } }); } /* Add hidden interests for shy/introverted */ if (trait === "Shy" || trait === "Introverted") { interests.hidden.push("secret_hobbies", "private_dreams", "hidden_talents"); } /* Add sexual interests for flirty/perverted */ if (trait === "Flirty" || trait === "Seductive") { interests.sexual.push("fantasies", "dating_tips", "attraction", "chemistry"); } if (trait === "Perverted") { interests.sexual.push("kinks", "experiences", "desires"); interests.exotic.push("unusual_requests", "taboo_topics"); } }); } /* Job-based interests */ if (npc.jobs && npc.jobs.length > 0) { npc.jobs.forEach(function(job) { if (mappings.jobs[job]) { mappings.jobs[job].forEach(function(interest) { if (!interests.secondary.includes(interest) && interests.secondary.length < 7) { interests.secondary.push(interest); } }); } /* Add sexual interests for adult jobs */ if (job === "Stripper" || job === "Porn Star") { interests.sexual.push("body_confidence", "performance", "admirers", "the_industry"); } if (job === "Brothel Worker") { interests.sexual.push("clients", "techniques", "boundaries"); interests.exotic.push("unusual_requests", "memorable_encounters"); } }); } /* Ensure minimum interests */ var casualTopics = setup.npcInterests.categories.casual; while (interests.primary.length < 2) { var randomTopic = casualTopics[Math.floor(Math.random() * casualTopics.length)]; if (!interests.primary.includes(randomTopic)) { interests.primary.push(randomTopic); } } while (interests.secondary.length < 3) { var randomTopic = casualTopics[Math.floor(Math.random() * casualTopics.length)]; if (!interests.secondary.includes(randomTopic) && !interests.primary.includes(randomTopic)) { interests.secondary.push(randomTopic); } } return interests; }>> /* Initialize interests for all NPCs */ <<set setup.initializeAllNPCInterests = function() { var v = State.variables; if (!v.npcs) return; for (var i = 0; i < v.npcs.length; i++) { var npc = v.npcs[i]; if (!npc.interests) { npc.interests = setup.generateNPCInterests(npc); } } }>> /* Get available topics for NPC based on relationship level */ <<set setup.getAvailableTopics = function(npcName, relationshipLevel) { var npc = setup.getNPCByName(npcName); if (!npc || !npc.interests) { npc.interests = setup.generateNPCInterests(npc); } var availableTopics = []; var interests = npc.interests; /* Always available */ availableTopics = availableTopics.concat(interests.primary); availableTopics = availableTopics.concat(interests.secondary); /* Personal level (1+) */ if (relationshipLevel >= 1) { availableTopics = availableTopics.concat(interests.hidden || []); } /* Sexual level (3+) */ if (relationshipLevel >= 3) { availableTopics = availableTopics.concat(interests.sexual || []); } /* Exotic level (4) */ if (relationshipLevel >= 4) { availableTopics = availableTopics.concat(interests.exotic || []); } return availableTopics; }>> /* Check if topic is appropriate for relationship level */ <<set setup.canDiscussTopic = function(topic, relationshipLevel) { var categories = setup.npcInterests.categories; var unlockLevels = setup.npcInterests.unlockLevels; for (var category in categories) { if (categories[category].includes(topic)) { return relationshipLevel >= unlockLevels[category]; } } return true; }>> /* Update NPC interests when traits change */ <<set setup.updateNPCInterests = function(npc) { var baseInterests = setup.generateNPCInterests(npc); /* 15% chance each interest shifts to something related */ for (var category in baseInterests) { if (Array.isArray(baseInterests[category])) { for (var i = 0; i < baseInterests[category].length; i++) { if (Math.random() < 0.15) { var allTopics = setup.npcInterests.categories.casual.concat( setup.npcInterests.categories.personal ); var newTopic = allTopics[Math.floor(Math.random() * allTopics.length)]; if (!baseInterests[category].includes(newTopic)) { baseInterests[category][i] = newTopic; } } } } } npc.interests = baseInterests; return npc.interests; }>> /* Location-specific dialogue topics */ <<set setup.locationDialogueTopics = { "Casino": [ {id: "gambling_talk", label: "Talk about gambling luck"}, {id: "high_rollers", label: "Ask about high rollers"} ], "Mall": [ {id: "shopping_talk", label: "Ask what they are shopping for"}, {id: "deals", label: "Talk about sales and deals"} ], "GymNPCs": [ {id: "workout_talk", label: "Ask about their workout routine"}, {id: "fitness_goals", label: "Discuss fitness goals"} ], "TheAngler": [ {id: "drink_talk", label: "Buy them a drink"}, {id: "gossip", label: "Ask what is the word on the street"}, {id: "rough_day", label: "Ask about their day"} ], "Hospital": [ {id: "health_talk", label: "Ask about health"}, {id: "work_stories", label: "Ask about interesting cases"} ], "HospitalClinic": [ {id: "checkup_talk", label: "Ask about getting a checkup"}, {id: "medical_advice", label: "Ask for health advice"} ], "GroceryStore": [ {id: "cooking_talk", label: "Ask what they are making"}, {id: "recipes", label: "Exchange recipe ideas"} ], "ModelingStudio": [ {id: "work_talk", label: "Ask about their shoots"}, {id: "industry_gossip", label: "Ask about industry drama"} ], "ModelingStudioFashion": [ {id: "fashion_talk", label: "Ask about fashion trends"}, {id: "photoshoot_stories", label: "Ask about memorable shoots"} ], "ModelingStudioAdult": [ {id: "industry_talk", label: "Ask about the industry"}, {id: "fans_talk", label: "Ask about fans"} ], "ResidentialDistrict": [ {id: "neighborhood_talk", label: "Ask about the neighborhood"}, {id: "neighbors", label: "Ask about the neighbors"} ], "Beach": [ {id: "beach_talk", label: "Talk about the weather"}, {id: "swimming", label: "Ask if they like swimming"} ], "StripClub": [ {id: "entertainment", label: "Ask about the entertainment"}, {id: "regulars", label: "Ask about regulars"} ], "Brothel": [ {id: "services_talk", label: "Ask about services"}, {id: "worker_life", label: "Ask about the lifestyle"} ], "Cafe": [ {id: "coffee_talk", label: "Talk about coffee preferences"}, {id: "hangout", label: "Ask if they come here often"} ], "Downtown": [ {id: "city_talk", label: "Talk about city life"}, {id: "events", label: "Ask about upcoming events"} ], "Docks": [ {id: "ships_talk", label: "Ask about the ships"}, {id: "work_talk", label: "Ask about dock work"} ], "RedLightDistrict": [ {id: "nightlife", label: "Ask about the nightlife"}, {id: "staying_safe", label: "Ask about staying safe here"} ] }>> /* Get location-specific topics */ <<set setup.getLocationTopics = function(location) { return setup.locationDialogueTopics[location] || []; }>> /* ---------------------------------- */ /* --- FLIRTING SYSTEM --- */ /* ---------------------------------- */ /* Flirting success factors based on traits and relationship */ <<set setup.flirtingSystem = { baseSuccessChance: 20, modifiers: { "Seductive": 25, "Flirty": 20, "Attractive": 15, "Confident": 10, "Charismatic": 10, "Shy": -15, "Awkward": -10, "Unattractive": -20 }, relationshipBonus: { 0: 0, /* Stranger - no bonus */ 1: 10, /* Acquaintance */ 2: 20, /* Friend */ 3: 35, /* Close Friend */ 4: 50 /* Best Friend */ } }>> /* Calculate flirt success chance */ <<set setup.calculateFlirtChance = function(npcName) { var v = State.variables; var player = v.player || {}; var playerTraits = player.mentalTraits || []; var playerPhysicalTraits = player.physicalTraits || []; var allTraits = playerTraits.concat(playerPhysicalTraits); var chance = setup.flirtingSystem.baseSuccessChance; /* Apply trait modifiers */ for (var i = 0; i < allTraits.length; i++) { var trait = allTraits[i]; if (setup.flirtingSystem.modifiers[trait]) { chance += setup.flirtingSystem.modifiers[trait]; } } /* Apply relationship bonus */ var rel = v.npcRelationships[npcName]; if (rel) { chance += setup.flirtingSystem.relationshipBonus[rel.level] || 0; } /* Check NPC's receptiveness based on their traits */ var npc = setup.findNPCByName(npcName); if (npc) { var npcTraits = (npc.mentalTraits || []).concat(npc.physicalTraits || []); for (var j = 0; j < npcTraits.length; j++) { var npcTrait = npcTraits[j]; if (npcTrait === "Flirty" || npcTrait === "Seductive") { chance += 15; } else if (npcTrait === "Prudish" || npcTrait === "Reserved") { chance -= 15; } } } /* Clamp between 5 and 95 */ return Math.max(5, Math.min(95, chance)); }>> /* Attempt to flirt with an NPC */ <<set setup.attemptFlirt = function(npcName) { var v = State.variables; var chance = setup.calculateFlirtChance(npcName); var roll = Math.floor(Math.random() * 100); var success = roll < chance; /* Track flirt attempts */ if (!v.flirtHistory) v.flirtHistory = {}; if (!v.flirtHistory[npcName]) { v.flirtHistory[npcName] = { attempts: 0, successes: 0, lastAttempt: 0, arousalLevel: 0 }; } v.flirtHistory[npcName].attempts++; v.flirtHistory[npcName].lastAttempt = v.dayNumber; if (success) { v.flirtHistory[npcName].successes++; v.flirtHistory[npcName].arousalLevel = Math.min(100, v.flirtHistory[npcName].arousalLevel + 15); /* Add relationship points */ setup.addRelationshipXP(npcName, 5); } else { v.flirtHistory[npcName].arousalLevel = Math.max(0, v.flirtHistory[npcName].arousalLevel - 5); } return { success: success, chance: chance, roll: roll, arousalLevel: v.flirtHistory[npcName].arousalLevel }; }>> /* Get flirt responses based on NPC personality */ <<set setup.getFlirtResponse = function(npcName, success) { var npc = setup.findNPCByName(npcName); if (!npc) return "..."; var traits = (npc.mentalTraits || []).concat(npc.physicalTraits || []); var isFlirty = traits.includes("Flirty") || traits.includes("Seductive"); var isShy = traits.includes("Shy") || traits.includes("Reserved"); var isConfident = traits.includes("Confident") || traits.includes("Bold"); if (success) { if (isFlirty) { return [ "*winks back* I like where this is going...", "Mmm, keep talking like that...", "*leans closer* Tell me more...", "You're quite charming, aren't you?" ][Math.floor(Math.random() * 4)]; } else if (isShy) { return [ "*blushes deeply* Oh, um... thank you...", "*looks away shyly* That's... that's really sweet...", "*fidgets nervously* I... I like that..." ][Math.floor(Math.random() * 3)]; } else if (isConfident) { return [ "*smirks* Not bad. I'm impressed.", "Smooth. I'll give you that one.", "*raises an eyebrow* Interesting approach..." ][Math.floor(Math.random() * 3)]; } else { return [ "*smiles* That's really sweet of you.", "*laughs softly* You're quite the charmer.", "*grins* Keep that up and you might get somewhere." ][Math.floor(Math.random() * 3)]; } } else { if (isConfident) { return [ "Nice try, but you'll have to do better than that.", "*looks unimpressed* Is that your best line?", "Points for effort, I suppose." ][Math.floor(Math.random() * 3)]; } else if (isShy) { return [ "*looks uncomfortable* Um... I'm not sure...", "*shifts awkwardly* That's... that's a bit forward..." ][Math.floor(Math.random() * 2)]; } else { return [ "*polite but distant* That's... nice of you to say.", "*laughs awkwardly* Thanks, I guess?", "*changes subject* So anyway..." ][Math.floor(Math.random() * 3)]; } } }>> /* ---------------------------------- */ /* --- SEXUAL ENCOUNTER SYSTEM --- */ /* ---------------------------------- */ /* Check if sexual encounter is possible */ <<set setup.canInitiateSexualEncounter = function(npcName) { var v = State.variables; /* Check relationship level (minimum Close Friend - level 3) */ var rel = v.npcRelationships[npcName]; if (!rel || rel.level < 3) return { possible: false, reason: "Not close enough" }; /* Check arousal level */ var flirtHistory = v.flirtHistory && v.flirtHistory[npcName]; if (!flirtHistory || flirtHistory.arousalLevel < 50) { return { possible: false, reason: "Not aroused enough" }; } /* Check NPC traits for willingness */ var npc = setup.findNPCByName(npcName); if (npc) { var traits = (npc.mentalTraits || []).concat(npc.physicalTraits || []); if (traits.includes("Prudish") && rel.level < 4) { return { possible: false, reason: "NPC is too reserved" }; } } return { possible: true, reason: "Ready" }; }>> /* Sexual encounter willingness check */ <<set setup.checkSexualWillingness = function(npcName) { var v = State.variables; var baseChance = 30; /* Relationship level bonus */ var rel = v.npcRelationships[npcName]; if (rel) { baseChance += rel.level * 15; } /* Arousal bonus */ var flirtHistory = v.flirtHistory && v.flirtHistory[npcName]; if (flirtHistory) { baseChance += Math.floor(flirtHistory.arousalLevel / 2); } /* NPC trait modifiers */ var npc = setup.findNPCByName(npcName); if (npc) { var traits = (npc.mentalTraits || []).concat(npc.physicalTraits || []); if (traits.includes("Flirty") || traits.includes("Seductive")) { baseChance += 20; } if (traits.includes("Nympho") || traits.includes("Lustful")) { baseChance += 30; } if (traits.includes("Prudish")) { baseChance -= 25; } if (traits.includes("Reserved")) { baseChance -= 15; } } return Math.max(5, Math.min(95, baseChance)); }>> /* Track sexual encounters */ <<set setup.recordSexualEncounter = function(npcName, encounterType) { var v = State.variables; if (!v.sexualEncounters) v.sexualEncounters = {}; if (!v.sexualEncounters[npcName]) { v.sexualEncounters[npcName] = { totalEncounters: 0, firstEncounter: v.dayNumber, lastEncounter: v.dayNumber, encounterTypes: {} }; } var record = v.sexualEncounters[npcName]; record.totalEncounters++; record.lastEncounter = v.dayNumber; if (!record.encounterTypes[encounterType]) { record.encounterTypes[encounterType] = 0; } record.encounterTypes[encounterType]++; /* Reset arousal after encounter */ if (v.flirtHistory && v.flirtHistory[npcName]) { v.flirtHistory[npcName].arousalLevel = 0; } /* Add significant relationship points */ setup.addRelationshipXP(npcName, 25); return record; }>> /* ---------------------------------- */ /* --- DIALOGUE OPTION GENERATOR --- */ /* ---------------------------------- */ /* Generate dialogue options based on context */ <<set setup.generateDialogueOptions = function(npcName, currentLocation) { var v = State.variables; var options = []; /* Get relationship level */ var rel = v.npcRelationships[npcName] || { level: 0 }; /* Basic options always available */ options.push({ id: "small_talk", label: "Make small talk", category: "casual", minLevel: 0 }); /* Location-specific topics */ var locationTopics = setup.getLocationTopics(currentLocation); for (var i = 0; i < locationTopics.length; i++) { options.push({ id: locationTopics[i].id, label: locationTopics[i].label, category: "location", minLevel: 0 }); } /* Acquaintance+ options (level 1+) */ if (rel.level >= 1) { options.push({ id: "ask_about_day", label: "Ask about their day", category: "personal", minLevel: 1 }); options.push({ id: "share_story", label: "Share a story", category: "personal", minLevel: 1 }); } /* Friend+ options (level 2+) */ if (rel.level >= 2) { options.push({ id: "ask_advice", label: "Ask for advice", category: "personal", minLevel: 2 }); options.push({ id: "flirt_light", label: "Flirt lightly", category: "romantic", minLevel: 2 }); } /* Close Friend+ options (level 3+) */ if (rel.level >= 3) { options.push({ id: "deep_conversation", label: "Have a deep conversation", category: "personal", minLevel: 3 }); options.push({ id: "flirt_heavy", label: "Flirt suggestively", category: "romantic", minLevel: 3 }); options.push({ id: "discuss_risque", label: "Discuss risque topics", category: "risque", minLevel: 3 }); } /* Best Friend+ options (level 4+) */ if (rel.level >= 4) { options.push({ id: "intimate_talk", label: "Have an intimate conversation", category: "sexual", minLevel: 4 }); /* Check if sexual encounter possible */ var canSex = setup.canInitiateSexualEncounter(npcName); if (canSex.possible) { options.push({ id: "initiate_sex", label: "Suggest something more...", category: "sexual", minLevel: 4 }); } } return options; }>> /* Get interest-based dialogue topics for an NPC */ <<set setup.getNPCDialogueTopics = function(npcName) { var v = State.variables; var npc = setup.findNPCByName(npcName); if (!npc) return []; var rel = v.npcRelationships[npcName] || { level: 0 }; var availableTopics = setup.getAvailableTopics(npcName, rel.level); /* Get NPC's interests if they exist */ var npcInterests = npc.interests || []; /* Combine with available topics based on relationship */ var topics = []; for (var i = 0; i < availableTopics.length; i++) { var topic = availableTopics[i]; var isInterest = npcInterests.includes(topic); topics.push({ topic: topic, isInterest: isInterest, engagementBonus: isInterest ? 15 : 0 }); } return topics; }>> /* ---------------------------------- */ /* --- PLAYER PAINTINGS SYSTEM --- */ /* ---------------------------------- */ <<set $playerPaintings = [ { id: "preset_suits", title: "Suits", imageData: "Images/Other/Paintings/SuitsImage.webp", createdDay: 0, isPreset: true } ]>> <<set $roomPaintings = {}>>
test
:: InitTimeSystem <<silently>> /* ---------------------------------- */ /* --- TIME & DAY TRACKING --- */ /* ---------------------------------- */ <<set $timeInMinutes = 480>> /* Start at 8:00 AM */ <<set $dayOfWeek = "Monday">> <<set $dayNumber = 1>> <<set $weekNumber = 1>> <<set setup.dayOrder = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]>> /* ---------------------------------- */ /* --- TRADE LIMITS --- */ /* ---------------------------------- */ <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> /* ---------------------------------- */ /* --- WORK TRACKING --- */ /* ---------------------------------- */ <<set $hoursWorkedToday = 0>> <<set $lastWorkDay = 0>> /* ---------------------------------- */ /* --- BUFF/DEBUFF SYSTEM --- */ /* ---------------------------------- */ <<set $lastSleepTime = ($dayNumber - 1) * 1440 + $timeInMinutes>> /* Track when player last slept */ <<set $activeBuffs = []>> /* Array of active buffs */ <<set $activeDebuffs = []>> /* Array of active debuffs */ <</silently>> /* Ensure all NPCs have hair length on game load */ <<set setup.ensureAllNPCsHaveHairLength = function() { var v = State.variables; if (v.npcs && v.npcs.length > 0) { v.npcs.forEach(function(npc) { if (!npc.appearance.hairLength) { npc.appearance.hairLength = Math.random() < 0.5 ? "short" : "long"; /* Remove any existing hair length traits first */ npc.physicalTraits.delete("Short Hair"); npc.physicalTraits.delete("Long Hair"); /* Add correct trait */ var hairLengthTrait = npc.appearance.hairLength === "short" ? "Short Hair" : "Long Hair"; if (!npc.physicalTraits.includes(hairLengthTrait)) { npc.physicalTraits.push(hairLengthTrait); } } }); } }>> /* Run the check immediately */ <<run setup.ensureAllNPCsHaveHairLength()>>
<<nobr>> /* Safety check - if this is somehow the first passage, redirect to actual start */ <<if visited() === 1 && tags().includes("start")>> <<goto "Start">> <</if>> <h1>🛍️ Sunfish City Mall - CLOSED</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 20px;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> ⏰ The mall is currently closed. </p> </div> <div style="padding: 20px; background: #3d3d3d; border-radius: 10px; text-align: center; color: #e0e0e0;"> <h2 style="color: #ffffff;">Mall Hours</h2> <p style="font-size: 18px; color: #cccccc;"> <strong>Open:</strong> 8:00 AM - 9:00 PM<br> <strong>Current Time:</strong> <<= getTimeString()>> </p> <p style="color: #aaaaaa; margin-top: 20px;"> The mall opens at 8:00 AM and closes at 9:00 PM. Come back during business hours! </p> </div> <br> <div style="text-align: center;"> [[Leave|BusinessDistrict]] </div> <</nobr>>
:: InitNPCData <<silently>> /* ================================== */ /* === NPC HELPER FUNCTIONS === */ /* ================================== */ <<set setup.findNPCByName = function(name) { var v = State.variables; for (var i = 0; i < v.npcs.length; i++) { if (v.npcs[i].name === name) { return v.npcs[i]; } } return null; }>> /* ---------------------------------- */ /* --- MANUAL NPC CREATION FUNCTION --- */ /* ---------------------------------- */ <<set setup.createNPC = function(config) { var skinTones = ["pale", "tan", "dark"]; var hairColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]; var hairStyles = ["short", "long"]; var ages = ["Adult", "Mature Adult"]; /* Determine hair length and add corresponding trait */ var hairLength = config.hairLength || (config.gender === "female" ? "long" : "short"); var hairLengthTrait = hairLength === "short" ? "Short Hair" : "Long Hair"; /* Add hair length trait to physical traits */ var allPhysicalTraits = config.physicalTraits.slice(); if (!allPhysicalTraits.includes(hairLengthTrait)) { allPhysicalTraits.push(hairLengthTrait); } /* Calculate stats from job requirements */ var jobName = Array.isArray(config.jobs) ? config.jobs[0] : config.jobs; var jobReqs = setup.jobRequirements[jobName] || {}; var npcStats = { charisma: config.baseStats.charisma || 15, dexterity: config.baseStats.dexterity || 15, strength: config.baseStats.strength || 15, intelligence: config.baseStats.intelligence || 15 }; /* Ensure stats meet job requirements */ for (var stat in jobReqs) { if (npcStats[stat] < jobReqs[stat]) { npcStats[stat] = jobReqs[stat]; } } var npc = { name: config.name, originalName: config.name, /* Store original name for image paths */ jobs: Array.isArray(config.jobs) ? config.jobs : [config.jobs], stats: npcStats, statMaxCaps: { charisma: 100, dexterity: 100, strength: 100, intelligence: 100 }, bodyParts: { gender: config.gender, chest: config.chest, butt: config.butt, genitals: config.genitals || "penis" }, appearance: { skinTone: config.skinTone || skinTones[Math.floor(Math.random() * skinTones.length)], hairColor: config.hairColor || hairColors[Math.floor(Math.random() * hairColors.length)], hairStyle: config.hairStyle || hairStyles[Math.floor(Math.random() * hairStyles.length)], hairLength: hairLength, physique: config.physique || "average", age: config.age || ages[Math.floor(Math.random() * ages.length)] }, skills: config.skills, physicalTraits: allPhysicalTraits, mentalTraits: config.mentalTraits, voiceTraits: (config.voiceTraits || []).slice(), hardTraits: {}, speechStyle: config.speechStyle || null, mood: { name: "neutral", intensity: 30, cacheKey: -1 } }; /* Preserve trait-trading lock from config (used by special NPCs like Bun Bun). */ if (config.traitTradingLocked) npc.traitTradingLocked = true; /* Generate hard traits */ function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } npc.skills.forEach(function(skill) { npc.hardTraits["skill:" + skill] = getRandomInt(0, 40); }); npc.physicalTraits.forEach(function(trait) { npc.hardTraits["physical:" + trait] = getRandomInt(0, 40); }); npc.mentalTraits.forEach(function(trait) { npc.hardTraits["mental:" + trait] = getRandomInt(0, 40); }); ["charisma", "dexterity", "strength", "intelligence"].forEach(function(stat) { npc.hardTraits["stat:" + stat] = getRandomInt(0, 40); }); ["chest", "butt", "gender"].forEach(function(bodyPart) { npc.hardTraits["bodyPart:" + bodyPart] = getRandomInt(10, 50); }); /* Apply trait bonuses */ npc.mentalTraits.forEach(function(trait) { if (setup.traitBonuses && setup.traitBonuses[trait]) { setup.applyTraitBonus(trait, npc); } }); npc.physicalTraits.forEach(function(trait) { if (setup.traitBonuses && setup.traitBonuses[trait]) { setup.applyTraitBonus(trait, npc); } }); npc.skills.forEach(function(skill) { if (setup.skillBonuses && setup.skillBonuses[skill]) { setup.applyTraitBonus(skill, npc); } }); return npc; }>> /* ---------------------------------- */ /* --- CREATE NPCs --- */ /* ---------------------------------- */ /* Marcus Carter - Security Guard */ <<run $npcs.push(setup.createNPC({ name: "Marcus Carter", speechStyle: "flirtatious", jobs: "Security Guard", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "penis", baseStats: {charisma: 20, dexterity: 15, strength: 25, intelligence: 15}, physicalTraits: ["Muscular", "Tall", "Strong", "Broad-shouldered"], mentalTraits: ["Confident", "Outgoing", "Brave", "Charming"], skills: ["Combat", "Athletics", "Public Speaking", "Acting", "Guitar"], skinTone: "tan", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Elena Romero - Clinic Assistant & Data Analyst */ <<run $npcs.push(setup.createNPC({ name: "Elena Romero", speechStyle: "analytical", jobs: ["Clinic Assistant"], gender: "female", chest: "small", butt: "small", genitals: "tight vagina", baseStats: {charisma: 20, dexterity: 20, strength: 10, intelligence: 55}, physicalTraits: ["Graceful", "Youthful", "Sharp Features"], mentalTraits: ["Intelligent", "Analytical", "Patient", "Kind", "Nerd", "Shy"], skills: ["Medicine", "First Aid", "Coding", "Math Skills", "Painting"], skinTone: "tan", hairColor: "Brown", hairLength: "long", age: "Adult" }))>> /* Silva Silva - Package Courier & Negotiator */ <<run $npcs.push(setup.createNPC({ name: "Silva Silva", speechStyle: "commanding", jobs: ["Package Courier"], gender: "female", chest: "medium", butt: "medium", genitals: "vagina", baseStats: {charisma: 55, dexterity: 20, strength: 15, intelligence: 20}, physicalTraits: ["Quick", "Lean", "Athletic Build", "Fashionable"], mentalTraits: ["Shrewd", "Confident", "Ambitious", "Diplomatic"], skills: ["Driving", "Athletics", "Persuasion", "Public Speaking", "Languages"], skinTone: "pale", hairColor: "Blonde", hairLength: "long", age: "Adult" }))>> /* Grimm Patel - Negotiator & Enforcer */ <<run $npcs.push(setup.createNPC({ name: "Grimm Patel", speechStyle: "blunt", jobs: ["Negotiator"], gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 55, dexterity: 20, strength: 55, intelligence: 20}, physicalTraits: ["Muscular", "Strong", "Scarred", "Sharp Features"], mentalTraits: ["Dominant", "Shrewd", "Stubborn", "Cynical", "Intimidating"], skills: ["Combat", "Stealth", "Persuasion", "Public Speaking", "Cooking"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Mature Adult" }))>> /* Scarlett Vex - Porn Star */ <<run $npcs.push(setup.createNPC({ name: "Scarlett Vex", speechStyle: "flirtatious", jobs: "Porn Star", gender: "female", chest: "huge", butt: "huge", genitals: "loose vagina", baseStats: {charisma: 60, dexterity: 25, strength: 15, intelligence: 15}, physicalTraits: ["Attractive", "Voluptuous", "Fit", "Smooth Skin"], mentalTraits: ["Confident", "Outgoing", "Ambitious", "Seductive", "Arrogant"], skills: ["Sexually Skilled", "Acting", "Modeling", "High Heels Proficient", "Dancing", "Photography"], skinTone: "pale", hairColor: "Red", hairLength: "long", age: "Adult" }))>> /* Jade Nightshade - Stripper */ <<run $npcs.push(setup.createNPC({ name: "Jade Nightshade", speechStyle: "flirtatious", jobs: "Stripper", gender: "female", chest: "large", butt: "large", genitals: "vagina", baseStats: {charisma: 40, dexterity: 30, strength: 15, intelligence: 15}, physicalTraits: ["Attractive", "Flexible", "Graceful", "Curvy"], mentalTraits: ["Sly", "Confident", "Creative", "Flirty", "Manipulative"], skills: ["Dancing", "Sexually Skilled", "High Heels Proficient", "Acting", "Singing"], skinTone: "tan", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Apollo Sterling - Stripper */ <<run $npcs.push(setup.createNPC({ name: "Apollo Sterling", speechStyle: "excitable", jobs: "Stripper", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 45, dexterity: 30, strength: 25, intelligence: 15}, physicalTraits: ["Attractive", "Muscular", "Flexible", "Graceful"], mentalTraits: ["Confident", "Outgoing", "Creative", "Charming", "Vain"], skills: ["Dancing", "Sexually Skilled", "Modeling", "Athletics", "Music"], skinTone: "pale", hairColor: "Blonde", hairLength: "short", age: "Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "Apollo strikes a pose as you approach, one hand on his hip. 'Well hello there. Enjoying the view?' He flashes a practiced smile.", "'New face?' Apollo looks you up and down appraisingly. 'Welcome to the show, darling.'" ], acquaintance: [ "'Hey there!' Apollo calls out with a wave. 'Back for another look? Can't say I blame you.'", "Apollo grins when he sees you. 'Ah, my favorite audience member returns.'" ], friend: [ "'Hey gorgeous!' Apollo calls out. 'You know, you're becoming one of my favorite people to see walk through that door.'", "Apollo's smile seems more genuine than his stage persona. 'There you are! I was hoping you'd stop by.'" ], closeFriend: [ "Apollo's face lights up genuinely when he sees you. 'There you are! I was just thinking about you.' For once, the charm seems completely real.", "'Finally!' Apollo beams. 'Someone I can actually talk to without the performance.'" ], bestFriend: [ "Apollo abandons his usual dramatic flair and gives you a warm, genuine smile. 'Hey you. Rough day. You're exactly who I needed to see.'", "'Thank god,' Apollo sighs with relief when he spots you. 'I've been drowning in shallow conversations. Come save me.'" ] }, smallTalk: [ "'The stage lights can be brutal, but the attention? Worth every hot minute under them.'", "'I spend more time on my appearance than most people spend on their entire lives. But look at these results!'", "'Dancing is art, darling. My body is the canvas, the music is my paint.'" ], complimentReactions: { low: "Apollo preens visibly. 'Well of course. But do tell me more...'", high: "Apollo's smile softens. 'Coming from you? That actually means something.'" } } })>> /* Diamond Murphy - Prostitute */ <<run $npcs.push(setup.createNPC({ name: "Diamond Murphy", speechStyle: "blunt", jobs: "Prostitute", gender: "female", chest: "large", butt: "large", genitals: "loose vagina", baseStats: {charisma: 35, dexterity: 20, strength: 15, intelligence: 15}, physicalTraits: ["Attractive", "Curvy", "Tattooed"], mentalTraits: ["Sly", "Hardworking", "Stubborn", "Selfish", "Street Smart"], skills: ["Sexually Skilled", "Persuasion", "Stealth", "Baking"], skinTone: "dark", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Tank Morrison - Bouncer */ <<run $npcs.push(setup.createNPC({ name: "Tank Morrison", speechStyle: "chill", jobs: "Bouncer", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 20, dexterity: 20, strength: 50, intelligence: 15}, physicalTraits: ["Muscular", "Tall", "Strong", "Broad-shouldered", "Scarred"], mentalTraits: ["Brave", "Calm", "Honest", "Loyal", "Protective"], skills: ["Combat", "Heavy Lifting", "Athletics", "Cooking"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Mature Adult" }))>> /* Candace Luxe - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Candace Luxe", speechStyle: "motherly", jobs: "Brothel Worker", gender: "female", chest: "huge", butt: "huge", genitals: "loose vagina", baseStats: {charisma: 40, dexterity: 25, strength: 15, intelligence: 20}, physicalTraits: ["Attractive", "Voluptuous", "Smooth Skin", "Pierced"], mentalTraits: ["Confident", "Friendly", "Empathetic", "Warm", "Nurturing"], skills: ["Sexually Skilled", "Persuasion", "High Heels Proficient", "Dancing", "Painting"], skinTone: "pale", hairColor: "Blonde", hairLength: "long", age: "Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "A warm smile crosses Candace's face. 'Hello there, sweetheart. First time? Don't worry, everyone's welcome here.'", "'Well hello,' Candace says with genuine friendliness. 'You look a little lost. Can I help you with something?'" ], acquaintance: [ "'There you are!' Candace beams. 'It's good to see you again, hun.'", "Candace's eyes light up with recognition. 'Hey! How have you been, sweetie?'" ], friend: [ "Candace wraps you in a warm hug. 'There's my favorite person! I was hoping you'd visit.'", "'Oh honey,' Candace smiles warmly. 'You always know when to show up. Come here.'" ], closeFriend: [ "Candace immediately reads your mood. 'Hey love. You look like you could use some company. Talk to me.'", "'There you are,' Candace says softly, her empathy evident. 'Rough day? I can tell.'" ], bestFriend: [ "Candace's professional warmth gives way to genuine affection. 'Thank god you're here. I've missed you.'", "'Finally,' Candace sighs with relief. 'Someone I can actually be myself with. How are you, really?'" ] }, smallTalk: [ "'Everyone needs connection, sweetie. That's all anyone really wants - to be seen and accepted.'", "'I take care of people. That's what I do, whether it's my job or my nature.'", "'The work can be demanding, but helping people feel good about themselves? That's worth it.'" ], complimentReactions: { low: "Candace smiles warmly. 'That's very sweet of you to say, hun.'", high: "Candace's eyes shimmer with genuine emotion. 'You always know what to say to make me feel special.'" } } })>> /* Ruby Becker - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Ruby Becker", speechStyle: "nervous", jobs: "Brothel Worker", gender: "female", chest: "large", butt: "large", genitals: "tight vagina", baseStats: {charisma: 40, dexterity: 25, strength: 15, intelligence: 18}, physicalTraits: ["Attractive", "Curvy", "Smooth Skin", "Freckled"], mentalTraits: ["Shy", "Kind", "Creative", "Sensitive", "Romantic"], skills: ["Sexually Skilled", "Persuasion", "High Heels Proficient", "Writing", "Photography"], skinTone: "pale", hairColor: "Red", hairLength: "long", age: "Adult" }))>> /* Sapphire Wallace - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Sapphire Wallace", speechStyle: "commanding", jobs: "Brothel Worker", gender: "female", chest: "huge", butt: "large", genitals: "vagina", baseStats: {charisma: 42, dexterity: 25, strength: 15, intelligence: 18}, physicalTraits: ["Attractive", "Voluptuous", "Smooth Skin", "Tattooed"], mentalTraits: ["Dominant", "Confident", "Ambitious", "Aggressive", "Competitive"], skills: ["Sexually Skilled", "Persuasion", "High Heels Proficient", "Dancing", "Martial Arts"], skinTone: "dark", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Jasmine Abrams - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Jasmine Abrams", speechStyle: "warm", jobs: "Brothel Worker", gender: "female", chest: "medium", butt: "huge", genitals: "vagina", baseStats: {charisma: 40, dexterity: 28, strength: 15, intelligence: 18}, physicalTraits: ["Attractive", "Flexible", "Graceful", "Smooth Skin"], mentalTraits: ["Submissive", "Friendly", "Patient", "Kind", "Gentle"], skills: ["Sexually Skilled", "Persuasion", "High Heels Proficient", "Dancing", "Yoga"], skinTone: "tan", hairColor: "Brown", hairLength: "long", age: "Adult" }))>> /* Ebony Vasquez - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Ebony Vasquez", speechStyle: "sarcastic", jobs: "Brothel Worker", gender: "female", chest: "large", butt: "huge", genitals: "vagina", baseStats: {charisma: 40, dexterity: 25, strength: 15, intelligence: 20}, physicalTraits: ["Attractive", "Curvy", "Smooth Skin"], mentalTraits: ["Sly", "Witty", "Competitive", "Clever", "Playful"], skills: ["Sexually Skilled", "Persuasion", "High Heels Proficient", "Acting", "Singing"], skinTone: "dark", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Amber Skye - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Amber Skye", speechStyle: "bubbly", jobs: "Brothel Worker", gender: "female", chest: "medium", butt: "large", genitals: "tight vagina", baseStats: {charisma: 40, dexterity: 25, strength: 15, intelligence: 18}, physicalTraits: ["Attractive", "Curvy", "Smooth Skin", "Youthful"], mentalTraits: ["Optimistic", "Energetic", "Curious", "Naive", "Bubbly"], skills: ["Sexually Skilled", "Persuasion", "High Heels Proficient", "Social Media", "Music"], skinTone: "tan", hairColor: "Blonde", hairLength: "long", age: "Adult" }))>> /* Kate Velvet - Brothel Owner */ <<run $npcs.push(setup.createNPC({ name: "Kate Velvet", speechStyle: "commanding", jobs: "Brothel Owner", gender: "female", chest: "huge", butt: "huge", genitals: "vagina", baseStats: {charisma: 80, dexterity: 25, strength: 20, intelligence: 60}, physicalTraits: ["Attractive", "Mature", "Voluptuous", "Sharp Features"], mentalTraits: ["Dominant", "Shrewd", "Ambitious", "Confident", "Arrogant", "Diva"], skills: ["Management", "Persuasion", "Accounting", "Sexually Skilled", "Languages", "Leadership"], skinTone: "pale", hairColor: "Red", hairLength: "long", age: "Mature Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "Kate's sharp eyes appraise you from head to toe. 'And you are?' Her tone makes it clear she expects you to prove your worth.", "'I don't recognize you.' Kate's voice carries authority. 'State your business or move along.'" ], acquaintance: [ "Kate acknowledges you with a curt nod. 'You again. At least you're punctual.'", "'Ah.' Kate's expression remains neutral. 'You've been here before. Acceptable.'" ], friend: [ "Kate's severe expression softens slightly. 'Good. Someone competent. Come in.'", "'There you are,' Kate says with what might almost be approval. 'I could use someone with sense right now.'" ], closeFriend: [ "Kate actually smiles - a rare sight. 'Finally, someone I can have a real conversation with. Everyone else is so tedious today.'", "'Perfect timing,' Kate says, her usual imperious tone warmed with genuine pleasure. 'I was just thinking about you.'" ], bestFriend: [ "Kate's mask drops entirely, revealing unexpected warmth. 'Thank god. Come here, I need your opinion on something actually important.'", "'There you are,' Kate sighs with relief. 'Everyone's been insufferable today. You're the only one who understands.'" ] }, smallTalk: [ "'Power isn't given, it's taken. I learned that lesson early and I've never forgotten it.'", "'Running an empire requires vision, control, and the willingness to make difficult decisions.'", "'Respect is earned through competence and results, not through groveling or sentiment.'" ], complimentReactions: { low: "Kate raises an eyebrow. 'Flattery? How transparent. But... not unwelcome.'", high: "Kate's eyes gleam with something like genuine appreciation. 'From you, that's actually meaningful.'" } } })>> /* Bella Carver - Social Media Influencer */ <<run $npcs.push(setup.createNPC({ name: "Bella Carver", speechStyle: "bubbly", jobs: "Social Media Influencer", gender: "female", chest: "large", butt: "large", genitals: "vagina", baseStats: {charisma: 50, dexterity: 25, strength: 15, intelligence: 25}, physicalTraits: ["Attractive", "Youthful", "Curvy", "Fashionable"], mentalTraits: ["Outgoing", "Creative", "Ambitious", "Naive", "Vain", "Prep"], skills: ["Social Media", "Photography", "Modeling", "Acting", "Makeup"], skinTone: "tan", hairColor: "Brown", hairLength: "long", age: "Adult" }))>> /* Jake Steel - Construction Worker */ <<run $npcs.push(setup.createNPC({ name: "Jake Steel", speechStyle: "chill", jobs: "Construction Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "penis", baseStats: {charisma: 15, dexterity: 18, strength: 30, intelligence: 15}, physicalTraits: ["Muscular", "Strong", "Sturdy", "Broad-shouldered"], mentalTraits: ["Hardworking", "Honest", "Calm", "Loyal", "Simple"], skills: ["Heavy Lifting", "Construction", "Driving", "Fishing"], skinTone: "tan", hairColor: "Brown", hairLength: "short", age: "Adult" }))>> /* Marco Rodriguez - Construction Worker */ <<run $npcs.push(setup.createNPC({ name: "Marco Rodriguez", speechStyle: "excitable", jobs: "Construction Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "penis", baseStats: {charisma: 18, dexterity: 18, strength: 30, intelligence: 15}, physicalTraits: ["Muscular", "Strong", "Sturdy", "Tattooed"], mentalTraits: ["Friendly", "Competitive", "Brave", "Hot-Headed", "Passionate"], skills: ["Heavy Lifting", "Construction", "Cooking", "Guitar"], skinTone: "tan", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Tyrone Washington - Construction Worker */ <<run $npcs.push(setup.createNPC({ name: "Tyrone Washington", speechStyle: "sarcastic", jobs: "Construction Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 20, dexterity: 18, strength: 32, intelligence: 15}, physicalTraits: ["Muscular", "Strong", "Sturdy", "Broad-shouldered", "Tall"], mentalTraits: ["Outgoing", "Witty", "Confident", "Funny", "Jock"], skills: ["Heavy Lifting", "Construction", "Basketball", "Music"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Sheryl Williams - Construction Worker */ <<run $npcs.push(setup.createNPC({ name: "Sheryl Williams", speechStyle: "blunt", jobs: "Construction Worker", gender: "female", chest: "small", butt: "medium", genitals: "tight vagina", baseStats: {charisma: 18, dexterity: 20, strength: 30, intelligence: 18}, physicalTraits: ["Muscular", "Strong", "Sturdy", "Athletic Build"], mentalTraits: ["Hardworking", "Stubborn", "Brave", "Direct", "Tomboy"], skills: ["Heavy Lifting", "Construction", "Martial Arts", "Gardening"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* David O'Brien - Construction Worker */ <<run $npcs.push(setup.createNPC({ name: "David O'Brien", jobs: "Construction Worker", speechStyle: "chill", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "penis", baseStats: {charisma: 15, dexterity: 18, strength: 28, intelligence: 15}, physicalTraits: ["Muscular", "Strong", "Sturdy", "Freckled"], mentalTraits: ["Calm", "Patient", "Thoughtful", "Quiet", "Reserved"], skills: ["Heavy Lifting", "Construction", "Plumbing", "Painting"], skinTone: "pale", hairColor: "Red", hairLength: "short", age: "Mature Adult" }))>> /* Mike Murphy - Dock Worker */ <<run $npcs.push(setup.createNPC({ name: "Mike Murphy", speechStyle: "aggressive", jobs: "Dock Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 18, dexterity: 20, strength: 32, intelligence: 15}, physicalTraits: ["Muscular", "Strong", "Broad-shouldered", "Tattooed"], mentalTraits: ["Aggressive", "Competitive", "Brave", "Short Tempered", "Reckless"], skills: ["Heavy Lifting", "Athletics", "Swimming", "Cooking"], skinTone: "pale", hairColor: "Brown", hairLength: "short", age: "Adult" }))>> /* Carlos Mendez - Dock Worker */ <<run $npcs.push(setup.createNPC({ name: "Carlos Mendez", speechStyle: "flirtatious", jobs: "Dock Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 20, dexterity: 20, strength: 30, intelligence: 15}, physicalTraits: ["Muscular", "Strong", "Broad-shouldered"], mentalTraits: ["Friendly", "Outgoing", "Optimistic", "Charming", "Flirty"], skills: ["Heavy Lifting", "Athletics", "Dancing", "Guitar"], skinTone: "tan", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Jamal Rivers - Dock Worker */ <<run $npcs.push(setup.createNPC({ name: "Jamal Rivers", speechStyle: "analytical", jobs: "Dock Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 20, dexterity: 22, strength: 32, intelligence: 18}, physicalTraits: ["Muscular", "Strong", "Broad-shouldered", "Athletic Build"], mentalTraits: ["Ambitious", "Intelligent", "Competitive", "Determined", "Focused"], skills: ["Heavy Lifting", "Athletics", "Basketball", "Writing"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Rosa Otterino - Dock Worker */ <<run $npcs.push(setup.createNPC({ name: "Rosa Otterino", speechStyle: "chill", jobs: "Dock Worker", gender: "female", chest: "small", butt: "medium", genitals: "vagina", baseStats: {charisma: 18, dexterity: 22, strength: 30, intelligence: 18}, physicalTraits: ["Muscular", "Strong", "Athletic Build"], mentalTraits: ["Hardworking", "Honest", "Calm", "Reliable", "Reserved", "Trusting"], skills: ["Heavy Lifting", "Athletics", "Swimming", "Painting"], skinTone: "tan", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Keisha Jackson - Dock Worker */ <<run $npcs.push(setup.createNPC({ name: "Keisha Jackson", speechStyle: "excitable", jobs: "Dock Worker", gender: "female", chest: "medium", butt: "large", genitals: "vagina", baseStats: {charisma: 22, dexterity: 20, strength: 32, intelligence: 18}, physicalTraits: ["Muscular", "Strong", "Broad-shouldered", "Curvy"], mentalTraits: ["Confident", "Outgoing", "Brave", "Bold", "Sassy"], skills: ["Heavy Lifting", "Athletics", "Singing", "Cooking"], skinTone: "dark", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Dick Richardson - City Mayor */ <<run $npcs.push(setup.createNPC({ name: "Dick Richardson", speechStyle: "commanding", jobs: "City Mayor", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 90, dexterity: 20, strength: 20, intelligence: 70}, physicalTraits: ["Mature", "Sharp Features"], mentalTraits: ["Arrogant", "Shrewd", "Ambitious", "Dominant", "Selfish", "Corrupt"], skills: ["Public Speaking", "Management", "Legal Knowledge"], skinTone: "pale", hairColor: "Brown", hairLength: "short", age: "Mature Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "Mayor Richardson looks down at you as if evaluating livestock. 'Do you have an appointment? No? Then make yourself useful or get out.'", "'Another constituent,' the Mayor says with barely concealed disdain. 'What do you want?'" ], acquaintance: [ "'You again.' The Mayor's tone suggests he's categorized you as mildly useful. 'What is it this time?'", "'Ah yes, I remember you.' Richardson's smile doesn't reach his eyes. 'Here to offer support, I trust?'" ], friend: [ "'Good to see you,' Richardson says with calculated warmth. 'You're one of the few people in this city with actual potential.'", "The Mayor's demeanor shifts to something resembling genuine interest. 'Excellent timing. I have a proposition that might benefit us both.'" ], closeFriend: [ "Richardson drops some of his political facade. 'Finally, someone I can speak plainly with. This job is exhausting when you're surrounded by idiots.'", "'There you are,' the Mayor says with real satisfaction. 'Come in. Let's discuss real business, not this performative nonsense I deal with all day.'" ], bestFriend: [ "Richardson's mask falls completely. 'Thank god. Everyone else wants something from me. You're the only one who understands how the game really works.'", "'Perfect,' Richardson says quietly. 'I need your counsel on something... delicate. You're the only one I trust with this.'" ] }, smallTalk: [ "'Politics is about leverage. Know what people want, know what they fear, and you control everything.'", "'The public elects symbols and speeches. Behind closed doors? That's where real power is wielded.'", "'Altruism is for fools. Every transaction should benefit you more than the other party.'" ], complimentReactions: { low: "Richardson smirks. 'Flattery. I appreciate the effort, but I can see through it.'", high: "Richardson studies you with new respect. 'You know, you might actually understand this city's real dynamics.'" } } })>> /* Creo Applesauce - Mayor's Secretary */ <<run $npcs.push(setup.createNPC({ name: "Creo Applesauce", speechStyle: "nervous", jobs: "Mayor's Secretary", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 60, dexterity: 25, strength: 15, intelligence: 75}, physicalTraits: ["Sharp Features", "Lean"], mentalTraits: ["Intelligent", "Analytical", "Patient", "Submissive", "Anxious", "Nerd", "Corporate Drone"], skills: ["Management", "Accounting", "Coding", "Languages", "Piano"], skinTone: "pale", hairColor: "Blonde", hairLength: "short", age: "Adult" }))>> /* Brad Icus - Fitness Shop Clerk */ <<run $npcs.push(setup.createNPC({ name: "Brad Icus", speechStyle: "excitable", jobs: "Fitness Shop Clerk", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 30, dexterity: 25, strength: 35, intelligence: 20}, physicalTraits: ["Fit", "Muscular", "Athletic Build", "Attractive"], mentalTraits: ["Energetic", "Friendly", "Optimistic", "Simple", "Jock"], skills: ["Athletics", "Sales", "Heavy Lifting", "Gardening", "Cooking"], skinTone: "tan", hairColor: "Blonde", hairLength: "short", age: "Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "'Hey there!' Brad calls out with infectious energy. 'Welcome to the shop, bro! You look like someone who wants to get PUMPED!'", "Brad practically bounces over. 'Yo! New face! That's awesome! Let me know if you need any gear recommendations!'" ], acquaintance: [ "'Hey, I know you!' Brad grins widely. 'Good to see you back! Ready to crush it today?'", "'Dude!' Brad gives you an enthusiastic wave. 'What's up! Here to level up your fitness game?'" ], friend: [ "'There's my buddy!' Brad immediately comes over for a fist bump. 'How's training going? You looking swole!'", "'Yooo!' Brad beams. 'Perfect timing, I was just thinking about inviting you to hit the gym later!'" ], closeFriend: [ "'My man!' Brad pulls you into a bro hug. 'Dude, I've been wanting to tell you about this new protein blend I tried. It's insane!'", "Brad's face lights up completely. 'There you are! Bro, serious question - you free this weekend? Got this sick hiking trail I wanna show you.'" ], bestFriend: [ "'Finally!' Brad says with genuine relief. 'Everyone else today has been all negative energy. You get it, you know? The grind, the gains, the LIFE!'", "Brad grabs your shoulder with real affection. 'Dude. Real talk. You're like, one of the few people who actually inspires me. Let's hang out after my shift.'" ] }, smallTalk: [ "'Bro, fitness isn't just about the body, it's about the MINDSET! You gotta stay positive and keep pushing!'", "'I love this job, man. Helping people get healthy? That's what it's all about!'", "'Dude, protein shakes for breakfast, killer workout, then a nice long run. Perfect day, every day!'" ], complimentReactions: { low: "Brad's grin somehow gets even wider. 'Thanks bro! That's awesome! You're awesome too!'", high: "Brad looks genuinely touched. 'Dude... that means a lot. For real. You're a true friend.'" } } })>> /* Raven Bido - Ecentric Shop Worker */ <<run $npcs.push(setup.createNPC({ name: "Raven Bido", speechStyle: "gothic", jobs: "Ecentric Shop Worker", gender: "female", chest: "small", butt: "small", genitals: "tight vagina", baseStats: {charisma: 25, dexterity: 25, strength: 15, intelligence: 22}, physicalTraits: ["Tattooed", "Pierced", "Lean", "Youthful"], mentalTraits: ["Creative", "Curious", "Introverted", "Cynical", "Goth"], skills: ["Sales", "Art", "Painting", "Music", "Writing"], skinTone: "pale", hairColor: "Black", hairLength: "long", age: "Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "Raven glances up from her book, one eyebrow pierced with a silver ring rising slightly. 'Help you?' Her tone suggests mild curiosity at best.", "'Mmm.' Raven acknowledges your presence with minimal effort. 'If you're looking for mainstream garbage, wrong shop.'" ], acquaintance: [ "'Oh. You again.' Raven's lips twitch into something almost resembling a smile. 'At least you have decent taste.'", "Raven marks her page and looks up. 'Back already? Didn't think you'd return to our little corner of weird.'" ], friend: [ "'Hey.' Raven actually sets her book aside. 'Good timing. I was getting bored with normies all morning.'", "Raven's face softens noticeably. 'There you are. I found this band I think you'd like. Very obscure.'" ], closeFriend: [ "Raven's usual detached expression cracks into genuine warmth. 'Finally. Someone with actual depth. I've been dying to show you something I painted.'", "'Thank the void,' Raven sighs dramatically. 'I was about to lose my mind from small talk. Come here, I need your opinion on something.'" ], bestFriend: [ "Raven abandons her post entirely and comes over. 'Okay, real talk time. I wrote something and you're the only person whose opinion I actually value.'", "'Perfect timing,' Raven says with rare enthusiasm. 'I've been saving this existential crisis specifically to have with you. Coffee after my shift?'" ] }, smallTalk: [ "'Most people sleepwalk through life consuming whatever media they're told to. I prefer things with actual substance.'", "'Art, music, literature - they're the only things that make existence tolerable. Well, that and good coffee.'", "'Working retail would be soul-crushing if I didn't treat every customer interaction like performance art.'" ], complimentReactions: { low: "Raven smirks. 'Trying to charm the goth girl? How original. But... thanks, I guess.'", high: "Raven's cynical mask slips, revealing genuine appreciation. 'You know, you actually get it. That's rare.'" } } })>> /* Crystal Meffin - Beauty Salon Stylist */ <<run $npcs.push(setup.createNPC({ name: "Crystal Meffin", speechStyle: "bubbly", jobs: "Beauty Salon Stylist", gender: "female", chest: "medium", butt: "medium", genitals: "tight vagina", baseStats: {charisma: 35, dexterity: 35, strength: 15, intelligence: 20}, physicalTraits: ["Attractive", "Graceful", "Youthful", "Fashionable"], mentalTraits: ["Friendly", "Outgoing", "Creative", "Bubbly", "Prep"], skills: ["Hair Styling", "Makeup", "Art", "Fashion Design", "Photography"], skinTone: "pale", hairColor: "Blonde", hairLength: "long", age: "Adult" }))>> /* Sophi Boris - Beauty Salon Stylist */ <<run $npcs.push(setup.createNPC({ name: "Sophi Boris", speechStyle: "sarcastic", jobs: "Beauty Salon Stylist", gender: "female", chest: "large", butt: "large", genitals: "vagina", baseStats: {charisma: 35, dexterity: 35, strength: 15, intelligence: 20}, physicalTraits: ["Attractive", "Graceful", "Curvy", "Fashionable"], mentalTraits: ["Confident", "Witty", "Ambitious", "Arrogant", "Diva"], skills: ["Hair Styling", "Makeup", "Dancing", "Singing", "Social Media"], skinTone: "tan", hairColor: "Brown", hairLength: "long", age: "Adult" }))>> /* Naomi Light - Beauty Salon Stylist */ <<run $npcs.push(setup.createNPC({ name: "Naomi Light", speechStyle: "warm", jobs: "Beauty Salon Stylist", gender: "female", chest: "small", butt: "medium", genitals: "tight vagina", baseStats: {charisma: 35, dexterity: 38, strength: 15, intelligence: 22}, physicalTraits: ["Attractive", "Graceful", "Flexible"], mentalTraits: ["Kind", "Patient", "Empathetic", "Calm", "Spiritual"], skills: ["Hair Styling", "Makeup", "Yoga", "Meditation", "Gardening"], skinTone: "dark", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Kevin Oats - Tech Store Clerk */ <<run $npcs.push(setup.createNPC({ name: "Kevin Oats", speechStyle: "nervous", jobs: "Tech Store Clerk", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 20, dexterity: 22, strength: 15, intelligence: 35}, physicalTraits: ["Lean", "Youthful"], mentalTraits: ["Intelligent", "Analytical", "Shy", "Awkward", "Insecure", "Nerd"], skills: ["Coding", "Sales", "Math Skills", "Gaming", "Building PCs"], skinTone: "pale", hairColor: "Brown", hairLength: "short", age: "Adult" }))>> /* Destiny Pumpkin - Adult Store Clerk */ <<run $npcs.push(setup.createNPC({ name: "Destiny Pumpkin", speechStyle: "commanding", jobs: "Adult Store Clerk", gender: "female", chest: "huge", butt: "large", genitals: "vagina", baseStats: {charisma: 30, dexterity: 22, strength: 15, intelligence: 20}, physicalTraits: ["Attractive", "Pierced", "Voluptuous", "Tattooed"], mentalTraits: ["Confident", "Sly", "Creative", "Selfish", "Manipulative"], skills: ["Sales", "Persuasion", "Sexually Skilled", "Art", "Writing"], skinTone: "tan", hairColor: "Red", hairLength: "long", age: "Adult" }))>> /* Alex Passionfruit - Adult Store Clerk */ <<run $npcs.push(setup.createNPC({ name: "Alex Passionfruit", speechStyle: "flirtatious", jobs: "Adult Store Clerk", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 28, dexterity: 22, strength: 18, intelligence: 20}, physicalTraits: ["Attractive", "Lean", "Pierced"], mentalTraits: ["Outgoing", "Witty", "Curious", "Flirty", "Femboy"], skills: ["Sales", "Persuasion", "Sexually Skilled", "Music", "Gaming"], skinTone: "pale", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Hannah Chuckins - Baker */ <<run $npcs.push(setup.createNPC({ name: "Hannah Chuckins", speechStyle: "motherly", jobs: "Baker", gender: "female", chest: "medium", butt: "large", genitals: "tight vagina", baseStats: {charisma: 20, dexterity: 25, strength: 18, intelligence: 20}, physicalTraits: ["Soft", "Curvy", "Freckled"], mentalTraits: ["Kind", "Patient", "Creative", "Shy", "Nurturing"], skills: ["Baking", "Cooking", "Gardening", "Painting", "Singing"], skinTone: "pale", hairColor: "Red", hairLength: "long", age: "Adult" }))>> /* Fen Ris - Fitness Trainer */ <<run $npcs.push(setup.createNPC({ name: "Fen Ris", speechStyle: "chill", jobs: "Fitness Trainer", gender: "female", chest: "huge", butt: "medium", genitals: "vagina", baseStats: {charisma: 45, dexterity: 80, strength: 80, intelligence: 25}, physicalTraits: ["Tall", "Muscular", "Athletic Build", "Sharp Features", "Were-Creature"], mentalTraits: ["Confident", "Calm", "Honest", "Patient", "Disciplined"], skills: ["Athletics", "Heavy Lifting", "Combat", "Yoga", "Teaching"], skinTone: "tan", hairColor: "Black", hairLength: "long", age: "Adult" }))>> <<run Object.assign($npcs[$npcs.length - 1], { uniqueDialogue: { greetings: { stranger: [ "Fen Ris's yellow eyes assess you with the focus of a predator. 'New here? Focus and effort matter more than natural talent. Show me which you have.'", "'You look lost.' Fen Ris's tail swishes once. 'Gym's not a social club. You here to work or waste time?'" ], acquaintance: [ "Fen nods once in acknowledgment. 'Back again. Good. Consistency builds results.'", "'I remember you,' Fen says simply. Her clawed hand gestures to the equipment. 'Ready to put in the work?'" ], friend: [ "Fen's serious expression softens just slightly. 'There you are. I've been watching your progress. You're improving.'", "'Good timing.' Fen's yellow eyes show approval. 'I wanted to show you a new technique. You've earned it.'" ], closeFriend: [ "Fen abandons her current task and approaches. 'Finally, someone who takes training seriously. I have a challenging routine planned if you're interested.'", "Fen's tail swishes with what might be pleasure. 'There you are. I was hoping you'd come by. Your dedication is... refreshing.'" ], bestFriend: [ "Fen's usually stoic face breaks into a genuine smile, revealing her sharp canines. 'Perfect. I need a real training partner, not these half-hearted tourists. You free?'", "'Finally,' Fen sighs with relief. 'Everyone else today has been making excuses. You understand what real commitment means. That's rare.'" ] }, smallTalk: [ "'Training isn't about instant gratification. It's about discipline, routine, and incremental progress every single day.'", "'People want results without effort. They don't understand that transformation requires pain and patience.'", "'The body is capable of far more than most people push it to. Mental barriers break before physical ones.'" ], complimentReactions: { low: "Fen's ear twitches. 'Words are easy. Show me through action instead.'", high: "Fen meets your eyes directly. 'You don't say things you don't mean. I respect that about you.'" } } })>> /* Pheiffer Coms - Police Officer */ <<run $npcs.push(setup.createNPC({ name: "Pheiffer Coms", speechStyle: "blunt", jobs: "Police Officer", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "penis", baseStats: {charisma: 30, dexterity: 28, strength: 50, intelligence: 25}, physicalTraits: ["Fit", "Strong", "Athletic Build", "Broad-shouldered"], mentalTraits: ["Brave", "Honest", "Stubborn", "Loyal", "By-the-Book"], skills: ["Combat", "Driving", "First Aid", "Athletics", "Fishing"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Selkira Onyxia - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Selkira Onyxia", speechStyle: "commanding", jobs: "Brothel Worker", gender: "female", chest: "giant", butt: "giant", genitals: "loose vagina", baseStats: {charisma: 42, dexterity: 30, strength: 18, intelligence: 20}, physicalTraits: ["Curvy", "Attractive", "Fit", "Graceful", "Flexible", "Silky Voice", "Seductive", "Broad-shouldered"], mentalTraits: ["Alluring", "Cold", "Overthinker", "Impulsive", "Insecure", "Ambitious", "Dominant", "Jealous"], skills: ["High Heels Proficient", "Sexually Skilled", "Serving", "Acting", "Languages"], skinTone: "tan", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Janis Besser - Baker */ <<run $npcs.push(setup.createNPC({ name: "Janis Besser", speechStyle: "motherly", jobs: "Baker", gender: "female", chest: "small", butt: "small", genitals: "tight vagina", baseStats: {charisma: 18, dexterity: 28, strength: 15, intelligence: 22}, physicalTraits: ["Petite", "Soft", "Freckled", "Youthful", "Quick", "Warm Tone"], mentalTraits: ["Kind", "Patient", "Creative", "Hardworking", "Shy", "Nurturing"], skills: ["Baking", "Cooking", "Gardening", "Customer Service", "Painting"], skinTone: "pale", hairColor: "Red", hairLength: "short", age: "Adult" }))>> /* Dennis Fungi - Dancing Instructor */ <<run $npcs.push(setup.createNPC({ name: "Dennis Fungi", speechStyle: "excitable", jobs: "Dancing Instructor", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", baseStats: {charisma: 50, dexterity: 55, strength: 48, intelligence: 25}, physicalTraits: ["Fit", "Athletic Build", "Graceful", "Flexible", "Attractive", "Smooth Voice"], mentalTraits: ["Confident", "Outgoing", "Creative", "Energetic", "Disciplined", "Charming"], skills: ["Dancing", "Teaching", "Athletics", "Music", "Yoga"], skinTone: "tan", hairColor: "Brown", hairLength: "short", age: "Adult" }))>> /* Yvela Mushroom - Dancing Instructor */ <<run $npcs.push(setup.createNPC({ name: "Yvela Mushroom", speechStyle: "commanding", jobs: "Dancing Instructor", gender: "female", chest: "huge", butt: "huge", genitals: "vagina", baseStats: {charisma: 52, dexterity: 58, strength: 50, intelligence: 28}, physicalTraits: ["Fit", "Athletic Build", "Graceful", "Flexible", "Attractive", "Melodic Voice"], mentalTraits: ["Confident", "Ambitious", "Creative", "Energetic", "Disciplined", "Competitive"], skills: ["Dancing", "Teaching", "Athletics", "Yoga", "Martial Arts"], skinTone: "dark", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Banana Banana - Barista */ <<run $npcs.push(setup.createNPC({ name: "Banana Banana", speechStyle: "bubbly", jobs: "Barista", gender: "female", chest: "giant", butt: "giant", genitals: "tight vagina", baseStats: {charisma: 22, dexterity: 25, strength: 15, intelligence: 18}, physicalTraits: ["Youthful", "Quick", "Energetic", "Friendly Tone", "Fashionable"], mentalTraits: ["Friendly", "Optimistic", "Energetic", "Creative", "Talkative", "Bubbly"], skills: ["Customer Service", "Cooking", "Art", "Social Media", "Music"], skinTone: "tan", hairColor: "Blonde", hairLength: "long", age: "Adult" }))>> /* Xenis Aku - Bus Driver */ <<run $npcs.push(setup.createNPC({ name: "Xenis Aku", speechStyle: "chill", jobs: "Bus Driver", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 18, dexterity: 25, strength: 22, intelligence: 20}, physicalTraits: ["Sturdy", "Calm Voice", "Mature", "Relaxed"], mentalTraits: ["Calm", "Patient", "Honest", "Reliable", "Introverted", "Thoughtful"], skills: ["Driving", "Customer Service", "First Aid", "Navigation", "Mechanical Repair"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Mature Adult" }))>> /* Xanithar Galdenentri - Unemployed */ <<run $npcs.push(setup.createNPC({ name: "Xanithar Galdenentri", speechStyle: "deadpan", jobs: "Unemployed", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 350, dexterity: 300, strength: 310, intelligence: 450}, physicalTraits: ["Mature", "Underweight", "Mumbly Voice", "Scarred"], mentalTraits: ["Crazy", "Eccentric", "Intelligent", "Paranoid", "Erratic", "Obsessive", "Bookworm"], skills: ["Magic Theory", "Languages", "Writing", "Teaching", "Medicine"], skinTone: "pale", hairColor: "Platinum Blonde", hairLength: "long", age: "Mature Adult" }))>> /* Trixie Rye - Cocktail Waitress */ <<run $npcs.push(setup.createNPC({ name: "Trixie Rye", speechStyle: "flirtatious", jobs: "Cocktail Waitress", gender: "female", chest: "huge", butt: "huge", genitals: "vagina", baseStats: {charisma: 42, dexterity: 30, strength: 18, intelligence: 20}, physicalTraits: ["Attractive", "Voluptuous", "Graceful", "Smooth Skin", "Charming Tone"], mentalTraits: ["Confident", "Flirty", "Witty", "Ambitious", "Sly", "Outgoing"], skills: ["Serving", "High Heels Proficient", "Customer Service", "Dancing", "Persuasion"], skinTone: "tan", hairColor: "Brown", hairLength: "long", age: "Adult" }))>> /* Revna McKraken - Strange book shop owner */ /* Custom Information: A hypnotic and cunning woman who pulls you in so naturally you don't even notice her pointy teeth. Her words and methods are strange and she seems quite cagey about her past and personal life. You get the feeling she won't trade you anything of herself, but she might appreciate a donation. (Just a reminder about the "totally not a vampire" trait. Since the desires section doesn't work, here is the working list. Traits she wants for her vanity: Alluring, witty, high heel proficient, modeling, dancing, smooth skin, sharp features, soft, flexible, fashionable: Traits she wants for her efficiency: efficient, quick learner, shrewd, management, athletics, tech savvy, coding; She should never trade away anything! She's a vampire, she takes and extracts by nature.) */ <<run $npcs.push(setup.createNPC({ name: "Revna McKraken", speechStyle: "gothic", jobs: "Mysterious Book Shop owner", gender: "female", chest: "medium", butt: "medium", genitals: "vagina", baseStats: {charisma: 99, dexterity: 99, strength: 99, intelligence: 99}, physicalTraits: ["Pale Skin", "Attractive", "Graceful", "Voluptuous", "Quick Reflexes", "Definitely not a Vampire"], mentalTraits: ["Charming", "Diplomatic", "Bookworm", "Seductive", "Intelligent", "Moody", "Sly", "Confident", "Creative", "Patient", "Perceptive", "Deceitful", "Goth"], voiceTraits: ["Silky Voice"], skills: ["Sexually Skilled", "Stealth", "Persuasion", "Acting", "Languages", "Product Knowledge", "Martial Arts", "Gardening", "Writing", "Medicine", "Combat", "Occult Expert"], skinTone: "pale", hairColor: "Black", hairLength: "long", age: "Adult" }))>> /* Quesha Epo - Static-tier NPC, Hidden Lagoon resident / Beach Dive Shop owner */ <<set _qNpc = setup.createNPC({ name: "Quesha Epo", speechStyle: "soft", jobs: "Dive Shop Owner", gender: "female", chest: "huge", butt: "huge", genitals: "vagina", baseStats: {strength: 90, dexterity: 60, charisma: 170, intelligence: 90}, physicalTraits: ["Blue Hair", "Tall", "Voluptuous", "Smooth Skin", "Graceful", "Athletic Build", "High Stamina"], mentalTraits: ["Kind", "Patient", "Shy", "Perceptive", "Loyal", "Creative", "Curious", "Bookworm"], voiceTraits: ["Silky Voice"], skills: ["Swimming", "Fishing", "Languages", "Cooking", "Persuasion", "Sexual Stamina Expert"], skinTone: "pale", hairColor: "Blue", hairLength: "long", age: "Adult", traitTradingLocked: true })>> <<run setup.queshaDialogue && (_qNpc.uniqueDialogue = setup.queshaDialogue)>> <<run $npcs.push(_qNpc)>> /* Flona Vulri - Static-tier NPC, Tundra of Aeternus resident (Snow Fox, motherly) */ <<run $npcs.push(setup.createNPC({ name: "Flona Vulri", speechStyle: "soft", jobs: "???", gender: "female", chest: "huge", butt: "large", genitals: "vagina", baseStats: {strength: 70, dexterity: 60, charisma: 160, intelligence: 150}, physicalTraits: ["Snow Fox", "Tall", "Voluptuous", "Smooth Skin", "Graceful", "High Stamina"], mentalTraits: ["Kind", "Patient", "Loyal", "Perceptive"], voiceTraits: ["Silky Voice"], skills: ["Cooking", "Languages", "Persuasion"], skinTone: "pale", hairColor: "Platinum Blonde", hairLength: "long", age: "Mature Adult", traitTradingLocked: true }))>> /* Clair - Dream entity, Dream Dimension resident. Player copies this sheet exactly via the Twinning spell, so these traits and stats ARE the reward. */ <<run $npcs.push(setup.createNPC({ name: "Clair", speechStyle: "soft", jobs: "???", gender: "female", chest: "large", butt: "large", genitals: "vagina", baseStats: {strength: 200, dexterity: 350, charisma: 400, intelligence: 400}, physicalTraits: ["Tall", "Voluptuous", "Smooth Skin", "Graceful"], mentalTraits: ["Calm", "Wise", "Curious", "Playful", "Perceptive"], voiceTraits: ["Silky Voice"], skills: ["Occult Expert", "Languages", "Persuasion"], skinTone: "pale", hairColor: "Platinum Blonde", hairLength: "long", age: "Adult", traitTradingLocked: true }))>> /* Butt Johnson - Streamer (Apartment Neighbor) */ <<run $npcs.push(setup.createNPC({ name: "Butt Johnson", speechStyle: "nervous", jobs: "Streamer", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis", baseStats: {charisma: 18, dexterity: 15, strength: 12, intelligence: 35}, physicalTraits: ["Short Hair", "Overweight", "Plain", "Blemished", "Unkempt"], mentalTraits: ["Nerd", "Lazy", "Introverted", "Awkward", "Disorganized", "Shy", "Forgetful", "Obsessive"], skills: ["Gaming", "Coding", "Tech-Savvy", "Social Media", "Forklift Certified"], skinTone: "pale", hairColor: "Brown", hairLength: "short", age: "Adult" }))>> /* Purple Wood - Streamer */ <<set _violetTemp = setup.createNPC({ name: "Purple Wood", speechStyle: "gothic", jobs: "Streamer", gender: "female", chest: "small", butt: "huge", genitals: "vagina", baseStats: {charisma: 25, dexterity: 20, strength: 15, intelligence: 30}, physicalTraits: ["Attractive", "Pierced", "Tattooed", "Graceful", "Pale Skin"], mentalTraits: ["Creative", "Introverted", "Moody", "Goth", "Cynical"], skills: ["Sales", "Art", "Music", "Painting", "Writing"], skinTone: "pale", hairColor: "Black", hairLength: "long", age: "Adult" })>> /* Luna Snow - Musician */ <<run $npcs.push(setup.createNPC({ name: "Luna Snow", speechStyle: "warm", jobs: "Musician", gender: "female", chest: "huge", butt: "huge", genitals: "big penis", baseStats: {charisma: 99, dexterity: 10, strength: 10, intelligence: 10}, physicalTraits: ["Curvy", "Soft", "Smooth Skin", "Youthful", "Attractive", "Fit", "Graceful", "Freckled", "Short"], mentalTraits: ["Charming", "Funny", "Bookworm", "Warm", "Blunt", "Creative", "Wise", "Intelligent", "Stubborn", "Calm", "Artistic", "Musky"], skills: ["Guitar", "Photography", "Art", "Painting", "Music", "Acting", "Martial Arts"], skinTone: "pale", hairColor: "Brown", hairLength: "long", age: "Adult" }))>> /* Boris Shorthead - Patrol Officer */ <<run $npcs.push(setup.createNPC({ name: "Boris Shorthead", speechStyle: "blunt", jobs: "Patrol Officer", gender: "male", chest: "flat masculine", butt: "medium", genitals: "small penis", baseStats: {charisma: 15, dexterity: 20, strength: 50, intelligence: 20}, physicalTraits: ["Short", "Muscular", "Strong", "Broad-shouldered"], mentalTraits: ["Disciplined", "Brave", "Blunt", "Loyal"], skills: ["Combat", "Driving", "First Aid", "Public Speaking"], skinTone: "pale", hairColor: "Brown", hairLength: "short", age: "Adult" }))>> /* Mareregererrer Mayonnaise - Patrol Officer */ <<run $npcs.push(setup.createNPC({ name: "Mareregererrer Mayonnaise", speechStyle: "blunt", jobs: "Patrol Officer", gender: "female", chest: "medium", butt: "medium", genitals: "vagina", baseStats: {charisma: 25, dexterity: 25, strength: 45, intelligence: 25}, physicalTraits: ["Athletic Build", "Tall", "Fit", "Sharp Features"], mentalTraits: ["Confident", "Determined", "Analytical", "Direct"], skills: ["Combat", "Driving", "Persuasion", "First Aid"], skinTone: "tan", hairColor: "Blonde", hairLength: "medium", age: "Adult" }))>> /* Poggies Name420 - Patrol Officer (Femboy) */ <<run $npcs.push(setup.createNPC({ name: "Poggies Name420", speechStyle: "flirtatious", jobs: "Patrol Officer", gender: "male", chest: "flat", butt: "giant", genitals: "penis", baseStats: {charisma: 30, dexterity: 30, strength: 45, intelligence: 20}, physicalTraits: ["Femboy", "Petite", "Graceful", "Smooth Skin"], mentalTraits: ["Unpredictable", "Energetic", "Flirty", "Confident", "Femboy"], skills: ["Combat", "Driving", "Dancing", "High Heels Proficient"], skinTone: "pale", hairColor: "Blonde", hairLength: "long", age: "Young Adult" }))>> /* Sunny Flipflop - Sheriff */ <<run $npcs.push(setup.createNPC({ name: "Sunny Flipflop", speechStyle: "commanding", jobs: "Sheriff", gender: "female", chest: "medium", butt: "large", genitals: "big penis", baseStats: {charisma: 45, dexterity: 35, strength: 50, intelligence: 35}, physicalTraits: ["Muscular", "Strong", "Fit", "Athletic Build", "Tall"], mentalTraits: ["Confident", "Disciplined", "Brave", "Honest", "Loyal", "Ambitious", "Hardworking", "Organized"], skills: ["Combat", "Legal Knowledge", "Management", "Public Speaking", "First Aid", "Driving", "Persuasion", "Leadership"], skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* Bongo Bongo - Police Station Receptionist */ <<run $npcs.push(setup.createNPC({ name: "Bongo Bongo", speechStyle: "warm", jobs: "Police Station Receptionist", gender: "female", chest: "medium", butt: "medium", genitals: "vagina", baseStats: {charisma: 30, dexterity: 25, strength: 25, intelligence: 20}, physicalTraits: ["Pale Skin", "Long Hair", "Fit", "Quick Reflexes", "Sharp Features"], mentalTraits: ["Polite", "Organized", "Friendly", "Brave", "Disciplined", "Patient"], skills: ["Customer Service", "Combat", "First Aid", "Inventory Management", "Product Knowledge"], skinTone: "pale", hairColor: "Blonde", hairLength: "long", age: "Adult" }))>> /* Roisin Sullivan - Unemployed Drifter with Connections */ <<run $npcs.push(setup.createNPC({ name: "Roisin Sullivan", speechStyle: "aggressive", jobs: "Fuck Employment", gender: "female", chest: "huge", butt: "large", genitals: "tight vagina", baseStats: {charisma: 37, dexterity: 68, strength: 98, intelligence: 20}, physicalTraits: ["Athletic Build", "Attractive", "Fast", "Fit", "Flexible", "Perceptive", "Quick Reflexes", "Relaxed", "Smooth Skin", "Strong", "Sturdy", "Tall", "Youthful"], mentalTraits: ["Alluring", "Ambitious", "Blunt", "Cold", "Competitive", "Confident", "Delinquent", "Determined", "Disorganized", "Dominant", "Efficient", "Extroverted", "Forgetful", "Impatient", "Impulsive", "Insecure", "Lucky", "Obsessive", "Reckless", "Risk Taker", "Sensitive", "Steadfast", "Stubborn"], skills: ["Athletics", "Baking", "Combat", "Driving", "Forklift Certified", "Gardening", "Heavy Lifting", "Swimmer"], voiceTraits: ["Gaelic Accent"], skinTone: "pale", hairColor: "Red", hairLength: "long", age: "Adult" }))>> /* Cid Cranberry - Barista */ <<run $npcs.push(setup.createNPC({ name: "Cid Cranberry", speechStyle: "warm", jobs: "Barista", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "penis", baseStats: {charisma: 30, dexterity: 70, strength: 50, intelligence: 30}, physicalTraits: ["Expressive Voice", "Mature", "Attractive", "Clumsy", "Fit", "Freckled"], mentalTraits: ["Kind", "Optimistic", "Naive", "Arrogant", "Ambitious", "Brave", "Blunt", "Disciplined", "Empathetic", "Reliable", "Bad Luck", "Caffeine Addict", "Honest", "Slow Learner", "Supportive", "High Stamina", "Submissive"], skills: ["Combat", "Navigation", "Heavy Lifting", "Maid", "Roleplay Expert", "Acting", "Art"], skinTone: "pale", hairColor: "Black", hairLength: "short", age: "Adult" }))>> /* ============ PUFFY'S MAID CAFE STAFF ============ */ /* Mochi - Werecat Maid (petite, cute, pink hair, erotic but innocent) */ <<run $npcs.push(setup.createNPC({ name: "Mochi", speechStyle: "cheerful", jobs: "Maid", gender: "female", chest: "small", butt: "small", genitals: "tight vagina", baseStats: {charisma: 40, dexterity: 35, strength: 10, intelligence: 25}, physicalTraits: ["Petite", "Youthful", "Cute", "Smooth Skin", "Werecat"], mentalTraits: ["Kind", "Shy", "Energetic", "Submissive", "Mischievous"], skills: ["Dancing", "Cooking", "Maid", "Acrobatics"], skinTone: "pale", hairColor: "Pink", hairLength: "long", age: "Adult" }))>> /* Ren - Kitsune (Kitsune) Maid (mature, seductive, purple hair, openly horny) */ <<run $npcs.push(setup.createNPC({ name: "Ren", speechStyle: "flirtatious", jobs: "Maid", gender: "female", chest: "huge", butt: "huge", genitals: "tight vagina", baseStats: {charisma: 60, dexterity: 40, strength: 20, intelligence: 45}, physicalTraits: ["Attractive", "Graceful", "Tall", "Smooth Skin", "Kitsune"], mentalTraits: ["Confident", "Seductive", "Calm", "Flirty", "Insatiable", "Cunning"], skills: ["Sexually Skilled", "Cooking", "Maid", "Acting", "Public Speaking"], skinTone: "pale", hairColor: "Purple", hairLength: "long", age: "Mature Adult" }))>> /* Clover - Hucow Maid (incredibly curvy, giant breasts/ass, black spotted white hair, openly horny) */ <<run $npcs.push(setup.createNPC({ name: "Clover", speechStyle: "flirtatious", jobs: "Maid", gender: "female", chest: "giant", butt: "giant", genitals: "tight vagina", baseStats: {charisma: 50, dexterity: 20, strength: 30, intelligence: 30}, physicalTraits: ["Attractive", "Voluptuous", "Curvy", "Smooth Skin", "Hucow", "Lactating", "Maternal"], mentalTraits: ["Kind", "Confident", "Flirty", "Seductive", "Insatiable", "Shameless"], skills: ["Sexually Skilled", "Cooking", "Maid", "Heavy Lifting"], skinTone: "pale", hairColor: "Black Spotted White", hairLength: "long", age: "Adult" }))>> <<run $npcs.push(_violetTemp)>> /* Activate Bimbo state on Violet at game start */ <<run setup.activateBimboTrait(_violetTemp)>> /* Initialize permanent IDs for trading system */ <<for _npc range $npcs>> <<if !_npc.permanentId>> <<set _npc.permanentId = _npc.name>> <</if>> <</for>> <</silently>>s
<<nobr>> <!-- Track the original location if not already in NPC flow --> <<if !$lastLocation || !["NPCInteraction", "NPCTalk", "NPCTalkResponse", "NPCSocialSelect", "NPCGiftResponse", "TradeInterface", "TradeSelectItems", "TradeResult", "RomanceInitiate", "RomanceKiss", "RomanceMakeOut", "RomanceBuildUp", "RomanceIntimacy", "RomanceClimax", "RomanceAftermath", "HomeInviteSelect", "HomeIntimateSelect", "HomeIntimateScene"].includes($lastLocation)>> <<set $preNPCLocation = $lastLocation>> <</if>> <!-- Clear any stale home-visit return flag. Reaching NPCInteraction means this is a world conversation, which must return to the world location on exit, not the player home. The home-visit Chat button jumps straight to NPCTalk and bypasses this, so a genuine home visit keeps its flag. --> <<set $homeVisitReturn = false>> <<set _npc = $tradingWithNPC>> <<if !_npc>> <<set _exitTo = $preNPCLocation || $lastLocation || "Downtown">> <<goto _exitTo>> <<else>> <<if $compactNPCMenu>> <!-- ===== COMPACT NPC MENU ===== --> <<set _displayNPCPhysicalTraits = (_npc.physicalTraits || []).filter(function(t) { return t !== "Short Hair" && t !== "Long Hair"; })>> <<if _npc.name === "Roisin Sullivan">> <<set _roisinFriendship = ($relationships && $relationships[_npc.name]) ? $relationships[_npc.name].level : 0>> <<if _roisinFriendship >= 4>><<set _traitStoragePrice = 100000>> <<elseif _roisinFriendship >= 3>><<set _traitStoragePrice = 500000>> <<elseif _roisinFriendship >= 2>><<set _traitStoragePrice = 1000000>> <<elseif _roisinFriendship >= 1>><<set _traitStoragePrice = 5000000>> <<else>><<set _traitStoragePrice = 10000000>><</if>> <<set _canAffordTraitStorage = $money >= _traitStoragePrice>> <</if>> <div style="background: #0a0a1e; min-height: 100vh; padding: 20px;"> <!-- TOP BAR: name + actions --> <div style="background: rgba(15, 15, 35, 0.98); border: 2px solid rgba(125, 211, 252, 0.4); border-radius: 10px; padding: 14px 18px; margin-bottom: 18px; box-shadow: 0 4px 20px rgba(0,0,0,0.6); backdrop-filter: blur(10px); display: flex; align-items: center; gap: 18px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 180px;"> <div style="font-size: 22px; font-weight: bold; color: #fff;">_npc.name</div> <div style="font-size: 13px; color: #7dd3fc; margin-top: 2px;"> <<if _npc.jobs && _npc.jobs.length > 0>><<print _npc.jobs.join(", ")>><<else>>Unemployed<</if>> </div> </div> <div class="trade-ui-actions" style="margin: 0; gap: 10px;"> <<if _npc.name === "Xanithar Galdenentri" || _npc.name === "Xantria Galdenentri" || _npc.originalName === "Bun Bun" || _npc.name === "Quesha Epo" || _npc.originalName === "Quesha Epo" || _npc.name === "Flona Vulri" || _npc.originalName === "Flona Vulri" || _npc.name === "Clair" || _npc.originalName === "Clair">> <<link "<span class='trade-ui-btn trade-ui-btn-trade' style='padding: 8px 18px; font-size: 14px;'>💬 Talk</span>">> <<set $tradingWithNPC = _npc>> <<goto "NPCTalk">> <</link>> <<elseif _npc.name === "Roisin Sullivan">> <<link "<span class='trade-ui-btn trade-ui-btn-trade' style='padding: 8px 18px; font-size: 14px;'>💬 Talk</span>">> <<set $tradingWithNPC = _npc>> <<goto "NPCTalk">> <</link>> <<link "<span class='trade-ui-btn trade-ui-btn-cancel' style='padding: 8px 18px; font-size: 14px;'>💱 Trade</span>">> <<set $tradingWithNPC = _npc>> <<goto "TradeInterface">> <</link>> <<link "<span class='trade-ui-btn' style='padding: 8px 18px; font-size: 14px; background: rgba(40, 167, 69, 0.18); border-color: #28a745; color: #51cf66;'>💰 Sell Traits</span>">> <<set $tradingWithNPC = _npc>> <<goto "SellTraits">> <</link>> <<if $traitStorageUnlocked>> <span class="trade-ui-btn" style="padding: 8px 18px; font-size: 14px; background: rgba(80, 80, 80, 0.3); border-color: #555; color: #888; cursor: default;">🧬 Trait Storage (Owned)</span> <<elseif _roisinFriendship < 0>> <span class="trade-ui-btn" style="padding: 8px 18px; font-size: 14px; background: rgba(80, 80, 80, 0.3); border-color: #555; color: #888; cursor: not-allowed;">🧬 Trait Storage (Locked)</span> <<elseif !_canAffordTraitStorage>> <span class="trade-ui-btn" style="padding: 8px 18px; font-size: 14px; background: rgba(80, 80, 80, 0.3); border-color: #555; color: #888; cursor: not-allowed;">🧬 Trait Storage ($<<print _traitStoragePrice.toLocaleString()>>)</span> <<else>> <<link "<span class='trade-ui-btn' style='padding: 8px 18px; font-size: 14px; background: rgba(224, 64, 251, 0.2); border-color: #e040fb; color: #e040fb;'>🧬 Trait Storage ($<<print _traitStoragePrice.toLocaleString()>>)</span>">> <<set $money -= _traitStoragePrice>> <<set $traitStorageUnlocked = true>> <<set $traitStorage = []>> <<goto "RoisinTraitStoragePurchased">> <</link>> <</if>> <<else>> <<link "<span class='trade-ui-btn trade-ui-btn-trade' style='padding: 8px 18px; font-size: 14px;'>💬 Talk</span>">> <<set $tradingWithNPC = _npc>> <<goto "NPCTalk">> <</link>> <<link "<span class='trade-ui-btn trade-ui-btn-cancel' style='padding: 8px 18px; font-size: 14px;'>💱 Trade</span>">> <<set $tradingWithNPC = _npc>> <<goto "TradeInterface">> <</link>> <</if>> <<if setup.slime.isPlayerSlimeBodied() && setup.slimePossession.canPossess(_npc).ok>><<link "<span class='trade-ui-btn trade-ui-btn-trade' style='padding: 8px 18px; font-size: 14px;'>🫧 Slither & Possess</span>">><<set $slimeTargetName = (_npc.originalName || _npc.name)>><<goto "SlimePossessAttempt">><</link>><</if>> <<link "<span class='trade-ui-btn trade-ui-btn-clear' style='padding: 8px 18px; font-size: 14px;'>← Leave</span>">> <<set $tradingWithNPC = null>> <<set _exitTo = $preNPCLocation || $lastLocation || "Downtown">> <<goto _exitTo>> <</link>> </div> </div> <!-- TWO-COLUMN BODY --> <div class="trade-ui-wrapper" style="max-width: 1100px;"> <div class="trade-ui-columns"> <!-- LEFT: Appearance --> <div class="trade-ui-column trade-ui-col-npc"> <div class="trade-ui-column-header">👤 Appearance</div> <<if $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <<set _npcImage = setup.getNPCImage(_npc.name)>> <<if _npcImage>> <div style="text-align: center; margin-bottom: 12px;"> <img @src="_npcImage" style="max-width: 100%; max-height: 320px; border-radius: 8px; border: 2px solid rgba(192, 132, 252, 0.5); box-shadow: 0 0 15px rgba(192, 132, 252, 0.25);" onerror="this.style.display='none';"> </div> <</if>> <</if>> <<set _npcHairStyle = _npc.appearance.hairStyle === "messy" ? "Messy " : "">> <<set _npcHairLength = _npc.appearance.hairLength ? _npc.appearance.hairLength.toUpperFirst() : "Short">> <div style="font-size: 13px; color: #ccc; line-height: 1.7; padding: 4px 8px;"> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Hair:</strong> <<print _npcHairStyle + _npcHairLength>> <<print _npc.appearance.hairColor>></p> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Skin Tone:</strong> <<print _npc.appearance.skinTone.toUpperFirst()>></p> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Chest:</strong> <<print _npc.bodyParts.chest.toUpperFirst()>></p> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Butt:</strong> <<print _npc.bodyParts.butt.toUpperFirst()>></p> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Genitals:</strong> <<print (_npc.bodyParts.genitals || "Unknown").toUpperFirst()>></p> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Gender:</strong> <<print _npc.bodyParts.gender.toUpperFirst()>></p> <p style="margin: 6px 0;"><strong style="color: #c084fc;">Age:</strong> <<print _npc.appearance.age || "Adult">></p> </div> </div> <!-- RIGHT: Stats and Traits --> <div class="trade-ui-column trade-ui-col-player"> <div class="trade-ui-column-header">📊 Stats & Traits</div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 12px; font-size: 13px;"> <div style="background: rgba(20,20,40,0.7); padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);"> <strong style="color: #aaa;">Cha:</strong> <span style="color: #7dd3fc; font-weight: bold;">_npc.stats.charisma</span> </div> <div style="background: rgba(20,20,40,0.7); padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);"> <strong style="color: #aaa;">Dex:</strong> <span style="color: #7dd3fc; font-weight: bold;">_npc.stats.dexterity</span> </div> <div style="background: rgba(20,20,40,0.7); padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);"> <strong style="color: #aaa;">Str:</strong> <span style="color: #7dd3fc; font-weight: bold;">_npc.stats.strength</span> </div> <div style="background: rgba(20,20,40,0.7); padding: 8px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);"> <strong style="color: #aaa;">Int:</strong> <span style="color: #7dd3fc; font-weight: bold;">_npc.stats.intelligence</span> </div> </div> <<if _displayNPCPhysicalTraits.length > 0>> <div class="trade-ui-category trade-ui-cat-physical"> <div class="trade-ui-category-title" style="cursor: default;">💪 Physical Traits <span style="font-size: 11px; opacity: 0.7;"><<print _displayNPCPhysicalTraits.length>></span></div> <div class="trade-ui-category-body" style="line-height: 2;"> <<for _trait range _displayNPCPhysicalTraits>> <span style="background: rgba(81, 207, 102, 0.1); color: #51cf66; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid rgba(81, 207, 102, 0.4); white-space: nowrap; display: inline-block; margin: 3px 3px 3px 0;">_trait</span> <</for>> </div> </div> <</if>> <<if _npc.mentalTraits && _npc.mentalTraits.length > 0>> <div class="trade-ui-category trade-ui-cat-mental"> <div class="trade-ui-category-title" style="cursor: default;">🧠 Mental Traits <span style="font-size: 11px; opacity: 0.7;"><<print _npc.mentalTraits.length>></span></div> <div class="trade-ui-category-body" style="line-height: 2;"> <<for _trait range _npc.mentalTraits>> <span style="background: rgba(192, 132, 252, 0.1); color: #c084fc; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid rgba(192, 132, 252, 0.4); white-space: nowrap; display: inline-block; margin: 3px 3px 3px 0;">_trait</span> <</for>> </div> </div> <</if>> <<if _npc.skills && _npc.skills.length > 0>> <div class="trade-ui-category trade-ui-cat-skills"> <div class="trade-ui-category-title" style="cursor: default;">🎯 Skills <span style="font-size: 11px; opacity: 0.7;"><<print _npc.skills.length>></span></div> <div class="trade-ui-category-body" style="line-height: 2;"> <<for _skill range _npc.skills>> <span style="background: rgba(255, 212, 59, 0.1); color: #ffd43b; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid rgba(255, 212, 59, 0.4); white-space: nowrap; display: inline-block; margin: 3px 3px 3px 0;">_skill</span> <</for>> </div> </div> <</if>> </div> </div> </div> <!-- Cafe Recruit (secondary) --> <<if $cafeOwnership && $cafeOwnership.owned && setup.cafe.recruitableNPCs[_npc.name]>> <<set _recruitStatus = setup.cafe.getRecruitStatus(_npc.name)>> <div style="margin-top: 18px; max-width: 1100px; margin-left: auto; margin-right: auto;"> <<if _recruitStatus.can>> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 13px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 15px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid rgba(46, 204, 113, 0.5);'>🏠 Recruit for <<= $cafeOwnership.cafeName>></div>">> <<set $cafeRecruitTarget = _npc.name>> <<goto "CafeRecruit">> <</link>> <<else>> <div style="background: #2a2a2a; color: #888; padding: 13px; border-radius: 10px; text-align: center; font-size: 13px; border: 2px solid #444;">🏠 Recruit for <<= $cafeOwnership.cafeName>>: <<= _recruitStatus.reason>></div> <</if>> </div> <</if>> <!-- Life Swap (Soul-trait gated) --> <<set _hasSoulTrait = ($skills && $skills.includes("Soul")) || ($physicalTraits && $physicalTraits.includes("Soul")) || ($mentalTraits && $mentalTraits.includes("Soul"))>> <<if _hasSoulTrait || $debugLifeSwapBypass>> <<set _lifeSwapProtectedNPCs = ["Xanithar Galdenentri", "Revna McKraken", "Roisin Sullivan", "Luna Snow", "Fen Ris", "Quesha Epo", "Flona Vulri", "Mochi", "Ren", "Clover", "Bun Bun", "Clair"]>> <<set _npcNameForCheck = _npc.originalName || _npc.name>> <<if !_lifeSwapProtectedNPCs.includes(_npcNameForCheck)>> <<set _hasSunfishTrait = ($skills && $skills.includes("Sunfish")) || ($physicalTraits && $physicalTraits.includes("Sunfish")) || ($mentalTraits && $mentalTraits.includes("Sunfish"))>> <<set _hasMinStats = $stats.strength >= 50 && $stats.intelligence >= 50 && $stats.charisma >= 50 && $stats.dexterity >= 50>> <<set _isOriginalBody = $lifeSwapOriginalBodyNPC && (_npc.name === $lifeSwapOriginalBodyNPC || _npc.originalName === $lifeSwapOriginalBodyNPC)>> <<set _canLifeSwap = $debugLifeSwapBypass || _isOriginalBody || (_hasSunfishTrait && _hasMinStats)>> <div style="margin-top: 12px; max-width: 1100px; margin-left: auto; margin-right: auto;"> <<if _canLifeSwap>> <<link "<div style='background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 13px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 15px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #e040fb;'>🔮 Life Swap</div>">> <<set $lifeSwapNPC = _npc>> <<set $lifeSwapIsOriginalBody = _isOriginalBody>> <<goto "LifeSwapConfirm">> <</link>> <<else>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); color: #888; padding: 13px; border-radius: 10px; text-align: center; font-size: 14px; border: 2px solid #555;"> 🔮 Life Swap: <<if !_hasSunfishTrait && !_hasMinStats>>Requires Sunfish trait and 50+ in all stats <<elseif !_hasSunfishTrait>>Requires Sunfish trait <<else>>Requires 50+ in all base stats<</if>> </div> <</if>> </div> <</if>> <</if>> </div> <!-- ===== END COMPACT NPC MENU ===== --> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #667eea;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">_npc.name</h1> <p style="color: white; margin: 0; font-size: 18px; text-align: center;"> <<if _npc.jobs && _npc.jobs.length > 0>> <<print _npc.jobs.join(", ")>> <<else>> Unemployed <</if>> </p> </div> <!-- NPC Stats --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #17a2b8; padding-bottom: 10px;">📊 Stats</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; font-size: 16px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Charisma:</strong> <span style="color: #17a2b8; font-weight: bold;">_npc.stats.charisma</span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Dexterity:</strong> <span style="color: #17a2b8; font-weight: bold;">_npc.stats.dexterity</span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Strength:</strong> <span style="color: #17a2b8; font-weight: bold;">_npc.stats.strength</span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Intelligence:</strong> <span style="color: #17a2b8; font-weight: bold;">_npc.stats.intelligence</span> </div> </div> </div> <!-- NPC Appearance --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #9b59b6; padding-bottom: 10px;">👤 Appearance</h3> <div style="display: flex; gap: 20px; align-items: flex-start;"> <!-- Appearance Details --> <div style="flex: 1; font-size: 16px; color: #ccc; line-height: 1.8;"> <<set _npcHairStyle = _npc.appearance.hairStyle === "messy" ? "Messy " : "">> <<set _npcHairLength = _npc.appearance.hairLength ? _npc.appearance.hairLength.toUpperFirst() : "Short">> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Hair:</strong> <<print _npcHairStyle + _npcHairLength>> <<print _npc.appearance.hairColor>></p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Skin Tone:</strong> <<print _npc.appearance.skinTone.toUpperFirst()>></p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Chest:</strong> <<print _npc.bodyParts.chest.toUpperFirst()>></p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Butt:</strong> <<print _npc.bodyParts.butt.toUpperFirst()>></p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Genitals:</strong> <<print (_npc.bodyParts.genitals || "Unknown").toUpperFirst()>></p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Gender:</strong> <<print _npc.bodyParts.gender.toUpperFirst()>></p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Age:</strong> <<print _npc.appearance.age || "Adult">></p> </div> <!-- NPC Image --> <<if $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <<set _npcImage = setup.getNPCImage(_npc.name)>> <<if _npcImage>> <div style="flex-shrink: 0;"> <img @src="_npcImage" style="max-width: 250px; max-height: 350px; border-radius: 8px; border: 2px solid #9b59b6; box-shadow: 0 0 15px rgba(155,89,182,0.4);" onerror="this.style.display='none';"> </div> <</if>> <</if>> </div> </div> <!-- NPC Traits --> <<if _npc.physicalTraits && _npc.physicalTraits.length > 0>> <<set _displayNPCPhysicalTraits = _npc.physicalTraits.filter(function(trait) { return trait !== "Short Hair" && trait !== "Long Hair"; })>> <<if _displayNPCPhysicalTraits.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #51cf66; padding-bottom: 10px;">💪 Physical Traits</h3> <div style="line-height: 2.5;"> <<for _trait range _displayNPCPhysicalTraits>> <span style="background: #1a1a1a; color: #51cf66; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #51cf66; font-weight: 500; white-space: nowrap; display: inline-block; margin: 5px 5px 5px 0;">_trait</span> <</for>> </div> </div> <</if>> <</if>> <<if _npc.mentalTraits && _npc.mentalTraits.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #9b59b6; padding-bottom: 10px;">🧠 Mental Traits</h3> <div style="line-height: 2.5;"> <<for _trait range _npc.mentalTraits>> <span style="background: #1a1a1a; color: #9b59b6; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #9b59b6; font-weight: 500; white-space: nowrap; display: inline-block; margin: 5px 5px 5px 0;">_trait</span> <</for>> </div> </div> <</if>> <<if _npc.skills && _npc.skills.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #ffc107; padding-bottom: 10px;">🎯 Skills</h3> <div style="line-height: 2.5;"> <<for _skill range _npc.skills>> <span style="background: #1a1a1a; color: #ffc107; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #ffc107; font-weight: 500; white-space: nowrap; display: inline-block; margin: 5px 5px 5px 0;">_skill</span> <</for>> </div> </div> <</if>> <!-- Action Buttons --> <<if _npc.name === "Roisin Sullivan">> <!-- Calculate trait storage price based on friendship level --> <<set _roisinFriendship = ($relationships && $relationships[_npc.name]) ? $relationships[_npc.name].level : 0>> <<if _roisinFriendship >= 4>> <<set _traitStoragePrice = 100000>> <<elseif _roisinFriendship >= 3>> <<set _traitStoragePrice = 500000>> <<elseif _roisinFriendship >= 2>> <<set _traitStoragePrice = 1000000>> <<elseif _roisinFriendship >= 1>> <<set _traitStoragePrice = 5000000>> <<else>> <<set _traitStoragePrice = 10000000>> <</if>> <<set _canBuyTraitStorage = _roisinFriendship >= 0 && !$traitStorageUnlocked>> <<set _canAffordTraitStorage = $money >= _traitStoragePrice>> <!-- 4-column grid for Roisin Sullivan --> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 15px; margin-top: 25px;"> <<link "<div style='background: #667eea; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💱 Initiate Trade</div>">> <<set $tradingWithNPC = _npc>> <<goto "TradeInterface">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💬 Talk</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCTalk">> <</link>> <<link "<div style='background: #28a745; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💰 Sell Traits</div>">> <<set $tradingWithNPC = _npc>> <<goto "SellTraits">> <</link>> <!-- Trait Storage Purchase --> <<if $traitStorageUnlocked>> <div style='background: #333; color: #888; padding: 18px; border-radius: 12px; text-align: center; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'> 🧬 Trait Storage<br><span style="font-size: 12px;">(Already Owned)</span> </div> <<elseif _roisinFriendship < 0>> <div style='background: #333; color: #888; padding: 18px; border-radius: 12px; text-align: center; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'> 🧬 Trait Storage<br><span style="font-size: 12px;">(Won't sell to you)</span> </div> <<elseif !_canAffordTraitStorage>> <div style='background: #333; color: #888; padding: 18px; border-radius: 12px; text-align: center; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'> 🧬 Trait Storage<br><span style="font-size: 12px;">$<<print _traitStoragePrice.toLocaleString()>></span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #e040fb;'>🧬 Trait Storage<br><span style='font-size: 12px;'>$<<print _traitStoragePrice.toLocaleString()>></span></div>">> <<set $money -= _traitStoragePrice>> <<set $traitStorageUnlocked = true>> <<set $traitStorage = []>> <<goto "RoisinTraitStoragePurchased">> <</link>> <</if>> </div> <<elseif _npc.name === "Xanithar Galdenentri" || _npc.name === "Xantria Galdenentri" || _npc.originalName === "Bun Bun" || _npc.name === "Quesha Epo" || _npc.originalName === "Quesha Epo" || _npc.name === "Flona Vulri" || _npc.originalName === "Flona Vulri" || _npc.name === "Clair" || _npc.originalName === "Clair">> <!-- Xanithar/Xantria/Bun Bun/Quesha/Flona/Clair: Talk only, no trading --> <div style="display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 25px; max-width: 300px; margin-left: auto; margin-right: auto;"> <<link "<div style='background: #17a2b8; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💬 Talk</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCTalk">> <</link>> </div> <<else>> <!-- 2-column grid for other NPCs --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 25px;"> <<link "<div style='background: #667eea; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💱 Initiate Trade</div>">> <<set $tradingWithNPC = _npc>> <<goto "TradeInterface">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💬 Talk</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCTalk">> <</link>> </div> <</if>> <!-- Slime: Slither & Possess (classic interface). Mirrors the compact-menu option so slime players can possess from either interface. canPossess already excludes protected/anchor/maid NPCs. --> <<if setup.slime.isPlayerSlimeBodied() && setup.slimePossession.canPossess(_npc).ok>> <div style="display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 15px; max-width: 300px; margin-left: auto; margin-right: auto;"> <<link "<div style='background: linear-gradient(135deg, #1a4d3e 0%, #2ecc71 100%); color: #eafff5; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>🫧 Slither & Possess</div>">> <<set $slimeTargetName = (_npc.originalName || _npc.name)>> <<goto "SlimePossessAttempt">> <</link>> </div> <</if>> <!-- Cafe Recruitment Button --> <<if $cafeOwnership && $cafeOwnership.owned && setup.cafe.recruitableNPCs[_npc.name]>> <<set _recruitStatus = setup.cafe.getRecruitStatus(_npc.name)>> <div style="margin-top: 15px; max-width: 500px; margin-left: auto; margin-right: auto;"> <<if _recruitStatus.can>> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 15px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>🏠 Recruit for <<= $cafeOwnership.cafeName>></div>">> <<set $cafeRecruitTarget = _npc.name>> <<goto "CafeRecruit">> <</link>> <<else>> <div style="background: #333; color: #888; padding: 15px; border-radius: 12px; text-align: center; font-size: 14px; border: 2px solid #555;">🏠 Recruit for <<= $cafeOwnership.cafeName>> — <<= _recruitStatus.reason>></div> <</if>> </div> <</if>> <!-- Life Swap Button - Requires Soul trait (or bypass) --> <<set _hasSoulTrait = ($skills && $skills.includes("Soul")) || ($physicalTraits && $physicalTraits.includes("Soul")) || ($mentalTraits && $mentalTraits.includes("Soul"))>> <<if _hasSoulTrait || $debugLifeSwapBypass>> <<set _lifeSwapProtectedNPCs = ["Xanithar Galdenentri", "Revna McKraken", "Roisin Sullivan", "Luna Snow", "Fen Ris", "Quesha Epo", "Flona Vulri", "Mochi", "Ren", "Clover", "Bun Bun", "Clair"]>> <<set _npcNameForCheck = _npc.originalName || _npc.name>> <<if !_lifeSwapProtectedNPCs.includes(_npcNameForCheck)>> <<set _hasSunfishTrait = ($skills && $skills.includes("Sunfish")) || ($physicalTraits && $physicalTraits.includes("Sunfish")) || ($mentalTraits && $mentalTraits.includes("Sunfish"))>> <<set _hasMinStats = $stats.strength >= 50 && $stats.intelligence >= 50 && $stats.charisma >= 50 && $stats.dexterity >= 50>> <<set _isOriginalBody = $lifeSwapOriginalBodyNPC && (_npc.name === $lifeSwapOriginalBodyNPC || _npc.originalName === $lifeSwapOriginalBodyNPC)>> <<set _canLifeSwap = $debugLifeSwapBypass || _isOriginalBody || (_hasSunfishTrait && _hasMinStats)>> <div style="display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 15px;"> <<if _canLifeSwap>> <<link "<div style='background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #e040fb;'>🔮 Life Swap</div>">> <<set $lifeSwapNPC = _npc>> <<set $lifeSwapIsOriginalBody = _isOriginalBody>> <<goto "LifeSwapConfirm">> <</link>> <<else>> <div style='background: linear-gradient(135deg, #555 0%, #333 100%); color: #888; padding: 18px; border-radius: 12px; text-align: center; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #555;'> 🔮 Life Swap <div style="font-size: 12px; margin-top: 8px; color: #666;"> <<if !_hasSunfishTrait && !_hasMinStats>> Requires Sunfish trait and 50+ in all stats <<elseif !_hasSunfishTrait>> Requires Sunfish trait <<else>> Requires 50+ in all base stats <</if>> </div> </div> <</if>> </div> <</if>> <</if>> <br> <!-- Back Button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Leave</div>">> <<set $tradingWithNPC = null>> <<set _exitTo = $preNPCLocation || $lastLocation || "Downtown">> <<goto _exitTo>> <</link>> </div> </div> <</if>> <</if>> <</nobr>>
<<nobr>> <<if $compactTradeUI>> <<set $playerTradePackage = {stats:[], physical:[], mental:[], skills:[], bodyParts:[], job:null, name:[], gender:null}>> <<set $npcTradePackage = {stats:[], physical:[], mental:[], skills:[], bodyParts:[], job:null, name:[], gender:null}>> <<tradeInterface>> <<else>> <<if !$tradingWithNPC>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <p style="color: #ff6b6b;">Error: No NPC selected for trading.</p> [[Go Back|$lastLocation]] </div> <<else>> <<set _npc = $tradingWithNPC>> <!-- Initialize trade packages if not exists --> <<if !$playerTradePackage>> <<set $playerTradePackage = { stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: [], gender: null }>> <</if>> <<if !$npcTradePackage>> <<set $npcTradePackage = { stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: [], gender: null }>> <</if>> <!-- Check if trading with old body (NPC has player's original body) --> <<set _isOldBody = (_npc.portraitSource === "player")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #667eea;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">💱 Trading with <<print _npc.name>></h1> <p style="color: white; margin: 0; font-size: 16px; text-align: center;"> Build your trade packages below, then attempt the swap when ready </p> </div> <!-- Trade Limit Display --> <div style="background: #2a2a2a; border: 3px solid #ffc107; padding: 18px; border-radius: 10px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="color: #ffc107; font-size: 18px; font-weight: bold;"> ⚡ Trades Remaining Today: <span style="color: #667eea;"><<print $tradesRemainingToday>> / <<print 5 + ($bonusDailyTrades || 0)>></span> </div> <<if $failedTradesWithToday.includes(_npc.name)>> <div style="color: #ff6b6b; font-weight: bold; margin-top: 10px; font-size: 16px;"> ⚠️ You already failed a trade with <<print _npc.name>> today! </div> <</if>> </div> <!-- Trade Value Calculation --> <<set _playerValue = setup.calculateTradeValue($playerTradePackage, true)>> <<set _baseNpcValue = setup.calculateTradeValue($npcTradePackage, false)>> <!-- Calculate preference adjustments FIRST (before relationship) --> <<set _npcValueAfterPreferences = setup.calculatePreferenceValueAdjustment(_npc, $playerTradePackage, $npcTradePackage, _baseNpcValue)>> <<set _preferenceAdjustment = _npcValueAfterPreferences - _baseNpcValue>> <!-- Get relationship level --> <<set _relLevel = 0>> <<if $relationships[_npc.name]>> <<set _relLevel = $relationships[_npc.name].level>> <</if>> <!-- Calculate relationship discount multiplier --> <<set _relMultiplier = 1.0>> <<if _relLevel === 2>> <<set _relMultiplier = 0.95>> <<elseif _relLevel === 3>> <<set _relMultiplier = 0.90>> <<elseif _relLevel === 4>> <<set _relMultiplier = 0.85>> <<elseif _relLevel >= 5>> <<set _relMultiplier = 0.80>> <</if>> <!-- Apply relationship discount to get value after relationship --> <<set _valueAfterRelationship = Math.floor(_npcValueAfterPreferences * _relMultiplier)>> <<set _relationshipDiscount = _npcValueAfterPreferences - _valueAfterRelationship>> <!-- ===== SKILL TREE: Apply Trade Value Reduction ===== --> <<set _skillTreeValueReduction = setup.skillTree.getEffect("tradeValueReduction")>> <<set _adjustedNpcValue = Math.max(0, _valueAfterRelationship - _skillTreeValueReduction)>> <<set _actualSkillReduction = _valueAfterRelationship - _adjustedNpcValue>> <!-- Calculate success chance modifiers --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _charismaBonus = 0>> <<if _totalCharisma > 0>> <<set _charismaBonus = Math.min(40, Math.floor(_totalCharisma / 3.75))>> <</if>> <<set _tradingBonus = $skills.includes("Trading") ? 2 : 0>> <<set _persuasionBonus = $skills.includes("Persuasion") ? 3 : 0>> <<set _sunfishBonus = $mentalTraits.includes("Sunfish") ? 10 : 0>> <<set _werefoxBonus = $physicalTraits.includes("Werefox") ? 10 : 0>> <<set _sirenBonus = $physicalTraits.includes("Siren") ? 30 : 0>> <!-- ===== SKILL TREE: Trade Success Bonus ===== --> <<set _skillTreeTradeBonus = setup.skillTree.getEffect("tradeSuccessBonus")>> <!-- ===== BUFF SYSTEM: Trade Bonus from buffs ===== --> <<set _buffTradeBonus = setup.getBuffEffect("tradeChance")>> <!-- Calculate beneficial trait bonuses --> <<set _beneficialTraits = ["Honest", "Confident", "Friendly", "Trusting", "Patient", "Intelligent", "Analytical", "Chill", "Nonchalant", "Charming", "Diplomatic", "Polite", "Reassuring", "Efficient", "Warm", "Lucky", "Cerberus", "Werecat", "Weresheep", "Himbo", "Werefox", "Trophy Wife", "Werebunny", "Punk", "Gym Bunny", "Siren"]>> <<set _beneficialCount = 0>> <<set _beneficialList = []>> <<for _i = 0; _i < _beneficialTraits.length; _i++>> <<if $mentalTraits.includes(_beneficialTraits[_i])>> <<set _beneficialCount++>> <<run _beneficialList.push(_beneficialTraits[_i])>> <</if>> <</for>> <<set _beneficialBonus = Math.ceil(_beneficialCount * 2)>> <!-- Calculate detrimental trait penalties --> <<set _detrimentalTraits = ["Aggressive", "Awkward", "Blunt", "Corrupt", "Moody", "Pessimistic", "Sensitive", "Shy", "Stubborn", "Arrogant", "Cold", "Deceitful", "Foolish", "Forgetful", "Impatient", "Insecure", "Reckless", "Rude", "Selfish", "Short Tempered", "Unlucky", "Unreliable", "Bitchy"]>> <<set _detrimentalCount = 0>> <<set _detrimentalList = []>> <<for _i = 0; _i < _detrimentalTraits.length; _i++>> <<if $mentalTraits.includes(_detrimentalTraits[_i])>> <<set _detrimentalCount++>> <<run _detrimentalList.push(_detrimentalTraits[_i])>> <</if>> <</for>> <<set _detrimentalPenalty = Math.ceil(_detrimentalCount * 3)>> <<set _isCriminal = ($jobs && $jobs.includes("Criminal"))>> <<set _relationshipBonus = setup.getRelationshipTradeBonus(_npc.name)>> <!-- Debuff modifiers (tradeChance from debuffs like exhaustion) --> <<set _debuffTradePenalty = setup.getDebuffEffect("tradeChance")>> <!-- Calculate total additive modifier (before criminal multiplier) --> <<set _totalModifier = _charismaBonus + _tradingBonus + _persuasionBonus + _sunfishBonus + _werefoxBonus + _sirenBonus + _skillTreeTradeBonus + _buffTradeBonus + _beneficialBonus - _detrimentalPenalty + _relationshipBonus + _debuffTradePenalty>> <<set _tradeChance = setup.calculateTradeChance(_playerValue, _adjustedNpcValue, _npc, $playerTradePackage, $npcTradePackage)>> <!-- OLD BODY TRADE RESTRICTION: Both sides must offer at least 75% of the other's value --> <<set _oldBodyTradeBlocked = false>> <<set _oldBodyBlockReason = "">> <<if _isOldBody && (_playerValue > 0 || _baseNpcValue > 0)>> <<set _minPlayerValueNeeded = Math.ceil(_baseNpcValue * 0.75)>> <<set _minNpcValueNeeded = Math.ceil(_playerValue * 0.75)>> <<if _playerValue < _minPlayerValueNeeded && _baseNpcValue > 0>> <<set _oldBodyTradeBlocked = true>> <<set _oldBodyBlockReason = "Your offer (" + _playerValue + ") must be at least 75% of what you're requesting (" + _minPlayerValueNeeded + " minimum).">> <<elseif _baseNpcValue < _minNpcValueNeeded && _playerValue > 0>> <<set _oldBodyTradeBlocked = true>> <<set _oldBodyBlockReason = "What you're requesting (" + _baseNpcValue + ") must be at least 75% of what you're offering (" + _minNpcValueNeeded + " minimum).">> <</if>> <</if>> <!-- Success Chance Modifiers Display --> <<if _totalModifier !== 0 || _buffTradeBonus > 0 || _isCriminal || ($currentArtifact === "The Drifter's Coin" || ($physicalTraits && $physicalTraits.includes("Naiad"))) || _debuffTradePenalty !== 0>> <div @style="'background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid ' + (_totalModifier > 0 ? '#51cf66' : '#ff6b6b') + ';'"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Success Chance Modifiers:</div> <<if _charismaBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Charisma Bonus: +<<print _charismaBonus>>% (Charisma: <<print _totalCharisma>><<if _totalCharisma >= 150>> - MAX<</if>>) </div> <</if>> <<if _tradingBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Trading Skill: +<<print _tradingBonus>>% </div> <</if>> <<if _persuasionBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Persuasion Skill: +<<print _persuasionBonus>>% </div> <</if>> <<if _sunfishBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Sunfish Trait: +<<print _sunfishBonus>>% </div> <</if>> <<if _sirenBonus > 0>> <div style="color: #4fc3f7; font-size: 14px; margin: 3px 0;"> ✓ Siren: +<<print _sirenBonus>>% </div> <</if>> <<if _werefoxBonus > 0>> <div style="color: #ff9800; font-size: 14px; margin: 3px 0;"> ✓ Werefox: +<<print _werefoxBonus>>% </div> <</if>> <<if _skillTreeTradeBonus > 0>> <div style="color: #9C27B0; font-size: 14px; margin: 3px 0;"> ⭐ Skill Tree (Bonus %): +<<print _skillTreeTradeBonus>>% </div> <</if>> <<if _buffTradeBonus > 0>> <div style="color: #4fc3f7; font-size: 14px; margin: 3px 0;"> ✨ Buff Bonus: +<<print _buffTradeBonus>>% </div> <</if>> <<if _beneficialBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Beneficial Traits: +<<print _beneficialBonus>>% (<<print _beneficialList.join(", ")>>) </div> <</if>> <<if _relationshipBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Relationship Bonus: +<<print _relationshipBonus>>% (Level <<print _relLevel>>) </div> <</if>> <<if _debuffTradePenalty < 0>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0;"> 💤 Debuff Penalty: <<print _debuffTradePenalty>>% </div> <</if>> <<if _detrimentalPenalty > 0>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0;"> ✗ Detrimental Traits: -<<print _detrimentalPenalty>>% (<<print _detrimentalList.join(", ")>>) </div> <</if>> <<if _isCriminal>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0;"> ✗ Criminal Job: ×0.25 (75% reduction - MULTIPLICATIVE) </div> <</if>> <<if ($currentArtifact === "The Drifter's Coin" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="color: #FFD700; font-size: 14px; margin: 3px 0;"> ✨ The Drifter's Coin: ×2 Success Chance! </div> <</if>> <div @style="'color: ' + (_totalModifier > 0 ? '#51cf66' : '#ff6b6b') + '; font-size: 15px; margin-top: 8px; font-weight: bold; border-top: 1px solid #444; padding-top: 8px;'"> Total Additive Modifier: <<if _totalModifier > 0>>+<</if>><<print _totalModifier>>% <<if _isCriminal>> <span style="color: #ff6b6b;"> × 0.25</span> <</if>> <<if ($currentArtifact === "The Drifter's Coin" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #FFD700;"> × 2</span> <</if>> </div> </div> <</if>> <!-- Value Adjustment Breakdown --> <<if _preferenceAdjustment !== 0 || _relationshipDiscount > 0 || _actualSkillReduction > 0>> <<set _prefs = setup.getNPCPreferences(_npc)>> <<set _willingCount = 0>> <<set _desiredCount = 0>> <<set _reluctantCount = 0>> <<if _prefs && _prefs.willingToTrade>> <<for _i = 0; _i < $playerTradePackage.physical.length; _i++>> <<if _prefs.willingToTrade.physical && _prefs.willingToTrade.physical.includes($playerTradePackage.physical[_i])>> <<set _willingCount++>> <</if>> <</for>> <<for _i = 0; _i < $playerTradePackage.mental.length; _i++>> <<if _prefs.willingToTrade.mental && _prefs.willingToTrade.mental.includes($playerTradePackage.mental[_i])>> <<set _willingCount++>> <</if>> <</for>> <<for _i = 0; _i < $playerTradePackage.skills.length; _i++>> <<if _prefs.willingToTrade.skills && _prefs.willingToTrade.skills.includes($playerTradePackage.skills[_i])>> <<set _willingCount++>> <</if>> <</for>> <</if>> <<if _prefs && _prefs.desires>> <<for _i = 0; _i < $playerTradePackage.physical.length; _i++>> <<if _prefs.desires.physical && _prefs.desires.physical.includes($playerTradePackage.physical[_i])>> <<set _desiredCount++>> <</if>> <</for>> <<for _i = 0; _i < $playerTradePackage.mental.length; _i++>> <<if _prefs.desires.mental && _prefs.desires.mental.includes($playerTradePackage.mental[_i])>> <<set _desiredCount++>> <</if>> <</for>> <<for _i = 0; _i < $playerTradePackage.skills.length; _i++>> <<if _prefs.desires.skills && _prefs.desires.skills.includes($playerTradePackage.skills[_i])>> <<set _desiredCount++>> <</if>> <</for>> <</if>> <<if _prefs && _prefs.reluctantToTrade>> <<for _i = 0; _i < $npcTradePackage.physical.length; _i++>> <<if _prefs.reluctantToTrade.physical && _prefs.reluctantToTrade.physical.includes($npcTradePackage.physical[_i])>> <<set _reluctantCount++>> <</if>> <</for>> <<for _i = 0; _i < $npcTradePackage.mental.length; _i++>> <<if _prefs.reluctantToTrade.mental && _prefs.reluctantToTrade.mental.includes($npcTradePackage.mental[_i])>> <<set _reluctantCount++>> <</if>> <</for>> <<for _i = 0; _i < $npcTradePackage.skills.length; _i++>> <<if _prefs.reluctantToTrade.skills && _prefs.reluctantToTrade.skills.includes($npcTradePackage.skills[_i])>> <<set _reluctantCount++>> <</if>> <</for>> <</if>> <div @style="'background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid ' + ((_preferenceAdjustment > 0 || _relationshipDiscount > 0 || _actualSkillReduction > 0) ? '#51cf66' : '#ff6b6b') + ';'"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">NPC Value Adjustments:</div> <div style="color: #ccc; font-size: 14px; margin: 3px 0;"> Base NPC Offer Value: <<print _baseNpcValue>> </div> <<if _willingCount > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Willing Items: <<print _willingCount>> item<<if _willingCount > 1>>s<</if>> (-20% cost each) </div> <</if>> <<if _desiredCount > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> 💚 Desired Items: <<print _desiredCount>> item<<if _desiredCount > 1>>s<</if>> (-15% cost each) </div> <</if>> <<if _reluctantCount > 0>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0;"> ⚠️ Reluctant Items: <<print _reluctantCount>> item<<if _reluctantCount > 1>>s<</if>> (+30% cost each) </div> <</if>> <<if _preferenceAdjustment !== 0>> <<if _preferenceAdjustment > 0>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0; font-style: italic;"> Preference Penalty: +<<print Math.abs(_preferenceAdjustment)>> </div> <<else>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0; font-style: italic;"> Preference Discount: <<print _preferenceAdjustment>> </div> <</if>> <div style="color: #ccc; font-size: 14px; margin: 3px 0; border-top: 1px solid #444; padding-top: 5px; margin-top: 5px;"> After Preferences: <<print _npcValueAfterPreferences>> </div> <</if>> <<if _relationshipDiscount > 0>> <<set _discountPercent = Math.round((1 - _relMultiplier) * 100)>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0; margin-top: 5px;"> ✓ Relationship Discount (Level <<print _relLevel>>): -<<print _discountPercent>>% (-<<print _relationshipDiscount>>) </div> <</if>> <<if _actualSkillReduction > 0>> <div style="color: #9C27B0; font-size: 14px; margin: 3px 0; margin-top: 5px;"> ⭐ Skill Tree (Trading): -<<print _actualSkillReduction>> value required </div> <</if>> <div @style="'color: ' + (_adjustedNpcValue < _baseNpcValue ? '#51cf66' : '#ff6b6b') + '; font-size: 15px; margin-top: 8px; font-weight: bold; border-top: 1px solid #444; padding-top: 8px;'"> Final NPC Value Required: <<print _adjustedNpcValue>> </div> </div> <</if>> <!-- Value from Exceeding Requirement --> <<if _playerValue > _adjustedNpcValue>> <<set _excessValue = _playerValue - _adjustedNpcValue>> <<set _excessPercent = Math.round((_excessValue / _adjustedNpcValue) * 100)>> <<set _baseChanceFromValue = Math.min(100, 1 + Math.round(((_playerValue / _adjustedNpcValue) - 1.0) / 0.7 * 99))>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #51cf66;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Trade Value Bonus:</div> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Offering <<print _excessValue>> more than required (+<<print _excessPercent>>% extra) </div> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Base success chance from value: <<print _baseChanceFromValue>>% </div> </div> <</if>> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; border: 3px solid #667eea; text-align: center; box-shadow: 0 2px 4px rgba(0,0,0,0.3);"> <div style="font-size: 16px; color: #aaa; margin-bottom: 8px; font-weight: bold;">Your Offer Value</div> <div style="font-size: 36px; font-weight: bold; color: #667eea;"><<print _playerValue>></div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; border: 3px solid #9b59b6; text-align: center; box-shadow: 0 2px 4px rgba(0,0,0,0.3);"> <div style="font-size: 16px; color: #aaa; margin-bottom: 8px; font-weight: bold;">Their Offer Value</div> <div style="font-size: 36px; font-weight: bold; color: #9b59b6;"><<print _baseNpcValue>></div> </div> <div @style="'background: #1a1a1a; padding: 20px; border-radius: 10px; border: 3px solid ' + (_tradeChance >= 50 ? '#51cf66' : (_tradeChance >= 30 ? '#ffc107' : '#ff6b6b')) + '; text-align: center; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'"> <div style="font-size: 16px; color: #aaa; margin-bottom: 8px; font-weight: bold;">Success Chance</div> <div @style="'font-size: 36px; font-weight: bold; color: ' + (_tradeChance >= 50 ? '#51cf66' : (_tradeChance >= 30 ? '#ffc107' : '#ff6b6b')) + ';'"><<print _tradeChance>>%</div> </div> </div> <!-- Old Body Trade Restriction Warning --> <<if _isOldBody>> <div style="background: #1a1a1a; border: 3px solid #e040fb; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #e040fb;">🔮 Trading with Your Old Body</strong> <p style="margin: 8px 0 0 0; font-size: 14px;">Both sides must offer at least 75% of the other's value. You cannot give away traits for free or make heavily unbalanced trades with your old body.</p> </div> <</if>> <<if _oldBodyTradeBlocked>> <div style="background: #1a1a1a; border: 3px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #ff6b6b;">⚠️ Unbalanced Trade Blocked!</strong> <<print _oldBodyBlockReason>> </div> <<elseif _playerValue < _adjustedNpcValue>> <div style="background: #1a1a1a; border: 3px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <<if _playerValue <= 0>> <strong style="color: #ff6b6b;">⚠️ Invalid Offer!</strong> You cannot offer negative or zero value. Your current offer value is <strong><<print _playerValue>></strong>. You cannot dump negative traits to get rid of them! <<else>> <strong style="color: #ff6b6b;">⚠️ Insufficient Value!</strong> You need to offer at least <strong><<print _adjustedNpcValue>></strong> value to attempt this trade. <<if _relationshipDiscount > 0>><span style="color: #51cf66;">(Relationship discount applied! Originally <<print _npcValueAfterPreferences>>)</span><</if>> <<if _actualSkillReduction > 0>><span style="color: #9C27B0;"> (Skill tree reduction applied!)</span><</if>> You are offering <strong><<print _playerValue>></strong>. <</if>> </div> <<elseif _tradeChance === 0>> <div style="background: #1a1a1a; border: 3px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #ff6b6b;">⚠️ Cannot Trade!</strong> Your offer does not meet the minimum requirements. </div> <<elseif _tradeChance < 30>> <div style="background: #1a1a1a; border: 3px solid #ffc107; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #ffc107;">⚠️ Low Chance!</strong> Consider offering more value for a better chance of success. (Currently <<print _tradeChance>>%) </div> <<elseif _tradeChance >= 100>> <div style="background: #1a1a1a; border: 3px solid #51cf66; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #51cf66;">✓ Guaranteed Success!</strong> You are offering double value or more. This trade will succeed 100%. </div> <<else>> <div style="background: #1a1a1a; border: 3px solid #17a2b8; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #17a2b8;">ℹ️ Fair Trade.</strong> You have a <<print _tradeChance>>% chance of success. Offer more value to increase your odds. </div> <</if>> <!-- Two Column Layout for Trade Building --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px; margin-bottom: 25px;"> <!-- YOUR OFFER COLUMN --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 4px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 20px 0; font-size: 26px; border-bottom: 3px solid #667eea; padding-bottom: 10px;">🎁 Your Offer</h2> <<if $playerTradePackage.name.length === 0 && $playerTradePackage.stats.length === 0 && $playerTradePackage.physical.length === 0 && $playerTradePackage.mental.length === 0 && $playerTradePackage.skills.length === 0 && $playerTradePackage.bodyParts.length === 0 && !$playerTradePackage.job>> <p style="color: #666; font-style: italic; text-align: center; font-size: 16px; padding: 40px 20px;">Empty. Click below to add items</p> <<else>> <!-- NAME --> <<if $playerTradePackage.name.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #9b59b6;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 8px;">👤 Name</div> <<for _i = 0; _i < $playerTradePackage.name.length; _i++>> <<set _nameObj = $playerTradePackage.name[_i]>> <<set _displayName = _nameObj.type === "firstName" ? (_nameObj.head ? setup.getCerberusHeadName(_nameObj.head) : $firstName) : $lastName>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<if _nameObj.type === "firstName">>First Name<<if _nameObj.head>> (<<print _nameObj.head>>)<</if>><<else>>Last Name<</if>>: <<print _displayName>> <<capture _nameObj>> <<link "❌">> <<run $playerTradePackage.name.delete(_nameObj)>> <<set _matchingNpc = $npcTradePackage.name.find(n => n.type === _nameObj.type)>> <<if _matchingNpc>><<run $npcTradePackage.name.delete(_matchingNpc)>><</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- BODY PARTS --> <<if $playerTradePackage.bodyParts.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #ff6b6b;"> <div style="color: #ff6b6b; font-weight: bold; margin-bottom: 8px;">🫀 Body Parts</div> <<for _i = 0; _i < $playerTradePackage.bodyParts.length; _i++>> <<set _bp = $playerTradePackage.bodyParts[_i]>> <<capture _bp>> <<set _bpActualValue = _bp.name === "chest" || _bp.name === "butt" || _bp.name === "gender" || _bp.name === "genitals" ? $bodyParts[_bp.name] : $appearance[_bp.name]>> <<if _bpActualValue && _bpActualValue !== "">> <<set _bpValue = setup.getTraitValue("bodyPart", _bp.name, _bpActualValue)>> <<set _bpDisplayText = _bpActualValue + " " + _bp.name>> <<else>> <<set _bpValue = 0>> <<set _bpDisplayText = _bp.name.toUpperFirst()>> <</if>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _bpDisplayText.toUpperFirst()>> (<<print _bpValue>>) <<link "❌">> <<run $playerTradePackage.bodyParts.delete(_bp)>> <<set _matchingNpcBp = $npcTradePackage.bodyParts.find(b => b.name === _bp.name)>> <<if _matchingNpcBp>><<run $npcTradePackage.bodyParts.delete(_matchingNpcBp)>><</if>> <<goto "TradeInterface">> <</link>> </div> <</capture>> <</for>> </div> <</if>> <!-- PHYSICAL TRAITS --> <<if $playerTradePackage.physical.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #51cf66;"> <div style="color: #51cf66; font-weight: bold; margin-bottom: 8px;">💪 Physical Traits</div> <<for _i = 0; _i < $playerTradePackage.physical.length; _i++>> <<set _trait = $playerTradePackage.physical[_i]>> <<capture _trait>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _trait>> (<<print _traitValue>>) <<link "❌">> <<run $playerTradePackage.physical.delete(_trait)>> <<set _conflict = setup.getConflictingTrait(_trait, _npc.physicalTraits)>> <<if _conflict>><<run $npcTradePackage.physical.delete(_conflict)>><</if>> <<goto "TradeInterface">> <</link>> </div> <</capture>> <</for>> </div> <</if>> <!-- MENTAL TRAITS --> <<if $playerTradePackage.mental.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #9b59b6;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 8px;">🧠 Mental Traits</div> <<for _i = 0; _i < $playerTradePackage.mental.length; _i++>> <<set _trait = $playerTradePackage.mental[_i]>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _trait>> (<<print _traitValue>>) <<capture _trait>> <<link "❌">> <<run $playerTradePackage.mental.delete(_trait)>> <<set _conflict = setup.getConflictingTrait(_trait, _npc.mentalTraits)>> <<if _conflict>><<run $npcTradePackage.mental.delete(_conflict)>><</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- SKILLS --> <<if $playerTradePackage.skills.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #ffc107;"> <div style="color: #ffc107; font-weight: bold; margin-bottom: 8px;">🎯 Skills</div> <<for _i = 0; _i < $playerTradePackage.skills.length; _i++>> <<set _skill = $playerTradePackage.skills[_i]>> <<set _skillValue = setup.getTraitValue("skill", _skill)>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _skill>> (+<<print _skillValue>>) <<capture _skill>> <<link "❌">> <<run $playerTradePackage.skills.delete(_skill)>> <<run $npcTradePackage.skills.delete(_skill)>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- JOB --> <<if $playerTradePackage.job>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #17a2b8;"> <div style="color: #17a2b8; font-weight: bold; margin-bottom: 8px;">💼 Job</div> <<set _jobValue = setup.getTraitValue("job", $playerTradePackage.job)>> <div style="color: #ccc; padding: 6px 0;"> <<print $playerTradePackage.job>> (<<print _jobValue>>) <<link "❌">> <<set $playerTradePackage.job = null>> <<set $npcTradePackage.job = null>> <<goto "TradeInterface">> <</link>> </div> </div> <</if>> <</if>> <<link "<div style='background: #667eea; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; margin-top: 15px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>➕ Add to Your Offer</div>">> <<set $tradeSide = "player">> <<goto "TradeSelectItems">> <</link>> </div> <!-- THEIR OFFER COLUMN --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 4px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #9b59b6; margin: 0 0 20px 0; font-size: 26px; border-bottom: 3px solid #9b59b6; padding-bottom: 10px;">🎁 Their Offer</h2> <<if $npcTradePackage.name.length === 0 && $npcTradePackage.stats.length === 0 && $npcTradePackage.physical.length === 0 && $npcTradePackage.mental.length === 0 && $npcTradePackage.skills.length === 0 && $npcTradePackage.bodyParts.length === 0 && !$npcTradePackage.job>> <p style="color: #666; font-style: italic; text-align: center; font-size: 16px; padding: 40px 20px;">Empty. Click below to add items</p> <<else>> <!-- NAME --> <<if $npcTradePackage.name.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #9b59b6;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 8px;">👤 Name</div> <<for _i = 0; _i < $npcTradePackage.name.length; _i++>> <<set _nameObj = $npcTradePackage.name[_i]>> <<set _npcNameParts = _npc.name.split(" ")>> <<set _displayName = _nameObj.type === "firstName" ? _npcNameParts[0] : _npcNameParts.slice(1).join(" ")>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<if _nameObj.type === "firstName">>First Name<<if _nameObj.head>> (<<print _nameObj.head>>)<</if>><<else>>Last Name<</if>>: <<print _displayName>> <<capture _nameObj>> <<link "❌">> <<run $npcTradePackage.name.delete(_nameObj)>> <<set _matchingPlayer = $playerTradePackage.name.find(n => n.type === _nameObj.type)>> <<if _matchingPlayer>><<run $playerTradePackage.name.delete(_matchingPlayer)>><</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- BODY PARTS --> <<if $npcTradePackage.bodyParts.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #ff6b6b;"> <div style="color: #ff6b6b; font-weight: bold; margin-bottom: 8px;">🫀 Body Parts</div> <<for _i = 0; _i < $npcTradePackage.bodyParts.length; _i++>> <<set _bp = $npcTradePackage.bodyParts[_i]>> <<capture _bp>> <<set _bpActualValue = _bp.name === "chest" || _bp.name === "butt" || _bp.name === "gender" || _bp.name === "genitals" ? _npc.bodyParts[_bp.name] : _npc.appearance[_bp.name]>> <<if _bpActualValue && _bpActualValue !== "">> <<set _bpValue = setup.getTraitValue("bodyPart", _bp.name, _bpActualValue)>> <<set _bpDisplayText = _bpActualValue + " " + _bp.name>> <<else>> <<set _bpValue = 0>> <<set _bpDisplayText = _bp.name.toUpperFirst()>> <</if>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _bpDisplayText.toUpperFirst()>> (<<print _bpValue>>) <<link "❌">> <<run $npcTradePackage.bodyParts.delete(_bp)>> <<set _matchingPlayerBp = $playerTradePackage.bodyParts.find(b => b.name === _bp.name)>> <<if _matchingPlayerBp>><<run $playerTradePackage.bodyParts.delete(_matchingPlayerBp)>><</if>> <<goto "TradeInterface">> <</link>> </div> <</capture>> <</for>> </div> <</if>> <!-- PHYSICAL TRAITS --> <<if $npcTradePackage.physical.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #51cf66;"> <div style="color: #51cf66; font-weight: bold; margin-bottom: 8px;">💪 Physical Traits</div> <<for _i = 0; _i < $npcTradePackage.physical.length; _i++>> <<set _trait = $npcTradePackage.physical[_i]>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _trait>> (<<print _traitValue>>) <<capture _trait>> <<link "❌">> <<run $npcTradePackage.physical.delete(_trait)>> <<set _conflict = setup.getConflictingTrait(_trait, $physicalTraits)>> <<if _conflict>><<run $playerTradePackage.physical.delete(_conflict)>><</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- MENTAL TRAITS --> <<if $npcTradePackage.mental.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #9b59b6;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 8px;">🧠 Mental Traits</div> <<for _i = 0; _i < $npcTradePackage.mental.length; _i++>> <<set _trait = $npcTradePackage.mental[_i]>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _trait>> (<<print _traitValue>>) <<capture _trait>> <<link "❌">> <<run $npcTradePackage.mental.delete(_trait)>> <<set _conflict = setup.getConflictingTrait(_trait, $mentalTraits)>> <<if _conflict>><<run $playerTradePackage.mental.delete(_conflict)>><</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- SKILLS --> <<if $npcTradePackage.skills.length > 0>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #ffc107;"> <div style="color: #ffc107; font-weight: bold; margin-bottom: 8px;">🎯 Skills</div> <<for _i = 0; _i < $npcTradePackage.skills.length; _i++>> <<set _skill = $npcTradePackage.skills[_i]>> <<set _skillValue = setup.getTraitValue("skill", _skill)>> <div style="color: #ccc; padding: 6px 0; border-bottom: 1px solid #333;"> <<print _skill>> (+<<print _skillValue>>) <<capture _skill>> <<link "❌">> <<run $npcTradePackage.skills.delete(_skill)>> <<run $playerTradePackage.skills.delete(_skill)>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- JOB --> <<if $npcTradePackage.job>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 12px; border: 2px solid #17a2b8;"> <div style="color: #17a2b8; font-weight: bold; margin-bottom: 8px;">💼 Job</div> <<set _jobValue = setup.getTraitValue("job", $npcTradePackage.job)>> <div style="color: #ccc; padding: 6px 0;"> <<print $npcTradePackage.job>> (<<print _jobValue>>) <<link "❌">> <<set $npcTradePackage.job = null>> <<set $playerTradePackage.job = null>> <<goto "TradeInterface">> <</link>> </div> </div> <</if>> <</if>> <<link "<div style='background: #9b59b6; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; margin-top: 15px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>➕ Request Their Items</div>">> <<set $tradeSide = "npc">> <<goto "TradeSelectItems">> <</link>> </div> </div> <!-- Action Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; margin-top: 25px;"> <<if _playerValue >= _adjustedNpcValue && _tradeChance > 0 && !$failedTradesWithToday.includes(_npc.name) && $tradesRemainingToday > 0 && !_oldBodyTradeBlocked && !setup.isTradeBlocked(_npc, $playerTradePackage, $npcTradePackage)>> <<link `"<div style='background: #51cf66; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>✅ Attempt Trade (" + _tradeChance + "%)</div>"`>> <<set $tradeResult = setup.attemptTrade(_npc, $playerTradePackage, $npcTradePackage)>> <<set $tradeResult.successChance = _tradeChance>> <<goto "TradeResult">> <</link>> <<else>> <div style='background: #3a3a3a; color: #666; padding: 18px; border-radius: 12px; text-align: center; font-weight: bold; font-size: 18px; opacity: 0.6;'>✅ Cannot Trade</div> <</if>> <<link "<div style='background: #ff6b6b; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🗑️ Clear All</div>">> <<set $playerTradePackage = { stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: [], gender: null }>> <<set $npcTradePackage = { stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: [], gender: null }>> <<goto "TradeInterface">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Cancel</div>">> <<set $playerTradePackage = null>> <<set $npcTradePackage = null>> <<set $currentNPC = null>> <<set $tradingWithNPC = null>> <<goto $lastLocation>> <</link>> </div> </div> <</if>> <</if>> <</nobr>>
<<nobr>> <<set $money = 0>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Age Verification Card --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0; text-align: center;">⚠️ Age Verification</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <p style="color: #e0e0e0; font-size: 16px; margin: 0 0 20px 0; text-align: center;"> Are you 18 years old or older? </p> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #51cf66dd 100%); color: white; padding: 12px 35px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); display: inline-block;'>✅ Yes</div>">> <<goto "DreamIntro">> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #ff6b6bdd 100%); color: white; padding: 12px 35px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); display: inline-block;'>❌ No</div>">> <<goto "Exit">> <</link>> </div> </div> </div> <!-- Game Info Card --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <p style="color: #e0e0e0; font-size: 16px; margin: 0 0 10px 0; text-align: center;"> Welcome to Sunfish City! A trait swapping game I made for the fun of it! </p> <p style="color: #ffc107; font-size: 14px; margin: 0; text-align: center; font-style: italic;"> <strong>Disclaimer:</strong> Not all jobs have functionality yet. </p> </div> <!-- Bugs Report Box --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <p style="color: #51cf66; font-size: 15px; margin: 0; text-align: center; font-weight: bold;"> Please report any bugs you find to my <a href="https://discord.gg/z9eDdQC6zA" target="_blank" style="color: #7289da; text-decoration: underline;">Discord</a> so I can easily sort them! </p> </div> <!-- Wiki Link --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <p style="color: #4dabf7; font-size: 15px; margin: 0; text-align: center; font-weight: bold;"> <a href="https://wiki.grankgames.com/index.php?title=Main_Page" target="_blank" style="color: #4dabf7; text-decoration: underline;">Click here to checkout the Official Sunfish City Wiki</a> </p> <p style="color: #ffd43b; font-size: 13px; margin: 8px 0 0 0; text-align: center;"> I'm looking for more Wiki Editors, if you're interested message me on Discord! </p> </div> <!-- Official Distribution Disclaimer --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #ffc107;"> <p style="color: #ffc107; font-size: 14px; margin: 0; text-align: center; font-weight: bold;"> ⚠️ If you found this game anywhere other than <a href="https://grankgames.com/" target="_blank" style="color: #51cf66; text-decoration: underline;">grankgames.com</a>, <a href="https://grankor72.itch.io/sunfish-city" target="_blank" style="color: #51cf66; text-decoration: underline;">itch.io</a>, <a href="https://tfgames.site/index.php?module=viewgame&id=3606" target="_blank" style="color: #51cf66; text-decoration: underline;">tfgames.site</a>, or <a href="https://www.patreon.com/c/Grankor" target="_blank" style="color: #51cf66; text-decoration: underline;">Patreon</a>, it was not me who posted the game there. </p> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<set _isPlayerSide = ($tradeSide === "player")>> <<set _npcPrefs = setup.getNPCPreferences(_npc)>> <!-- Player's inherited trade restrictions from Life Swap --> <<set _playerRestrictions = $lifeSwapTradeRestrictions || null>> <!-- Bimbo trait detection --> <<set _playerIsBimbo = $mentalTraits.includes("Bimbo")>> <<set _npcIsBimbo = _npc.mentalTraits.includes("Bimbo")>> <!-- Check if the CURRENT SIDE we're selecting from has Bimbo --> <<set _currentSideHasBimbo = (_isPlayerSide && _playerIsBimbo) || (!_isPlayerSide && _npcIsBimbo)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #667eea;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;"> <<if _isPlayerSide>> 🎁 Select Items for Your Offer <<else>> 🎁 Select Items You Want from _npc.name <</if>> </h1> <p style="color: white; margin: 0; font-size: 16px; text-align: center;"> Click on items to add them to the trade package </p> </div> <!-- BIMBO WARNING --> <<if _currentSideHasBimbo>> <div style="background: #3a2030; border: 2px solid #ff69b4; padding: 15px; border-radius: 8px; margin-bottom: 25px;"> <<if _isPlayerSide>> <p style="color: #ff69b4; margin: 0; font-weight: bold;">💋 You're a Bimbo! You can only trade your Name, Job, or the Bimbo trait itself.</p> <<else>> <p style="color: #ff69b4; margin: 0; font-weight: bold;">💋 _npc.name is a Bimbo! You can only request their Name, Job, or the Bimbo trait.</p> <</if>> </div> <</if>> <!-- LIFE SWAP TRADE RESTRICTIONS WARNING --> <<if _playerRestrictions && _isPlayerSide>> <div style="background: #2a2040; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; margin-bottom: 25px;"> <p style="color: #9b59b6; margin: 0; font-weight: bold;">Life Swap Restrictions: As <<print _playerRestrictions.sourceNPC>>, certain trades are restricted!</p> <p style="color: #aaa; margin: 5px 0 0 0; font-size: 14px;">Some traits cannot be traded away and some cannot be accepted.</p> </div> <</if>> <!-- NAME SECTION (Always available) --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #9b59b6; padding-bottom: 10px;">👤 Name</h2> <p style="color: #aaa; font-size: 15px; margin: 0 0 15px 0;"><em>Selecting a name automatically swaps both sides</em></p> <<if _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.name>> <div style="background: #3a2020; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0; font-weight: bold;">🚫 _npc.name will NEVER trade their name</p> </div> <</if>> <<set _playerHasFirstName = false>> <<set _playerHasLastName = false>> <<for _n range $playerTradePackage.name>> <<if _n.type === "firstName">><<set _playerHasFirstName = true>><</if>> <<if _n.type === "lastName">><<set _playerHasLastName = true>><</if>> <</for>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<set _nameValue = setup.getTraitValue("name", "firstName")>> <<set _npcFirstName = _npc.name.split(" ")[0]>> <<set _nameBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.name>> <<if !_playerHasFirstName && !_nameBlocked && $physicalTraits.includes("Cerberus")>> <<for _ch range [{k:"center",label:"Center"},{k:"left",label:"Left"},{k:"right",label:"Right"}]>> <<capture _ch>> <<set _chColor = setup.cerberusHeadColors[_ch.k]>> <<set _chName = setup.getCerberusHeadName(_ch.k)>> <<set _chCard = '<div style="background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid ' + _chColor + '; text-align: center;"><div style="font-weight: bold; font-size: 16px; margin-bottom: 5px; color: ' + _chColor + ';">First Name (' + _ch.label + ')</div><div style="color: ' + _chColor + '; font-size: 14px;">' + _chName + ' ↔️ ' + _npcFirstName + '</div><div style="color: ' + _chColor + '; font-size: 13px; margin-top: 5px;">Swap (Value: ' + _nameValue + ')</div></div>'>> <<link _chCard>> <<run $playerTradePackage.name.push({type: "firstName", head: _ch.k, value: setup.getCerberusHeadName(_ch.k)})>> <<run $npcTradePackage.name.push({type: "firstName", value: _npcFirstName})>> <<goto "TradeInterface">> <</link>> <</capture>> <</for>> <<elseif !_playerHasFirstName && !_nameBlocked>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid #9b59b6; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: #9b59b6;'>First Name</div><div style='color: #aaa; font-size: 14px;'><<print $firstName>> ↔️ <<print _npcFirstName>></div><div style='color: #9b59b6; font-size: 13px; margin-top: 5px;'>Swap (Value: <<print _nameValue>>)</div></div>">> <<run $playerTradePackage.name.push({type: "firstName", value: $firstName})>> <<run $npcTradePackage.name.push({type: "firstName", value: _npcFirstName})>> <<goto "TradeInterface">> <</link>> <<elseif _nameBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>First Name</div> <div style='font-size: 14px;'>🚫 Blocked</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>First Name</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <<set _npcLastName = _npc.name.split(" ").slice(1).join(" ")>> <<if !_playerHasLastName && !_nameBlocked>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid #9b59b6; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: #9b59b6;'>Last Name</div><div style='color: #aaa; font-size: 14px;'><<print $lastName>> ↔️ <<print _npcLastName>></div><div style='color: #9b59b6; font-size: 13px; margin-top: 5px;'>Swap (Value: <<print _nameValue>>)</div></div>">> <<run $playerTradePackage.name.push({type: "lastName", value: $lastName})>> <<run $npcTradePackage.name.push({type: "lastName", value: _npcLastName})>> <<goto "TradeInterface">> <</link>> <<elseif _nameBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Last Name</div> <div style='font-size: 14px;'>🚫 Blocked</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Last Name</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> </div> </div> <!-- JOB SECTION (Always available) --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #17a2b8; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #17a2b8; padding-bottom: 10px;">💼 Job</h2> <p style="color: #aaa; font-size: 15px; margin: 0 0 15px 0;"><em>Selecting a job automatically swaps both sides</em></p> <<set _playerJob = $jobs.length > 0 ? $jobs[0] : "Unemployed">> <<set _npcJob = _npc.jobs.length > 0 ? _npc.jobs[0] : "Unemployed">> <<set _jobAlreadySelected = ($playerTradePackage.job !== null)>> <<set _canTrade = setup.canTradeJob(_playerJob, _npcJob)>> <<set _jobBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.job>> <<if _jobBlocked>> <div style="background: #3a2020; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0; font-weight: bold;">🚫 _npc.name will NEVER trade their job</p> </div> <</if>> <<if _playerJob === "Criminal" && !setup.canTradeCriminalJob()>> <div style='background: #3a2020; border: 2px solid #ff6b6b; padding: 18px; border-radius: 8px; text-align: center;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px; color: #ff6b6b;'>🚫 Cannot Trade Criminal Job</div> <div style='font-size: 14px; color: #ccc;'>You must serve jail time or pay your fine first!</div> </div> <<elseif !_jobAlreadySelected && _canTrade && !_jobBlocked>> <<set _playerJobValue = setup.getTraitValue("job", _playerJob)>> <<set _npcJobValue = setup.getTraitValue("job", _npcJob)>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 18px; border-radius: 8px; cursor: pointer; border: 2px solid #17a2b8; text-align: center;'><div style='font-weight: bold; font-size: 18px; margin-bottom: 5px; color: #17a2b8;'>Trade Jobs</div><div style='color: #aaa; font-size: 14px;'>_playerJob ↔️ _npcJob</div><div style='color: #17a2b8; font-size: 14px; margin-top: 5px;'>Your Value: _playerJobValue | Their Value: _npcJobValue</div></div>">> <<set $playerTradePackage.job = _playerJob>> <<set $npcTradePackage.job = _npcJob>> <<goto "TradeInterface">> <</link>> <<elseif _jobBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 18px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px;'>Trade Jobs</div> <div style='font-size: 14px;'>🚫 They Won't Trade</div> </div> <<elseif _jobAlreadySelected>> <div style='background: #1a1a1a; color: #666; padding: 18px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px;'>Trade Jobs</div> <div style='font-size: 14px;'>Already Selected</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 18px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px;'>Trade Jobs</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> </div> <!-- BIMBO TRAIT SECTION (Only show if current side has Bimbo) --> <<if _currentSideHasBimbo>> <<set _currentPackage = _isPlayerSide ? $playerTradePackage : $npcTradePackage>> <<set _bimboInPackage = _currentPackage.mental.includes("Bimbo")>> <<set _oppositeHasBimbo = _isPlayerSide ? _npcIsBimbo : _playerIsBimbo>> <<set _bimboValue = setup.getTraitValue("mental", "Bimbo")>> <<set _npcWontAcceptBimbo = _isPlayerSide && _npcPrefs && _npcPrefs.wontTradeFor && _npcPrefs.wontTradeFor.mental && _npcPrefs.wontTradeFor.mental.includes("Bimbo")>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff69b4; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ff69b4; padding-bottom: 10px;">💋 Bimbo Trait</h2> <<if !_bimboInPackage && !_oppositeHasBimbo && !_npcWontAcceptBimbo>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid #ff69b4; text-align: center;'><div style='font-weight: bold; font-size: 18px; margin-bottom: 5px; color: #ff69b4;'><<if _isPlayerSide>>Trade Away Bimbo<<else>>Receive Bimbo<</if>></div><div style='color: #aaa; font-size: 14px;'>Value: _bimboValue</div><div style='color: #ff69b4; font-size: 13px; margin-top: 5px;'><<if _isPlayerSide>>Give up being a Bimbo<<else>>Become a Bimbo<</if>></div></div>">> <<if _isPlayerSide>> <<run $playerTradePackage.mental.push("Bimbo")>> <<else>> <<run $npcTradePackage.mental.push("Bimbo")>> <</if>> <<goto "TradeInterface">> <</link>> <<elseif _oppositeHasBimbo>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px;'>Bimbo Trait</div> <div style='font-size: 14px;'>They already have it</div> </div> <<elseif _npcWontAcceptBimbo>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px;'>Bimbo Trait</div> <div style='font-size: 14px;'>🚫 They won't accept this</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 18px; margin-bottom: 5px;'>Bimbo Trait</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> </div> <</if>> <!-- ALL OTHER SECTIONS (Only if NEITHER side has Bimbo) --> <<if !_currentSideHasBimbo>> <!-- BODY PARTS SECTION (Only if NEITHER side has Bimbo) --> <<if !_playerIsBimbo && !_npcIsBimbo>> <!-- Original Body Parts section stays here --> <<set _playerOfferedBodyPartTypes = []>> <<for _bp range $playerTradePackage.bodyParts>> <<run _playerOfferedBodyPartTypes.push(_bp.name)>> <</for>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ff6b6b; padding-bottom: 10px;">🫀 Body Parts</h2> <div style="background: #3a3020; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ffc107; margin: 0; font-weight: bold;">⚠️ Selecting a body part automatically swaps it between both of you</p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 15px;"> <!-- Chest --> <<set _partValue = setup.getTraitValue("bodyPart", "chest", $bodyParts.chest)>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("chest")>> <<set _playerChestSize = $bodyParts.chest>> <<set _npcChestSize = _npc.bodyParts.chest>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.chestSize && _npcPrefs.reluctantToTrade.chestSize.includes(_npcChestSize)>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.chestSize && _npcPrefs.willingToTrade.chestSize.includes(_npcChestSize)>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.chestSize && _npcPrefs.neverTrade.chestSize.includes(_npcChestSize)>> <<set _npcWontAcceptChestSize = _npcPrefs && _npcPrefs.wontTradeFor && _npcPrefs.wontTradeFor.chestSize && _npcPrefs.wontTradeFor.chestSize.includes(_playerChestSize)>> <<if !_alreadySelected && !_npcBlocked && !_npcWontAcceptChestSize && !setup.isBodyPartLockedByTransformation("chest")>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Chest<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>$bodyParts.chest ↔️ _npc.bodyParts.chest</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "chest", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "chest", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked || _npcWontAcceptChestSize>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Chest</div> <<if _npcBlocked>> <div style='font-size: 14px;'>🚫 They won't give up their _npcChestSize chest</div> <<else>> <div style='font-size: 14px;'>🚫 They don't want your _playerChestSize chest</div> <</if>> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Chest</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Butt --> <<set _partValue = setup.getTraitValue("bodyPart", "butt", $bodyParts.butt)>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("butt")>> <<set _playerButtSize = $bodyParts.butt>> <<set _npcButtSize = _npc.bodyParts.butt>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.buttSize && _npcPrefs.reluctantToTrade.buttSize.includes(_npcButtSize)>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.buttSize && _npcPrefs.willingToTrade.buttSize.includes(_npcButtSize)>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.buttSize && _npcPrefs.neverTrade.buttSize.includes(_npcButtSize)>> <<set _npcWontAcceptButtSize = _npcPrefs && _npcPrefs.wontTradeFor && _npcPrefs.wontTradeFor.buttSize && _npcPrefs.wontTradeFor.buttSize.includes(_playerButtSize)>> <<if !_alreadySelected && !_npcBlocked && !_npcWontAcceptButtSize && !setup.isBodyPartLockedByTransformation("butt")>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Butt<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>$bodyParts.butt ↔️ _npc.bodyParts.butt</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "butt", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "butt", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked || _npcWontAcceptButtSize>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Butt</div> <<if _npcBlocked>> <div style='font-size: 14px;'>🚫 They won't give up their _npcButtSize butt</div> <<else>> <div style='font-size: 14px;'>🚫 They don't want your _playerButtSize butt</div> <</if>> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Butt</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Gender --> <<set _partValue = setup.getTraitValue("bodyPart", "gender", "male")>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("gender")>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.bodyParts && _npcPrefs.reluctantToTrade.bodyParts.includes("gender")>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.bodyParts && _npcPrefs.willingToTrade.bodyParts.includes("gender")>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.bodyParts && _npcPrefs.neverTrade.bodyParts.includes("gender")>> <<set _lockedByTransform = setup.isBodyPartLockedByTransformation("gender")>> <<if !_alreadySelected && !_npcBlocked && !_lockedByTransform>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Gender<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>$bodyParts.gender ↔️ _npc.bodyParts.gender</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "gender", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "gender", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Gender</div> <div style='font-size: 14px;'>🚫 Won't Trade</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Gender</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Skin Color --> <<set _partValue = setup.getTraitValue("bodyPart", "skinTone")>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("skinTone")>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.bodyParts && _npcPrefs.reluctantToTrade.bodyParts.includes("skinTone")>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.bodyParts && _npcPrefs.willingToTrade.bodyParts.includes("skinTone")>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.bodyParts && _npcPrefs.neverTrade.bodyParts.includes("skinTone")>> <<set _lockedByTransform = setup.isBodyPartLockedByTransformation("skinTone")>> <<if !_alreadySelected && !_npcBlocked && !_lockedByTransform>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Skin Color<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>$appearance.skinTone ↔️ _npc.appearance.skinTone</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "skinTone", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "skinTone", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Skin Color</div> <div style='font-size: 14px;'>🚫 Won't Trade</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Skin Color</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Hair Color --> <<set _partValue = setup.getTraitValue("bodyPart", "hairColor")>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("hairColor")>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.bodyParts && _npcPrefs.reluctantToTrade.bodyParts.includes("hairColor")>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.bodyParts && _npcPrefs.willingToTrade.bodyParts.includes("hairColor")>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.bodyParts && _npcPrefs.neverTrade.bodyParts.includes("hairColor")>> <<set _lockedByTransform = setup.isBodyPartLockedByTransformation("hairColor")>> <<if !_alreadySelected && !_npcBlocked && !_lockedByTransform>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Hair Color<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>$appearance.hairColor ↔️ _npc.appearance.hairColor</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "hairColor", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "hairColor", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Hair Color</div> <div style='font-size: 14px;'>🚫 Won't Trade</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Hair Color</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Age --> <<set _partValue = setup.getTraitValue("bodyPart", "age")>> <<set _currentValue = $appearance.age || "Adult">> <<set _npcAge = _npc.appearance.age || "Adult">> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("age")>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.bodyParts && _npcPrefs.reluctantToTrade.bodyParts.includes("age")>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.bodyParts && _npcPrefs.willingToTrade.bodyParts.includes("age")>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.bodyParts && _npcPrefs.neverTrade.bodyParts.includes("age")>> <<set _lockedByTransform = setup.isBodyPartLockedByTransformation("age")>> <<if !_alreadySelected && !_npcBlocked && !_lockedByTransform>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Age<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>_currentValue ↔️ _npcAge</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "age", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "age", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Age</div> <div style='font-size: 14px;'>🚫 Won't Trade</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Age</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Hair Length --> <<set _partValue = setup.getTraitValue("bodyPart", "hairLength")>> <<set _currentValue = $appearance.hairLength || "short">> <<if !_npc.appearance.hairLength>> <<set _npc.appearance.hairLength = Math.random() < 0.5 ? "short" : "long">> <<set _hairLengthTrait = _npc.appearance.hairLength === "short" ? "Short Hair" : "Long Hair">> <<if !_npc.physicalTraits.includes(_hairLengthTrait)>> <<run _npc.physicalTraits.push(_hairLengthTrait)>> <</if>> <</if>> <<set _npcHairLength = _npc.appearance.hairLength>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("hairLength")>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.bodyParts && _npcPrefs.reluctantToTrade.bodyParts.includes("hairLength")>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.bodyParts && _npcPrefs.willingToTrade.bodyParts.includes("hairLength")>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.bodyParts && _npcPrefs.neverTrade.bodyParts.includes("hairLength")>> <<if !_alreadySelected && !_npcBlocked>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Hair Length<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>_currentValue ↔️ _npcHairLength</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "hairLength", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "hairLength", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Hair Length</div> <div style='font-size: 14px;'>🚫 Won't Trade</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Hair Length</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> <!-- Genitals --> <<set _partValue = setup.getTraitValue("bodyPart", "genitals", $bodyParts.genitals)>> <<set _alreadySelected = _playerOfferedBodyPartTypes.includes("genitals")>> <<set _playerGenitals = $bodyParts.genitals>> <<set _npcGenitals = _npc.bodyParts.genitals || "penis">> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.bodyParts && _npcPrefs.reluctantToTrade.bodyParts.includes("genitals")>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.bodyParts && _npcPrefs.willingToTrade.bodyParts.includes("genitals")>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.bodyParts && _npcPrefs.neverTrade.bodyParts.includes("genitals")>> <<set _lockedByTransform = setup.isBodyPartLockedByTransformation("genitals")>> <<if !_alreadySelected && !_npcBlocked && !_lockedByTransform>> <<set _borderColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : "#ff6b6b")>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 15px; border-radius: 8px; cursor: pointer; border: 2px solid _borderColor; text-align: center;'><div style='font-weight: bold; font-size: 16px; margin-bottom: 5px; color: _borderColor;'>Genitals<<if _npcWilling>> ✅<<elseif _npcReluctant>> ⚠️<</if>></div><div style='color: #aaa; font-size: 14px;'>_playerGenitals ↔️ _npcGenitals</div><div style='color: _borderColor; font-size: 13px; margin-top: 5px;'>Swap (Value: _partValue)<<if _npcWilling>><br>They're willing!<<elseif _npcReluctant>><br>They're reluctant (+30% cost)<</if>></div></div>">> <<run $playerTradePackage.bodyParts.push({name: "genitals", npc: _npc})>> <<run $npcTradePackage.bodyParts.push({name: "genitals", npc: _npc})>> <<goto "TradeInterface">> <</link>> <<elseif _npcBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Genitals</div> <div style='font-size: 14px;'>🚫 Won't Trade</div> </div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 15px; border-radius: 8px; border: 2px solid #666; text-align: center; opacity: 0.5;'> <div style='font-weight: bold; font-size: 16px; margin-bottom: 5px;'>Genitals</div> <div style='font-size: 14px;'>Already Selected</div> </div> <</if>> </div> </div> <</if>><!-- End body parts check for Bimbo --> <!-- PHYSICAL TRAITS SECTION --> <<set _availablePhysical = _isPlayerSide ? $physicalTraits : _npc.physicalTraits>> <<set _currentPackage = _isPlayerSide ? $playerTradePackage : $npcTradePackage>> <<set _oppositePackage = _isPlayerSide ? $npcTradePackage : $playerTradePackage>> <<set _oppositeTraits = _isPlayerSide ? _npc.physicalTraits : $physicalTraits>> <<set _displayPhysicalTraits = _availablePhysical.filter(function(trait) { return trait !== "Short Hair" && trait !== "Long Hair" && trait !== "Cuntboy" && trait !== "Dickgirl" && trait !== "Cerberus"; })>> <<if _displayPhysicalTraits.length > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #51cf66; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #51cf66; padding-bottom: 10px;">💪 Physical Traits</h2> <div style="display: flex; flex-wrap: wrap; gap: 12px; margin-top: 15px;"> <<for _trait range _displayPhysicalTraits>> <<capture _trait>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <<set _alreadyInPackage = _currentPackage.physical.includes(_trait)>> <<set _oppositeHasTrait = _oppositeTraits.includes(_trait)>> <<set _npcDesires = _npcPrefs && _npcPrefs.desires && _npcPrefs.desires.physical && _npcPrefs.desires.physical.includes(_trait)>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.physical && _npcPrefs.willingToTrade.physical.includes(_trait)>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.physical && _npcPrefs.reluctantToTrade.physical.includes(_trait)>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.physical && _npcPrefs.neverTrade.physical.includes(_trait)>> <<set _npcWontAccept = _npcPrefs && _npcPrefs.wontTradeFor && _npcPrefs.wontTradeFor.physical && _npcPrefs.wontTradeFor.physical.includes(_trait)>> <!-- Check if trait is blocked by player's current transformation --> <<set _transformationBlocked = !_isPlayerSide && setup.isTraitBlockedByTransformation(_trait, "physical")>> <<set _oppositeConflict = setup.getConflictingTrait(_trait, _oppositeTraits)>> <<set _packageConflict = setup.getConflictingTrait(_trait, _currentPackage.physical)>> <<if _isPlayerSide>> <<set _actuallyBlocked = _npcWontAccept>> <<set _blockedMessage = "They don't want this">> <<set _traitColor = _npcDesires ? "#51cf66" : (_traitValue >= 0 ? "#51cf66" : "#ff6b6b")>> <<set _statusIcon = _npcDesires ? "💚" : (_npcWilling ? "✅" : (_npcReluctant ? "⚠️" : (_actuallyBlocked ? "🚫" : "")))>> <<set _statusText = _npcDesires ? "They want this! (+15%)" : (_npcWilling ? "" : (_npcReluctant ? "They're reluctant (+30% cost)" : (_actuallyBlocked ? "Won't accept" : "")))>> <<else>> <<set _actuallyBlocked = _npcBlocked || _transformationBlocked>> <<set _blockedMessage = _transformationBlocked ? "Blocked by transformation" : "They won't give this up">> <<set _traitColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : (_actuallyBlocked ? "#ff6b6b" : "#51cf66"))>> <<set _statusIcon = _npcWilling ? "✅" : (_npcReluctant ? "⚠️" : (_actuallyBlocked ? "🚫" : ""))>> <<set _statusText = _npcWilling ? "They're willing!" : (_npcReluctant ? "They're reluctant (+30% cost)" : (_transformationBlocked ? "Blocked by transformation" : (_actuallyBlocked ? "Won't trade" : "")))>> <</if>> <<if !_alreadyInPackage && !_oppositeHasTrait && !_packageConflict && !_actuallyBlocked>> <<if _isPlayerSide>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 12px 20px; border-radius: 8px; cursor: pointer; border: 2px solid _traitColor; font-weight: 500; font-size: 15px;'>_trait _statusIcon <span style='color: _traitColor; font-size: 13px;'>(<<if _traitValue > 0>>+<</if>>_traitValue)</span><<if _oppositeConflict>> <span style='color: #ffc107; font-size: 12px;'>↔️ _oppositeConflict</span><</if>><<if _statusText>> <div style='color: _traitColor; font-size: 12px; margin-top: 5px;'>_statusText</div><</if>></div>">> <<run $playerTradePackage.physical.push(_trait)>> <<if _oppositeConflict>> <<run $npcTradePackage.physical.push(_oppositeConflict)>> <</if>> <<goto "TradeInterface">> <</link>> <<else>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 12px 20px; border-radius: 8px; cursor: pointer; border: 2px solid _traitColor; font-weight: 500; font-size: 15px;'>_trait _statusIcon <span style='color: _traitColor; font-size: 13px;'>(<<if _traitValue > 0>>+<</if>>_traitValue)</span><<if _oppositeConflict>> <span style='color: #ffc107; font-size: 12px;'>↔️ _oppositeConflict</span><</if>><<if _statusText>> <div style='color: _traitColor; font-size: 12px; margin-top: 5px;'>_statusText</div><</if>></div>">> <<run $npcTradePackage.physical.push(_trait)>> <<if _oppositeConflict>> <<run $playerTradePackage.physical.push(_oppositeConflict)>> <</if>> <<goto "TradeInterface">> <</link>> <</if>> <<elseif _oppositeHasTrait>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait <span style='font-size: 13px;'>(Already Has)</span></div> <<elseif _packageConflict>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait <span style='font-size: 13px;'>(Conflicts with _packageConflict)</span></div> <<elseif _actuallyBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 12px 20px; border-radius: 8px; border: 2px solid #ff6b6b; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait 🚫 <span style='font-size: 13px;'>(_blockedMessage)</span></div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait <span style='font-size: 13px;'>(Selected)</span></div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- MENTAL TRAITS SECTION --> <<set _availableMental = _isPlayerSide ? $mentalTraits.concat() : _npc.mentalTraits>> <<set _oppositeTraitsMental = _isPlayerSide ? _npc.mentalTraits : $mentalTraits>> <<if _isPlayerSide && $characterCreationTrait && !_availableMental.includes($characterCreationTrait)>> <<run _availableMental.push($characterCreationTrait)>> <</if>> <<if _availableMental.length > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #9b59b6; padding-bottom: 10px;">🧠 Mental Traits</h2> <div style="display: flex; flex-wrap: wrap; gap: 12px; margin-top: 15px;"> <<for _trait range _availableMental>> <<if _trait === "Perverted" || _trait === "Gambling Addiction">> <<continue>> <</if>> <<capture _trait>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<set _alreadyInPackage = _currentPackage.mental.includes(_trait)>> <<set _oppositeHasTrait = _oppositeTraitsMental.includes(_trait)>> <<set _npcDesires = _npcPrefs && _npcPrefs.desires && _npcPrefs.desires.mental && _npcPrefs.desires.mental.includes(_trait)>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.mental && _npcPrefs.willingToTrade.mental.includes(_trait)>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.mental && _npcPrefs.reluctantToTrade.mental.includes(_trait)>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.mental && _npcPrefs.neverTrade.mental.includes(_trait)>> <<set _npcWontAccept = _npcPrefs && _npcPrefs.wontTradeFor && _npcPrefs.wontTradeFor.mental && _npcPrefs.wontTradeFor.mental.includes(_trait)>> <!-- Check if trait is blocked by player's current transformation --> <<set _transformationBlocked = !_isPlayerSide && setup.isTraitBlockedByTransformation(_trait, "mental")>> <<set _oppositeConflict = setup.getConflictingTrait(_trait, _oppositeTraitsMental)>> <<set _packageConflict = setup.getConflictingTrait(_trait, _currentPackage.mental)>> <<if _isPlayerSide>> <<set _actuallyBlocked = _npcWontAccept>> <<set _blockedMessage = "They don't want this">> <<set _traitColor = _npcDesires ? "#9b59b6" : (_traitValue >= 0 ? "#9b59b6" : "#ff6b6b")>> <<set _statusIcon = _npcDesires ? "💜" : (_npcWilling ? "✅" : (_npcReluctant ? "⚠️" : (_actuallyBlocked ? "🚫" : "")))>> <<set _statusText = _npcDesires ? "They want this! (+15%)" : (_npcWilling ? "" : (_npcReluctant ? "They're reluctant (+30% cost)" : (_actuallyBlocked ? "Won't accept" : "")))>> <<else>> <<set _actuallyBlocked = _npcBlocked || _transformationBlocked>> <<set _blockedMessage = _transformationBlocked ? "Blocked by transformation" : "They won't give this up">> <<set _traitColor = _npcWilling ? "#9b59b6" : (_npcReluctant ? "#ffc107" : (_actuallyBlocked ? "#ff6b6b" : "#9b59b6"))>> <<set _statusIcon = _npcWilling ? "✅" : (_npcReluctant ? "⚠️" : (_actuallyBlocked ? "🚫" : ""))>> <<set _statusText = _npcWilling ? "They're willing!" : (_npcReluctant ? "They're reluctant (+30% cost)" : (_transformationBlocked ? "Blocked by transformation" : (_actuallyBlocked ? "Won't trade" : "")))>> <</if>> <<if !_alreadyInPackage && !_oppositeHasTrait && !_packageConflict && !_actuallyBlocked>> <<if _isPlayerSide>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 12px 20px; border-radius: 8px; cursor: pointer; border: 2px solid _traitColor; font-weight: 500; font-size: 15px;'>_trait _statusIcon <span style='color: _traitColor; font-size: 13px;'>(<<if _traitValue > 0>>+<</if>>_traitValue)</span><<if _oppositeConflict>> <span style='color: #ffc107; font-size: 12px;'>↔️ _oppositeConflict</span><</if>><<if _statusText>> <div style='color: _traitColor; font-size: 12px; margin-top: 5px;'>_statusText</div><</if>></div>">> <<run $playerTradePackage.mental.push(_trait)>> <<if _oppositeConflict>> <<run $npcTradePackage.mental.push(_oppositeConflict)>> <</if>> <<goto "TradeInterface">> <</link>> <<else>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 12px 20px; border-radius: 8px; cursor: pointer; border: 2px solid _traitColor; font-weight: 500; font-size: 15px;'>_trait _statusIcon <span style='color: _traitColor; font-size: 13px;'>(<<if _traitValue > 0>>+<</if>>_traitValue)</span><<if _oppositeConflict>> <span style='color: #ffc107; font-size: 12px;'>↔️ _oppositeConflict</span><</if>><<if _statusText>> <div style='color: _traitColor; font-size: 12px; margin-top: 5px;'>_statusText</div><</if>></div>">> <<run $npcTradePackage.mental.push(_trait)>> <<if _oppositeConflict>> <<run $playerTradePackage.mental.push(_oppositeConflict)>> <</if>> <<goto "TradeInterface">> <</link>> <</if>> <<elseif _oppositeHasTrait>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait <span style='font-size: 13px;'>(Already Has)</span></div> <<elseif _packageConflict>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait <span style='font-size: 13px;'>(Conflicts with _packageConflict)</span></div> <<elseif _actuallyBlocked>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 12px 20px; border-radius: 8px; border: 2px solid #ff6b6b; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait 🚫 <span style='font-size: 13px;'>(_blockedMessage)</span></div> <<else>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_trait <span style='font-size: 13px;'>(Selected)</span></div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- SKILLS SECTION --> <<set _availableSkills = _isPlayerSide ? $skills : _npc.skills>> <<set _oppositeSkills = _isPlayerSide ? _npc.skills : $skills>> <<if _availableSkills.length > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffc107; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ffc107; padding-bottom: 10px;">🎯 Skills</h2> <div style="display: flex; flex-wrap: wrap; gap: 12px; margin-top: 15px;"> <<for _skill range _availableSkills>> <<capture _skill>> <<set _skillValue = setup.getTraitValue("skill", _skill)>> <<set _alreadyInPackage = _currentPackage.skills.includes(_skill)>> <<set _oppositeHasSkill = _oppositeSkills.includes(_skill)>> <<set _npcDesires = _npcPrefs && _npcPrefs.desires && _npcPrefs.desires.skills && _npcPrefs.desires.skills.includes(_skill)>> <<set _npcWilling = _npcPrefs && _npcPrefs.willingToTrade && _npcPrefs.willingToTrade.skills && _npcPrefs.willingToTrade.skills.includes(_skill)>> <<set _npcReluctant = _npcPrefs && _npcPrefs.reluctantToTrade && _npcPrefs.reluctantToTrade.skills && _npcPrefs.reluctantToTrade.skills.includes(_skill)>> <<set _npcBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.skills && _npcPrefs.neverTrade.skills.includes(_skill)>> <<set _npcWontAccept = _npcPrefs && _npcPrefs.wontTradeFor && _npcPrefs.wontTradeFor.skills && _npcPrefs.wontTradeFor.skills.includes(_skill)>> <!-- Soul trait can never be traded --> <<set _isSoulTrait = _skill === "Soul">> <<if _isSoulTrait>> <<set _actuallyBlocked = true>> <<set _blockedMessage = "Bound to your soul">> <<set _traitColor = "#9b59b6">> <<set _statusIcon = "🔮">> <<set _statusText = "Cannot be traded">> <<elseif _isPlayerSide>> <<set _actuallyBlocked = _npcWontAccept>> <<set _blockedMessage = "They don't want this">> <<set _traitColor = _npcDesires ? "#ffc107" : "#ffc107">> <<set _statusIcon = _npcDesires ? "💛" : (_npcWilling ? "✅" : (_npcReluctant ? "⚠️" : (_actuallyBlocked ? "🚫" : "")))>> <<set _statusText = _npcDesires ? "They want this! (+30%)" : (_npcWilling ? "" : (_npcReluctant ? "They're reluctant (+30% cost)" : (_actuallyBlocked ? "Won't accept" : "")))>> <<else>> <<set _actuallyBlocked = _npcBlocked>> <<set _blockedMessage = "They won't give this up">> <<set _traitColor = _npcWilling ? "#51cf66" : (_npcReluctant ? "#ffc107" : (_actuallyBlocked ? "#ff6b6b" : "#ffc107"))>> <<set _statusIcon = _npcWilling ? "✅" : (_npcReluctant ? "⚠️" : (_actuallyBlocked ? "🚫" : ""))>> <<set _statusText = _npcWilling ? "They're willing!" : (_npcReluctant ? "They're reluctant (+30% cost)" : (_actuallyBlocked ? "Won't trade" : ""))>> <</if>> <<if !_alreadyInPackage && !_oppositeHasSkill && !_actuallyBlocked>> <<if _isPlayerSide>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 12px 20px; border-radius: 8px; cursor: pointer; border: 2px solid _traitColor; font-weight: 500; font-size: 15px;'>_skill _statusIcon <span style='color: _traitColor; font-size: 13px;'>(+_skillValue)</span><<if _statusText>> <div style='color: _traitColor; font-size: 12px; margin-top: 5px;'>_statusText</div><</if>></div>">> <<run $playerTradePackage.skills.push(_skill)>> <<goto "TradeInterface">> <</link>> <<else>> <<link "<div style='background: #1a1a1a; color: #ccc; padding: 12px 20px; border-radius: 8px; cursor: pointer; border: 2px solid _traitColor; font-weight: 500; font-size: 15px;'>_skill _statusIcon <span style='color: _traitColor; font-size: 13px;'>(+_skillValue)</span><<if _statusText>> <div style='color: _traitColor; font-size: 12px; margin-top: 5px;'>_statusText</div><</if>></div>">> <<run $npcTradePackage.skills.push(_skill)>> <<goto "TradeInterface">> <</link>> <</if>> <<elseif _oppositeHasSkill>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_skill <span style='font-size: 13px;'>(Already Has)</span></div> <<elseif _actuallyBlocked>> <<if _isPlayerSide && _npcWontAccept>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 12px 20px; border-radius: 8px; border: 2px solid #ff6b6b; font-weight: 500; font-size: 15px; opacity: 0.5;'>_skill 🚫 <span style='font-size: 13px;'>(They don't want this)</span></div> <<else>> <div style='background: #1a1a1a; color: #ff6b6b; padding: 12px 20px; border-radius: 8px; border: 2px solid #ff6b6b; font-weight: 500; font-size: 15px; opacity: 0.5;'>_skill 🚫 <span style='font-size: 13px;'>(They won't give this up)</span></div> <</if>> <<else>> <div style='background: #1a1a1a; color: #666; padding: 12px 20px; border-radius: 8px; border: 2px solid #666; font-weight: 500; font-size: 15px; opacity: 0.5;'>_skill <span style='font-size: 13px;'>(Selected)</span></div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <</if>><!-- End !_currentSideHasBimbo conditional --> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Trade Interface</div>">> <<goto "TradeInterface">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Safety check: ensure tradeResult exists --> <<if !$tradeResult>> <div style="background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 2px solid #dc3545;"> <h1 style="color: white; margin: 0 0 10px 0; font-size: 36px;">❌ Error</h1> <p style="color: white; margin: 0; font-size: 18px;">No trade result found</p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Go Back</div>">> <<goto $lastLocation>> <</link>> </div> <<elseif $tradeResult.success>> <!-- Unlock first trade achievement --> <<run setup.achievements.unlock("first_trade")>> <!-- Check for name trading achievement --> <<if $tradeResult.playerReceived.name && $tradeResult.playerReceived.name.length > 0>> <<run setup.achievements.unlock("trade_name_change")>> <</if>> <!-- Check for Lucky trait achievement --> <<if $tradeResult.playerReceived.mental && $tradeResult.playerReceived.mental.includes("Lucky")>> <<run setup.achievements.unlock("lucky_trait")>> <</if>> <!-- Check for Bimbo trait achievement --> <<if $tradeResult.playerReceived.mental && $tradeResult.playerReceived.mental.includes("Bimbo")>> <<run setup.achievements.unlock("become_bimbo")>> <</if>> <!-- Check for Mayor job achievement --> <<if $tradeResult.playerReceived.job && $tradeResult.playerReceived.job === "City Mayor">> <<run setup.achievements.unlock("become_mayor")>> <</if>> <!-- Check for Cuntboy, Dickgirl, or Futanari trait achievement (special gender trait) --> <<if $physicalTraits.includes("Cuntboy") || $physicalTraits.includes("Dickgirl") || $physicalTraits.includes("Futanari")>> <<run setup.achievements.unlock("special_gender_trait")>> <</if>> <!-- Check for gigantic chest AND butt WITHOUT bimbo trait achievement --> <<if $bodyParts.chest === "gigantic" && $bodyParts.butt === "gigantic">> <<if !$mentalTraits || !$mentalTraits.includes("Bimbo")>> <<run setup.achievements.unlock("gigantic_no_bimbo")>> <</if>> <</if>> <!-- Check for high value trait (100+) achievement --> <<set _receivedHighValue = false>> <<if $tradeResult.playerReceived.physical && $tradeResult.playerReceived.physical.length > 0>> <<for _trait range $tradeResult.playerReceived.physical>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <<if _traitValue >= 100>> <<set _receivedHighValue = true>> <</if>> <</for>> <</if>> <<if $tradeResult.playerReceived.mental && $tradeResult.playerReceived.mental.length > 0>> <<for _trait range $tradeResult.playerReceived.mental>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<if _traitValue >= 100>> <<set _receivedHighValue = true>> <</if>> <</for>> <</if>> <<if $tradeResult.playerReceived.skills && $tradeResult.playerReceived.skills.length > 0>> <<for _trait range $tradeResult.playerReceived.skills>> <<set _traitValue = setup.getTraitValue("skill", _trait)>> <<if _traitValue >= 100>> <<set _receivedHighValue = true>> <</if>> <</for>> <</if>> <<if $tradeResult.playerReceived.job>> <<set _jobValue = setup.getTraitValue("job", $tradeResult.playerReceived.job)>> <<if _jobValue >= 100>> <<set _receivedHighValue = true>> <</if>> <</if>> <<if _receivedHighValue>> <<run setup.achievements.unlock("valuable_trait_trade")>> <</if>> <!-- Check for low success chance win (15% or lower) --> <<if $tradeResult.successChance && $tradeResult.successChance <= 15>> <<run setup.achievements.unlock("low_odds_success")>> <</if>> <!-- SUCCESS HEADER --> <div style="background: linear-gradient(135deg, #28a745 0%, #20c997 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 2px solid #28a745;"> <h1 style="color: white; margin: 0 0 10px 0; font-size: 36px;">✅ Trade Successful!</h1> <p style="color: white; margin: 0; font-size: 18px;">The trade with _npc.name was successful</p> </div> <!-- Check for Bimbo trait changes --> <<set _playerGaveBimbo = $tradeResult.playerGave.mental && $tradeResult.playerGave.mental.includes("Bimbo")>> <<set _playerReceivedBimbo = $tradeResult.playerReceived.mental && $tradeResult.playerReceived.mental.includes("Bimbo")>> <!-- Bimbo Transformation Section (if applicable) --> <<if _playerReceivedBimbo>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff69b4; margin-top: 0; font-size: 24px; border-bottom: 3px solid #ff69b4; padding-bottom: 10px;">💋 Bimbo Transformation</h2> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff69b4;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getBimboTransformationText(true)>> </p> </div> </div> <<elseif _playerGaveBimbo>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #17a2b8; margin-top: 0; font-size: 24px; border-bottom: 3px solid #17a2b8; padding-bottom: 10px;">🧠 Regaining Clarity</h2> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #17a2b8;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getBimboTransformationText(false)>> </p> </div> </div> <</if>> <!-- NPC's Transformation Section --> <<set _npcTransformationDesc = setup.generateNPCCompleteTransformation(_npc, $tradeResult)>> <<if _npcTransformationDesc>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffc107; margin-top: 0; font-size: 24px; border-bottom: 3px solid #ffc107; padding-bottom: 10px;">🔄 _npc.name's Transformation</h2> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ffc107;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print _npcTransformationDesc>> </p> </div> </div> <</if>> <!-- What You Gave --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #dc3545; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #dc3545; margin-top: 0; font-size: 24px; border-bottom: 3px solid #dc3545; padding-bottom: 10px;">📤 What You Gave</h2> <<if $tradeResult.playerGave.name && $tradeResult.playerGave.name.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">👤 Name:</strong> <<for _item range $tradeResult.playerGave.name>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #9b59b6;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if _item.type === "firstName">>First Name: _item.value<<else>>Last Name: _item.value<</if>> </span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerGave.physical && $tradeResult.playerGave.physical.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">💪 Physical Traits:</strong> <<for _trait range $tradeResult.playerGave.physical>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #28a745;"> <span style="color: #fff; font-size: 16px; font-weight: 500;">_trait</span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerGave.mental && $tradeResult.playerGave.mental.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">🧠 Mental Traits:</strong> <<for _trait range $tradeResult.playerGave.mental>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #764ba2;"> <span style="color: #fff; font-size: 16px; font-weight: 500;">_trait</span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerGave.skills && $tradeResult.playerGave.skills.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">🎯 Skills:</strong> <<for _skill range $tradeResult.playerGave.skills>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #ffc107;"> <span style="color: #fff; font-size: 16px; font-weight: 500;">_skill</span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerGave.bodyParts && $tradeResult.playerGave.bodyParts.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">🫀 Body Parts:</strong> <<for _part range $tradeResult.playerGave.bodyParts>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #dc3545;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if _part.name === "chest">>Chest: _part.value <<elseif _part.name === "butt">>Butt: _part.value <<elseif _part.name === "gender">>Gender: _part.value <<elseif _part.name === "skinTone">>Skin Color: _part.value <<elseif _part.name === "hairColor">>Hair Color: _part.value <<elseif _part.name === "hairLength">>Hair Length: <<print _part.value ? _part.value.toUpperFirst() : "Short">> <<elseif _part.name === "age">>Age: _part.value <<elseif _part.name === "genitals">>Genitals: _part.value <</if>> </span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerGave.job>> <div style="margin-bottom: 0;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">💼 Job:</strong> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #17a2b8;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if $tradeResult.playerGave.job === "Unemployed">> <span style="color: #dc3545;">Unemployed</span> <<else>> $tradeResult.playerGave.job <</if>> </span> </div> </div> <</if>> </div> <!-- What You Received --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #28a745; margin-top: 0; font-size: 24px; border-bottom: 3px solid #28a745; padding-bottom: 10px;">📥 What You Received</h2> <<if $tradeResult.playerReceived.name && $tradeResult.playerReceived.name.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">👤 Name:</strong> <<for _item range $tradeResult.playerReceived.name>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #9b59b6;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if _item.type === "firstName">>First Name: _item.value<<else>>Last Name: _item.value<</if>> </span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerReceived.physical && $tradeResult.playerReceived.physical.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">💪 Physical Traits:</strong> <<for _trait range $tradeResult.playerReceived.physical>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #28a745;"> <span style="color: #fff; font-size: 16px; font-weight: 500;">_trait</span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerReceived.mental && $tradeResult.playerReceived.mental.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">🧠 Mental Traits:</strong> <<for _trait range $tradeResult.playerReceived.mental>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #764ba2;"> <span style="color: #fff; font-size: 16px; font-weight: 500;">_trait</span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerReceived.skills && $tradeResult.playerReceived.skills.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">🎯 Skills:</strong> <<for _skill range $tradeResult.playerReceived.skills>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #ffc107;"> <span style="color: #fff; font-size: 16px; font-weight: 500;">_skill</span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerReceived.bodyParts && $tradeResult.playerReceived.bodyParts.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">🫀 Body Parts:</strong> <<for _part range $tradeResult.playerReceived.bodyParts>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #dc3545;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if _part.name === "chest">>Chest: _part.value <<elseif _part.name === "butt">>Butt: _part.value <<elseif _part.name === "gender">>Gender: _part.value <<elseif _part.name === "skinTone">>Skin Color: _part.value <<elseif _part.name === "hairColor">>Hair Color: _part.value <<elseif _part.name === "hairLength">>Hair Length: <<print _part.value ? _part.value.toUpperFirst() : "Short">> <<elseif _part.name === "age">>Age: _part.value <<elseif _part.name === "genitals">>Genitals: _part.value <</if>> </span> </div> <</for>> </div> <</if>> <<if $tradeResult.playerReceived.job>> <div style="margin-bottom: 0;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;">💼 Job:</strong> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #17a2b8;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if $tradeResult.playerReceived.job === "Unemployed">> <span style="color: #dc3545;">Unemployed</span> <<else>> $tradeResult.playerReceived.job <</if>> </span> </div> </div> <</if>> <<if $tradeResult.npcReceived.job && $tradingWithNPC>> <div style="margin-bottom: 0; margin-top: 15px;"> <strong style="color: #ccc; font-size: 18px; display: block; margin-bottom: 10px;"><<print $tradingWithNPC.name>>'s New Job:</strong> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #17a2b8;"> <span style="color: #fff; font-size: 16px; font-weight: 500;"> <<if $tradeResult.npcReceived.job === "Unemployed">><span style="color: #dc3545;">Unemployed</span><<else>><<print $tradeResult.npcReceived.job>><</if>> </span> </div> </div> <</if>> </div> <!-- TRANSFORMATION DESCRIPTIONS SECTION --> <<if !_playerReceivedBimbo && !_playerGaveBimbo>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin-top: 0; font-size: 24px; border-bottom: 3px solid #ff6b6b; padding-bottom: 10px;">🔄 Transformation</h2> <!-- Body Part Transformations --> <<if $tradeResult.playerReceived.bodyParts && $tradeResult.playerReceived.bodyParts.length > 0>> <<for _part range $tradeResult.playerReceived.bodyParts>> <<if _part.name === "chest">> <<set _oldSize = $tradeResult.playerGave.bodyParts.find(p => p.name === "chest").value>> <<set _newSize = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff6b6b;"> <<print setup.getChestTransformationText(_oldSize, _newSize)>> </div> <</if>> <<if _part.name === "butt">> <<set _oldSize = $tradeResult.playerGave.bodyParts.find(p => p.name === "butt").value>> <<set _newSize = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff6b6b;"> <<print setup.getButtTransformationText(_oldSize, _newSize)>> </div> <</if>> <<if _part.name === "gender">> <<set _oldGender = $tradeResult.playerGave.bodyParts.find(p => p.name === "gender").value>> <<set _newGender = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #FFD700;"> <<print setup.getGenderTransformationText(_oldGender, _newGender)>> </div> <</if>> <<if _part.name === "genitals">> <<set _oldGenitals = $tradeResult.playerGave.bodyParts.find(p => p.name === "genitals").value>> <<set _newGenitals = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #9370DB;"> <<print setup.getGenitalTransformationText(_oldGenitals, _newGenitals)>> </div> <!-- Check for special trait acquisition --> <<if $physicalTraits.includes("Cuntboy")>> <div style="background: #3a2030; border: 2px solid #9b59b6; padding: 15px; margin: 15px 0; border-radius: 8px;"> <p style="color: #9b59b6; margin: 0; font-weight: bold; font-size: 16px;"> ✨ You've gained the "Cuntboy" trait - a male with a vagina! </p> </div> <<elseif $physicalTraits.includes("Dickgirl")>> <div style="background: #3a2030; border: 2px solid #9b59b6; padding: 15px; margin: 15px 0; border-radius: 8px;"> <p style="color: #9b59b6; margin: 0; font-weight: bold; font-size: 16px;"> ✨ You've gained the "Dickgirl" trait - a female with a penis! </p> </div> <<elseif $physicalTraits.includes("Futanari")>> <div style="background: #3a2030; border: 2px solid #e84393; padding: 15px; margin: 15px 0; border-radius: 8px;"> <p style="color: #e84393; margin: 0; font-weight: bold; font-size: 16px;"> ✨ You've gained the "<<print setup.getFutaDisplayName()>>" trait - you have both male and female genitalia! </p> <p style="color: #ccc; margin: 10px 0 0 0; font-size: 14px; line-height: 1.6;"> <<print setup.getFutaFlavorText("post_swap_gain")>> </p> </div> <</if>> <</if>> <<if _part.name === "age">> <<set _oldAge = $tradeResult.playerGave.bodyParts.find(p => p.name === "age").value>> <<set _newAge = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #C0C0C0;"> <<print setup.getAgeTransformationText(_oldAge, _newAge)>> </div> <</if>> <<if _part.name === "hairColor">> <<set _oldColor = $tradeResult.playerGave.bodyParts.find(p => p.name === "hairColor").value>> <<set _newColor = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff6b6b;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getHairColorTransformationText(_oldColor, _newColor)>> </p> </div> <</if>> <<if _part.name === "hairLength">> <<set _oldLength = $tradeResult.playerGave.bodyParts.find(p => p.name === "hairLength").value>> <<set _newLength = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff6b6b;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getHairLengthTransformationText(_oldLength, _newLength)>> </p> </div> <</if>> <<if _part.name === "skinTone">> <<set _oldTone = $tradeResult.playerGave.bodyParts.find(p => p.name === "skinTone").value>> <<set _newTone = _part.value>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff6b6b;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSkinToneTransformationText(_oldTone, _newTone)>> </p> </div> <</if>> <</for>> <</if>> <!-- Physical Trait Changes --> <<if $tradeResult.playerReceived.physical && $tradeResult.playerReceived.physical.length > 0>> <<for _trait range $tradeResult.playerReceived.physical>> <!-- Check for mutually exclusive swap --> <<set _oldTrait = null>> <<if $tradeResult.playerGave.physical && $tradeResult.playerGave.physical.length > 0>> <<for _gaveTrait range $tradeResult.playerGave.physical>> <<if setup.getConflictingTrait(_trait, [_gaveTrait]) === _gaveTrait>> <<set _oldTrait = _gaveTrait>> <</if>> <</for>> <</if>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #28a745;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _oldTrait>> <<print setup.getMutuallyExclusiveSwapText(_oldTrait, _trait)>> <<else>> <<print setup.getPhysicalTraitChangeText(_trait, true)>> <</if>> </p> </div> <!-- Special transformations --> <<if _trait === "Were-Creature">> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ffa500;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getWereCreatureTransformationText(true, "wolf")>> </p> </div> <<elseif _trait === "Definitely not a Vampire">> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #8b0000;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getVampireTransformationText(true)>> </p> </div> <<elseif _trait === "Sunfish">> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #4169e1;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSunfishTransformationText(true)>> </p> </div> <</if>> <</for>> <</if>> <!-- Mental Trait Changes --> <<if $tradeResult.playerReceived.mental && $tradeResult.playerReceived.mental.length > 0>> <<for _trait range $tradeResult.playerReceived.mental>> <!-- Check for mutually exclusive swap --> <<set _oldTrait = null>> <<if $tradeResult.playerGave.mental && $tradeResult.playerGave.mental.length > 0>> <<for _gaveTrait range $tradeResult.playerGave.mental>> <<if setup.getConflictingTrait(_trait, [_gaveTrait]) === _gaveTrait>> <<set _oldTrait = _gaveTrait>> <</if>> <</for>> <</if>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #764ba2;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _oldTrait>> <<print setup.getMutuallyExclusiveSwapText(_oldTrait, _trait)>> <<else>> <<print setup.getMentalTraitChangeText(_trait, true)>> <</if>> </p> </div> <</for>> <</if>> <!-- Skill Gains --> <<if $tradeResult.playerReceived.skills && $tradeResult.playerReceived.skills.length > 0>> <<for _skill range $tradeResult.playerReceived.skills>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ffc107;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSkillGainText(_skill)>> </p> </div> <</for>> <</if>> <!-- Job Knowledge --> <<if $tradeResult.playerReceived.job>> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #17a2b8;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getJobKnowledgeText($tradeResult.playerReceived.job)>> </p> </div> <</if>> </div> <</if>> <!-- Relationship Change from Trade --> <<set _tradeDisplayPts = $tradeResult.relationshipChange>> <<set _tradeHasCupid = $physicalTraits && $physicalTraits.includes("Cupid") && $tradeResult.relationshipChange > 0>> <<set _tradeHasWeresheep = $physicalTraits && $physicalTraits.includes("Weresheep") && $tradeResult.relationshipChange > 0>> <<if _tradeHasCupid>><<set _tradeDisplayPts = _tradeDisplayPts * 4>><</if>> <<if _tradeHasWeresheep>><<set _tradeDisplayPts = _tradeDisplayPts * 2>><</if>> <<if $tradeResult.relationshipChange > 0>> <div style="background: #2a4a2a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; margin-bottom: 25px; text-align: center;"> <span style="color: #51cf66; font-weight: bold; font-size: 16px;"> 💚 Trade completed! Relationship improved! (+<<print _tradeDisplayPts>> points) <<if _tradeHasCupid>> <span style="color: #ff69b4;">(💘 4x Cupid!)</span> <</if>> <<if _tradeHasWeresheep>> <span style="color: #f0e6ff;">(🐑 2x Weresheep!)</span> <</if>> <<if $tradeResult.hasArtifactBonus>> <span style="color: #e91e63;">(💖 4x Artifact!)</span> <</if>> </span> </div> <<elseif $tradeResult.relationshipChange < 0>> <div style="background: #2a4a2a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 25px; text-align: center;"> <span style="color: #ff6b6b; font-weight: bold; font-size: 16px;"> 💔 Trade completed! Relationship decreased! (<<print $tradeResult.relationshipChange>> points) </span> </div> <<else>> <div style="background: #2a4a2a; border: 2px solid #888; padding: 15px; border-radius: 8px; margin-bottom: 25px; text-align: center;"> <span style="color: #ccc; font-weight: bold; font-size: 16px;"> 💚 Trade completed! No relationship change </span> </div> <</if>> <<else>> <!-- Check for high success chance failure (85% or higher) --> <<if $tradeResult.successChance && $tradeResult.successChance >= 85>> <<run setup.achievements.unlock("high_odds_failure")>> <</if>> <!-- FAILURE HEADER --> <div style="background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 2px solid #dc3545;"> <h1 style="color: white; margin: 0 0 10px 0; font-size: 36px;">❌ Trade Failed!</h1> <p style="color: white; margin: 0; font-size: 18px;">_npc.name rejected your offer</p> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="text-align: center;"> <h2 style="color: #ffc107; margin-top: 0; font-size: 24px;">⚠️ What Happened?</h2> <p style="color: #ccc; font-size: 16px; line-height: 1.6; margin: 20px 0;"> You failed to trade with _npc.name. You've now lost your chance to trade with them today. </p> <p style="color: #aaa; font-size: 15px; font-style: italic; margin: 20px 0;"> 💡 <strong>Tip:</strong> Offer more value next time to increase your chances of success. You can't attempt another trade with _npc.name until tomorrow. </p> <div style="background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; margin-top: 20px;"> <p style="color: #ffc107; margin: 0; font-weight: bold;"> ⏰ Trades Remaining Today: $tradesRemainingToday / <<print 5 + ($bonusDailyTrades || 0)>> </p> </div> </div> </div> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Continue</div>">> <<set $lastTradedNPC = _npc>> <<set $tradingWithNPC = $lastTradedNPC>> <<set $playerTradePackage = null>> <<set $npcTradePackage = null>> <<goto "NPCInteraction">> <</link>> </div> </div> <</nobr>>
:: StoryInit <<silently>> /* Clean up stale data from old saves (memory optimization) */ <<if $tradeHistory !== undefined>><<run delete State.variables.tradeHistory>><</if>> <<if $stolenTraits !== undefined>><<run delete State.variables.stolenTraits>><</if>> <<run delete State.variables.activeGameIntervals>> <<run delete State.variables.activeGameTimeouts>> <<run delete State.variables.skillBonuses>> <<if $bodyPartImages !== undefined>> <<run (function() { var v = State.variables; var cats = ['chest', 'butt', 'hair']; for (var i = 0; i < cats.length; i++) { var cat = cats[i]; if (v.bodyPartImages[cat]) { if (!setup.bodyPartImages[cat]) setup.bodyPartImages[cat] = {}; for (var key in v.bodyPartImages[cat]) { if (v.bodyPartImages[cat][key]) { setup.bodyPartImages[cat][key] = v.bodyPartImages[cat][key]; } } } } delete v.bodyPartImages; })()>> <</if>> /* Migrate painting image data from save state to localStorage */ <<run (function() { var v = State.variables; if (v.playerPaintings) { for (var i = 0; i < v.playerPaintings.length; i++) { var p = v.playerPaintings[i]; if (p.imageData && p.imageData.indexOf('data:') === 0) { setup.paintingStorage.save(p.id, p.imageData); delete p.imageData; } } } if (v.roomPaintings) { for (var room in v.roomPaintings) { var rp = v.roomPaintings[room]; if (rp && rp.imageData && rp.imageData.indexOf('data:') === 0) { setup.paintingStorage.save(rp.id, rp.imageData); delete rp.imageData; } } } })()>> <<set $relationships = {}>> <<set $dayCount = $dayNumber>> /* Default compact trade UI to enabled for new games */ <<if typeof $compactTradeUI === "undefined">> <<set $compactTradeUI = true>> <</if>> /* Default compact NPC menu to enabled for new games */ <<if typeof $compactNPCMenu === "undefined">> <<set $compactNPCMenu = true>> <</if>> /* Player notes (inventory tab) */ <<if typeof $notes === "undefined">> <<set $notes = []>> <</if>> <<if typeof $noteFormTitle === "undefined">> <<set $noteFormTitle = "">> <</if>> <<if typeof $noteFormBody === "undefined">> <<set $noteFormBody = "">> <</if>> <<set $imageSettings = { imagesEnabled: true, locationImagesEnabled: true, eroticImagesEnabled: true, /* Erotic imagery (Secretary, Brothel, etc.) - ON by default */ npcImagesEnabled: true, /* NPC character images - ON by default */ customImages: { face: "", chest: "", butt: "" } }>> <<if State.variables.imageSettings && State.variables.imageSettings.secretaryImagesEnabled !== undefined>> <<set $imageSettings.eroticImagesEnabled = $imageSettings.secretaryImagesEnabled>> <<run delete $imageSettings.secretaryImagesEnabled>> <</if>> /* ---------------------------------- */ /* --- MALL HOURS FUNCTION --- */ /* ---------------------------------- */ <<set setup.isMallOpen = function() { var minutes = State.variables.timeInMinutes; var hour = Math.floor(minutes / 60) % 24; /* Mall is open from 8am (hour 8) to 9pm (hour 21) */ return (hour >= 8 && hour < 21); }>> /* ---------------------------------- */ /* --- HOME SYSTEM SETUP DATA --- */ /* ---------------------------------- */ /* Wall Paint Colors and Prices */ <<set setup.wallColors = { "Default Gray": "#2a2a2a", "Warm Cream": "#f5f0e6", "Ocean Blue": "#1e4d6b", "Forest Green": "#2d4a3e", "Soft Lavender": "#9b8aa3", "Sunset Orange": "#8b4513", "Midnight Purple": "#2d1b4e", "Rose Pink": "#8b5a6b", "Charcoal": "#1a1a1a", "Sky Blue": "#4a7c9b" }>> <<set setup.paintPrices = { "Default Gray": 0, "Warm Cream": 50, "Ocean Blue": 75, "Forest Green": 75, "Soft Lavender": 100, "Sunset Orange": 100, "Midnight Purple": 125, "Rose Pink": 125, "Charcoal": 50, "Sky Blue": 100 }>> /* Grocery Ingredients */ <<set setup.ingredients = { eggs: {name: "Eggs", price: 5, unit: "dozen"}, milk: {name: "Milk", price: 4, unit: "gallon"}, bread: {name: "Bread", price: 3, unit: "loaf"}, butter: {name: "Butter", price: 5, unit: "pack"}, cheese: {name: "Cheese", price: 7, unit: "block"}, chicken: {name: "Chicken Breast", price: 12, unit: "pack"}, beef: {name: "Ground Beef", price: 15, unit: "lb"}, rice: {name: "Rice", price: 8, unit: "bag"}, pasta: {name: "Pasta", price: 3, unit: "box"}, vegetables: {name: "Mixed Vegetables", price: 6, unit: "bag"}, fruit: {name: "Fresh Fruit", price: 8, unit: "bag"}, spices: {name: "Spice Set", price: 15, unit: "set"} }>> /* Cooking Recipes */ <<set setup.recipes = { scrambledEggs: { name: "Scrambled Eggs", ingredients: {eggs: 1, butter: 1}, ingredientCost: 5, buffDuration: 360, time: 15, requiresCooking: false, buffId: "food_morning_boost" }, grilledCheese: { name: "Grilled Cheese", ingredients: {bread: 1, cheese: 1, butter: 1}, ingredientCost: 8, buffDuration: 480, time: 20, requiresCooking: false, buffId: "food_comfort" }, chickenStirFry: { name: "Chicken Stir Fry", ingredients: {chicken: 1, vegetables: 1, rice: 1}, ingredientCost: 15, buffDuration: 720, time: 45, requiresCooking: true, buffId: "food_well_fed" }, pastaAlfredo: { name: "Pasta Alfredo", ingredients: {pasta: 1, butter: 1, cheese: 1, chicken: 1}, ingredientCost: 18, buffDuration: 600, time: 40, requiresCooking: true, buffId: "food_treasure_hunter" }, beefBurger: { name: "Homemade Burger", ingredients: {beef: 1, bread: 1, vegetables: 1, cheese: 1}, ingredientCost: 20, buffDuration: 720, time: 35, requiresCooking: true, buffId: "food_hearty_meal" }, fruitSmoothie: { name: "Fruit Smoothie", ingredients: {fruit: 1, milk: 1}, ingredientCost: 6, buffDuration: 360, time: 10, requiresCooking: false, buffId: "food_social_glow" } }>> /* Food Buffs - Applied when eating cooked food from inventory */ <<set setup.foodBuffs = { food_morning_boost: { name: "Morning Boost", description: "+$2-5 from all money sources", icon: "🌅", effect: "money_bonus", bonusMin: 2, bonusMax: 5 }, food_comfort: { name: "Comfort Food", description: "+10% Trading bonus", icon: "🧀", effect: "trading_bonus", tradingBonus: 0.10 }, food_social_glow: { name: "Social Glow", description: "+1 relationship points per daily talk", icon: "✨", effect: "relationship_bonus", relationshipBonus: 1 }, food_well_fed: { name: "Well Fed", description: "+15% Trading bonus", icon: "🍗", effect: "trading_bonus", tradingBonus: 0.15 }, food_treasure_hunter: { name: "Treasure Hunter", description: "+1% treasure chance, -1% trash in fishing", icon: "💎", effect: "fishing_luck", treasureBonus: 0.01, trashReduction: 0.01 }, food_hearty_meal: { name: "Hearty Meal", description: "+2 relationship points per daily talk", icon: "🍔", effect: "relationship_bonus", relationshipBonus: 2 }, vending_energy: { name: "Energized", description: "+3% trading chance", icon: "⚡", effect: "trading_bonus", tradingBonus: 0.03 }, vending_protein: { name: "Protein Boost", description: "+2% trading chance", icon: "💪", effect: "trading_bonus", tradingBonus: 0.02 }, vending_focus: { name: "Focused", description: "+2% trading chance", icon: "☕", effect: "trading_bonus", tradingBonus: 0.02 }, vending_refresh: { name: "Refreshed", description: "+1 daily talk bonus", icon: "💧", effect: "relationship_bonus", relationshipBonus: 1 }, shizu_brick: { name: "Shizu", description: "+10 Brick Power", icon: "🧱", effect: "brick_power", brickPower: 10 }, food_puffy_parfait: { name: "Puffy's Parfait", description: "+2 relationship points per daily talk", icon: "🍨", effect: "relationship_bonus", relationshipBonus: 2 }, food_puffy_coral_tea: { name: "Coral Tea", description: "+1 relationship points per daily talk", icon: "🍵", effect: "relationship_bonus", relationshipBonus: 1 }, food_puffy_reef_roll: { name: "Reef Roll", description: "+$3-8 from all money sources", icon: "🍣", effect: "money_bonus", bonusMin: 3, bonusMax: 8 }, food_puffy_starfish_cookie: { name: "Starfish Cookie", description: "+5% Trading bonus", icon: "🍪", effect: "trading_bonus", tradingBonus: 0.05 }, food_puffy_espresso: { name: "Anglerfish Espresso", description: "+10% Trading bonus", icon: "☕", effect: "trading_bonus", tradingBonus: 0.10 }, food_puffy_smoothie: { name: "Ocean Breeze Smoothie", description: "+1% treasure chance, -1% trash in fishing", icon: "🥤", effect: "fishing_luck", treasureBonus: 0.01, trashReduction: 0.01 } }>> /* Decor Items - Basic (Mall Floor 2 - Coral Furnishings) */ <<set setup.decorItems = { basic: [ {id: "poster_nature", name: "Nature Poster", price: 25, room: ["bedroom", "livingRoom", "masterBedroom"], desc: "A calming forest scene"}, {id: "poster_city", name: "City Skyline Poster", price: 25, room: ["bedroom", "livingRoom", "masterBedroom"], desc: "Urban nightscape"}, {id: "small_plant", name: "Potted Succulent", price: 35, room: ["bedroom", "bathroom", "kitchen", "livingRoom", "masterBedroom"], desc: "Low-maintenance greenery"}, {id: "desk_lamp", name: "Modern Desk Lamp", price: 45, room: ["bedroom", "office", "masterBedroom"], desc: "Sleek LED lighting"}, {id: "throw_pillow", name: "Decorative Pillow Set", price: 40, room: ["bedroom", "livingRoom", "masterBedroom"], desc: "Adds comfort and color"}, {id: "wall_clock", name: "Minimalist Wall Clock", price: 55, room: ["kitchen", "livingRoom", "office"], desc: "Simple and functional"}, {id: "small_rug", name: "Accent Rug", price: 80, room: ["bedroom", "livingRoom", "masterBedroom"], desc: "Soft underfoot"}, {id: "photo_frame", name: "Photo Frame Set", price: 30, room: ["bedroom", "livingRoom", "office", "masterBedroom"], desc: "Display your memories"}, {id: "candle_set", name: "Scented Candle Set", price: 35, room: ["bedroom", "bathroom", "livingRoom", "masterBedroom"], desc: "Lavender and vanilla"}, {id: "bathroom_mat", name: "Plush Bath Mat", price: 45, room: ["bathroom"], desc: "Soft and absorbent"}, {id: "towel_set", name: "Premium Towel Set", price: 60, room: ["bathroom"], desc: "Egyptian cotton"}, {id: "kitchen_art", name: "Kitchen Wall Art", price: 40, room: ["kitchen"], desc: "Food-themed prints"} ], premium: [ {id: "art_abstract", name: "Abstract Canvas Art", price: 250, room: ["livingRoom", "bedroom", "masterBedroom"], desc: "Museum-quality print"}, {id: "art_sculpture", name: "Modern Sculpture", price: 400, room: ["livingRoom", "office"], desc: "Conversation piece"}, {id: "designer_lamp", name: "Designer Floor Lamp", price: 350, room: ["livingRoom", "bedroom", "masterBedroom"], desc: "Italian design"}, {id: "persian_rug", name: "Persian Area Rug", price: 800, room: ["livingRoom", "bedroom", "masterBedroom"], desc: "Hand-woven luxury"}, {id: "crystal_vase", name: "Crystal Vase", price: 200, room: ["livingRoom", "bedroom", "masterBedroom"], desc: "Swarovski elements"}, {id: "bookshelf", name: "Mahogany Bookshelf", price: 600, room: ["livingRoom", "office", "bedroom", "masterBedroom"], desc: "Solid hardwood"}, {id: "massage_chair", name: "Massage Chair", price: 1500, room: ["livingRoom", "bedroom", "masterBedroom"], desc: "Full-body relaxation"}, {id: "spa_kit", name: "Luxury Spa Kit", price: 300, room: ["bathroom"], desc: "Premium bath products"}, {id: "rain_shower", name: "Rain Showerhead", price: 450, room: ["bathroom"], desc: "Spa-like experience"}, {id: "wine_rack", name: "Wine Rack Cabinet", price: 350, room: ["kitchen", "livingRoom"], desc: "Holds 24 bottles"}, {id: "espresso_machine", name: "Espresso Machine", price: 500, room: ["kitchen"], desc: "Barista quality"}, {id: "smart_mirror", name: "Smart Mirror", price: 400, room: ["bathroom", "bedroom", "masterBedroom"], desc: "With LED and info display"} ], aquarium: [ {id: "coral_replica", name: "Coral Reef Replica", price: 150, room: ["aquariumRoom", "bathroom", "livingRoom"], desc: "Colorful ocean decor"}, {id: "shell_collection", name: "Shell Collection Display", price: 75, room: ["bathroom", "bedroom", "livingRoom", "masterBedroom"], desc: "Beach treasures"}, {id: "fish_mobile", name: "Fish Mobile", price: 65, room: ["bedroom", "aquariumRoom", "masterBedroom"], desc: "Gentle movement"}, {id: "ocean_painting", name: "Ocean Scene Painting", price: 180, room: ["livingRoom", "aquariumRoom"], desc: "Serene seascape"}, {id: "anchor_decor", name: "Decorative Anchor", price: 90, room: ["livingRoom", "bathroom"], desc: "Nautical accent"}, {id: "seahorse_lamp", name: "Seahorse Table Lamp", price: 120, room: ["bedroom", "livingRoom", "aquariumRoom", "masterBedroom"], desc: "Soft ambient glow"}, {id: "diver_figurine", name: "Vintage Diver Figurine", price: 85, room: ["aquariumRoom", "office"], desc: "Nostalgic charm"}, {id: "wave_sound", name: "Ocean Wave Sound Machine", price: 55, room: ["bedroom", "bathroom", "masterBedroom"], desc: "Relaxing sounds"} ] }>> /* Aquarium Capacity Upgrades */ <<set setup.aquariumCapacityUpgrades = [ {level: 1, capacity: 10, cost: 0}, {level: 2, capacity: 20, cost: 2000}, {level: 3, capacity: 35, cost: 5000}, {level: 4, capacity: 50, cost: 10000} ]>> /* Fish Rarity Colors */ <<set setup.fishRarityColors = { common: "#9e9e9e", uncommon: "#51cf66", rare: "#1e90ff", epic: "#667eea", legendary: "#ffd700", mythical: "#ff6b9d" }>> /* Fish Feeding Animation Function */ <<set setup.feedFishAnimation = function() { var tank = document.getElementById('aquarium-tank'); if (!tank) return; var pellet = document.createElement('div'); pellet.className = 'pellet'; pellet.style.cssText = 'position: absolute; width: 8px; height: 8px; background: #8B4513; border-radius: 50%; transition: top 2s ease-in;'; var pelletX = Math.random() * 60 + 20; pellet.style.left = pelletX + '%'; pellet.style.top = '5%'; tank.appendChild(pellet); setTimeout(function() { pellet.style.top = '75%'; }, 100); var fish = document.querySelectorAll('.swimming-fish'); fish.forEach(function(f, i) { setTimeout(function() { f.style.left = (pelletX + (Math.random() * 10 - 5)) + '%'; f.style.top = '70%'; }, 500 + i * 150); }); setTimeout(function() { if (pellet.parentNode) pellet.remove(); var result = document.getElementById('feed-result'); if (result) result.innerHTML = '<p style="color: #51cf66; margin: 10px 0;">The fish swim excitedly for their meal!</p>'; }, 2500); setTimeout(function() { fish.forEach(function(f) { f.style.left = (Math.random() * 75) + '%'; f.style.top = (Math.random() * 60 + 10) + '%'; }); }, 4000); }>> /* ---------------------------------- */ /* --- ROOM RENOVATION SYSTEM --- */ /* ---------------------------------- */ /* Room Renovation Options by Size */ <<set setup.roomRenovations = { small: [ { id: "home_gym", name: "Home Gym", icon: "🏋️", cost: 2500, description: "A compact workout space with essential equipment.", benefit: "Free daily workout at home", color: "#e74c3c", passage: "RoomHomeGym" }, { id: "art_studio", name: "Art Studio", icon: "🎨", cost: 3000, description: "A creative space with easels, canvases, and art supplies.", benefit: "Paint pictures to sell or decorate your home", color: "#9b59b6", passage: "RoomArtStudio" }, /* DISABLED - Study room { id: "study", name: "Study", icon: "📚", cost: 2000, description: "A quiet reading room with bookshelves and a comfortable chair.", benefit: "Store and read books (Coming Soon)", color: "#8b4513", passage: "RoomStudy" }, */ { id: "guest_bedroom", name: "Guest Bedroom", icon: "🛏️", cost: 3500, description: "A cozy bedroom for overnight guests.", benefit: "NPC sleepovers for level 2+ relationships", color: "#3498db", passage: "RoomGuestBedroom", comingSoon: true }, { id: "small_fish_tank", name: "Small Fish Tank", icon: "🐠", cost: 1500, description: "A modest aquarium for displaying your fish collection.", benefit: "Display up to 5 fish (Common to Epic only)", color: "#1e90ff", passage: "RoomSmallFishTank" } ], medium: [ { id: "home_office", name: "Home Office", icon: "💼", cost: 5000, description: "A professional workspace with desk, computer, and filing cabinets.", benefit: "+2 bonus daily trades", color: "#2c3e50", passage: "RoomHomeOffice" }, { id: "medium_fish_tank", name: "Medium Aquarium", icon: "🐟", cost: 4000, description: "A larger aquarium with more space for your fish collection.", benefit: "Display up to 15 fish (Common to Epic only)", color: "#1e90ff", passage: "RoomMediumFishTank" }, { id: "laboratory", name: "Laboratory", icon: "🧪", cost: 45000, description: "A high-tech research lab with advanced equipment for scientific experiments and trait research.", benefit: "Research traits, train intelligence, future trait combination", color: "#00d4aa", passage: "RoomLaboratory" } ], large: [ { id: "professional_gym", name: "Professional Gym", icon: "🏆", cost: 15000, description: "A fully-equipped gym with professional-grade equipment.", benefit: "Train stats faster, increase stat potential, train stamina/flexibility", color: "#e74c3c", passage: "RoomProfessionalGym" }, { id: "streaming_studio", name: "Streaming Studio", icon: "📺", cost: 20000, description: "A professional streaming setup with lighting, soundproofing, and high-end equipment.", benefit: "Universal bonus to all stream categories", color: "#9146ff", passage: "RoomStreamingStudio" }, /* DISABLED - Home Theater room { id: "home_theater", name: "Home Theater", icon: "🎬", cost: 25000, description: "A luxurious theater room with surround sound and comfortable seating.", benefit: "Movie nights with NPCs (level 2+ relationships)", color: "#c0392b", passage: "RoomHomeTheater" }, */ /* DISABLED - Dungeon room { id: "dungeon", name: "Dungeon", icon: "⛓️", cost: 30000, description: "A private space equipped for BDSM activities.", benefit: "Train dom/sub/roleplay/fetishPlay sexual skills", color: "#2c3e50", passage: "RoomDungeon" }, */ /* DISABLED - Dance Studio room { id: "dance_studio", name: "Dance Studio", icon: "💃", cost: 18000, description: "A mirrored studio with a dance floor and barre.", benefit: "Train rhythm sexual skill, stripper job bonus", color: "#e83e8c", passage: "RoomDanceStudio" } */ ] }>> /* Fish Tank Capacity by Room Size */ <<set setup.fishTankCapacity = { small: 5, medium: 15, mansion: 50 }>> /* Fish rarities allowed in smaller tanks (not mythical/legendary) */ <<set setup.smallTankAllowedRarities = ["common", "uncommon", "rare", "epic"]>> /* ---------------------------------- */ /* --- HOME SYSTEM HELPER FUNCTIONS --- */ /* ---------------------------------- */ <<set setup.getCurrentHome = function() { var v = State.variables; if (v.houseLocation === "ResidentialMansions") return "PlayerModernMansion"; if (v.houseLocation === "ResidentialExpensiveHomes") return "PlayerExpensiveHome"; if (v.houseLocation === "ResidentialNormalHomes") return "PlayerSuburbanHome"; return "StudioApartment"; }>> <<set setup.getCurrentBathroom = function() { var home = setup.getCurrentHome(); var bathroomMap = { "StudioApartment": "StudioBathroom", "PlayerSuburbanHome": "PlayerSuburbanBathroom", "PlayerExpensiveHome": "PlayerExpensiveBathroom", "PlayerModernMansion": "PlayerMansionBathroom" }; /* Prefer the bathroom the player actually entered (captured in HomeBathroomActions), so showering in the apartment while owning a home returns to the apartment, not the owned home. */ return State.variables.currentBathroom || bathroomMap[home]; }>> <<set setup.hasLuxuryBathroom = function(home) { if (!home) home = setup.getCurrentHome(); return home === "PlayerExpensiveHome" || home === "PlayerModernMansion"; }>> <<set setup.getDecorForRoom = function(room) { var home = setup.getCurrentHome(); var v = State.variables; if (!v.homeDecor || !v.homeDecor[home]) return []; return v.homeDecor[home][room] || []; }>> <<set setup.addDecorToRoom = function(itemId, room) { var home = setup.getCurrentHome(); var v = State.variables; if (!v.homeDecor[home][room]) { v.homeDecor[home][room] = []; } v.homeDecor[home][room].push(itemId); }>> <<set setup.hasDecorItem = function(itemId, home) { if (!home) home = setup.getCurrentHome(); var v = State.variables; if (!v.homeDecor || !v.homeDecor[home]) return false; var homeDecor = v.homeDecor[home]; for (var room in homeDecor) { if (Array.isArray(homeDecor[room]) && homeDecor[room].includes(itemId)) { return true; } } return false; }>> <<set setup.getDecorItem = function(itemId) { var categories = ["basic", "premium", "aquarium"]; for (var i = 0; i < categories.length; i++) { var items = setup.decorItems[categories[i]]; for (var j = 0; j < items.length; j++) { if (items[j].id === itemId) return items[j]; } } return null; }>> <<set setup.canCookRecipe = function(recipeId) { var recipe = setup.recipes[recipeId]; if (!recipe) return false; var v = State.variables; for (var ingredient in recipe.ingredients) { var needed = recipe.ingredients[ingredient]; var have = (v.kitchenInventory && v.kitchenInventory.ingredients[ingredient]) || 0; /* Hucow provides unlimited milk */ if (ingredient === "milk" && v.physicalTraits && v.physicalTraits.includes("Hucow")) { continue; } if (have < needed) return false; } return true; }>> <<set setup.consumeIngredients = function(recipeId) { var recipe = setup.recipes[recipeId]; var v = State.variables; /* Hucow provides unlimited milk - don't consume it */ var hasHucow = v.physicalTraits && v.physicalTraits.includes("Hucow"); for (var ingredient in recipe.ingredients) { /* Skip milk consumption if player has Hucow trait */ if (ingredient === "milk" && hasHucow) continue; v.kitchenInventory.ingredients[ingredient] -= recipe.ingredients[ingredient]; } }>> <<set setup.getBodyDescription = function(part, size) { var descriptions = { chest: { flat: "flat chest", "flat masculine": "flat chest", small: "small breasts", medium: "modest breasts", large: "large breasts", huge: "huge breasts", giant: "massive breasts", gigantic: "enormous breasts" }, butt: { flat: "flat rear", "flat masculine": "flat rear", small: "small butt", medium: "round butt", large: "large butt", huge: "huge butt", giant: "massive butt", gigantic: "enormous butt" }, penis: { "small penis": "modest cock", penis: "cock", "big penis": "large cock", "huge penis": "huge cock", "giant penis": "massive cock" } }; if (descriptions[part] && descriptions[part][size]) { return descriptions[part][size]; } return size + " " + part; }>> /* ---------------------------------- */ /* --- LOAD SEPARATE DATA PASSAGES --- */ /* ---------------------------------- */ <<include "InitPlayerData">> <<include "InitGameSystems">> <<include "InitNPCData">> <<include "InitTimeSystem">> /* ---------------------------------- */ /* --- JOB INCOME RATES --- */ /* ---------------------------------- */ <<set setup.jobIncome = { /* Tier 0 */ "Unemployed": 0, /* Tier 1 */ "Street Performer": 8, "Package Courier": 10, "Construction Worker": 12, "Dock Worker": 15, "Security Guard": 12, "Baker": 10, "Maid": 10, /* Tier 2 */ "Stripper": 30, "Prostitute": 28, "Fitness Shop Clerk": 20, "Ecentric Shop Worker": 18, "Tech Store Clerk": 25, "Adult Store Clerk": 20, "Beauty Salon Stylist": 28, "Brothel Worker": 35, "Model": 32, "Bouncer": 30, /* Tier 3 */ "Clinic Assistant": 55, "Data Analyst": 65, "Negotiator": 70, "Enforcer": 60, "Porn Star": 75, "Social Media Influencer": 50, "Black Market Dealer": 80, "Police Officer": 55, /* Tier 4 */ "Brothel Owner": 150, "Mayor's Secretary": 120, "City Mayor": 200 }>> /* Get income for player's current job */ <<set setup.getJobIncome = function() { var v = State.variables; if (v.jobs && v.jobs.length > 0) { var jobName = v.jobs[0]; return setup.jobIncome[jobName] || 0; } return 0; }>> /* Work at current job and earn money */ <<set setup.workJob = function() { var v = State.variables; var income = setup.getJobIncome(); if (income > 0) { v.money += income; return income; } return 0; }>> <<set $hoursWorkedToday = 0>> <<set $lastWorkDay = 0>> <<set $lastWorkLocation = "">> <<set $hasChangedNameLegally = false>> /* ---------------------------------- */ /* --- HOME SYSTEM VARIABLES --- */ /* ---------------------------------- */ /* Home upgrade tracking */ <<set $homeUpgrades = { improvedShower: false, waterHeater: false, kitchenUpgrade: false, comfortableBed: false, entertainmentSystem: false }>> /* Per-home decoration and wall colors */ <<set $savedWallColors = []>> <<set $homeDecor = { StudioApartment: { roomColors: { bedroom: "#2a2a2a", bathroom: "#2a2a2a", kitchen: "#2a2a2a" }, bedroom: [], bathroom: [], kitchen: [] }, PlayerSuburbanHome: { roomColors: { bedroom: "#2a2a2a", bathroom: "#2a2a2a", kitchen: "#2a2a2a", livingRoom: "#2a2a2a" }, bedroom: [], bathroom: [], kitchen: [], livingRoom: [] }, PlayerExpensiveHome: { roomColors: { bedroom: "#2a2a2a", bathroom: "#2a2a2a", kitchen: "#2a2a2a", livingRoom: "#2a2a2a", office: "#2a2a2a" }, bedroom: [], bathroom: [], kitchen: [], livingRoom: [], office: [] }, PlayerModernMansion: { roomColors: { masterBedroom: "#2a2a2a", bathroom: "#2a2a2a", kitchen: "#2a2a2a", livingRoom: "#2a2a2a", office: "#2a2a2a", aquariumRoom: "#2a2a2a" }, masterBedroom: [], bathroom: [], kitchen: [], livingRoom: [], office: [], aquariumRoom: [] } }>> /* Mansion aquarium system */ <<set $mansionAquarium = { fish: [], capacity: 10, capacityLevel: 1, decorations: [], lastFedTime: 0 }>> /* Kitchen/cooking system */ <<set $kitchenInventory = { ingredients: {} }>> /* Food inventory - stores cooked meals */ <<set $foodInventory = []>> <<set $giftInventory = {}>> <<set $dailyGifts = {}>> <<set $honeyInventory = 0>> <<set $milkInventory = 0>> <<set $emptyBottles = 0>> <<set $jarredHoney = 0>> <<set $emptyJars = 0>> <<set $hasRefrigerator = false>> <<set $milkedToday = false>> <<set $honeyMilkInventory = 0>> <<set $madeHoneyMilkToday = false>> <<set $giftCooldowns = {}>> /* Masturbation tracking */ <<set $masturbationStats = { timesTotal: 0, lastLocation: "", toysUsed: { dildo: 0, fleshlight: 0 } }>> <</silently>>
<<nobr>> <h1 style="color: #667eea; text-align: center;">⚙️ Trait Bonus Configuration</h1> <div style="background: #2d2d2d; padding: 20px; border-radius: 10px; color: #fff; margin-bottom: 20px;"> <p style="color: #ccc; text-align: center;">Configure stat bonuses and effects for Physical and Mental traits</p> </div> <!-- PHYSICAL TRAITS SECTION --> <div style="background: white; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 3px solid #28a745;"> <h2 style="color: #28a745; margin-top: 0; border-bottom: 3px solid #28a745; padding-bottom: 10px;">💪 Physical Trait Bonuses</h2> <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #333; margin-top: 0;">Current Physical Trait Bonuses:</h3> <<set _physicalTraitsList = ["Tall", "Short", "Muscular", "Curvy", "Petite", "Broad-shouldered", "Flexible", "Strong", "Quick", "Graceful", "Sturdy", "Lean", "Soft", "Sharp Features", "Smooth Skin", "Scarred", "Pierced", "Youthful", "Mature", "Tattooed"]>> <<for _trait range _physicalTraitsList>> <div style="background: white; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #28a745;"> <h4 style="color: #28a745; margin: 0 0 10px 0;">_trait</h4> <<if setup.physicalTraitBonuses && setup.physicalTraitBonuses[_trait]>> <<set _bonuses = setup.physicalTraitBonuses[_trait]>> <div style="color: #333; margin-bottom: 10px;"> <strong>Current Bonuses:</strong><br> <<if _bonuses.charisma>>Charisma: +_bonuses.charisma<br><</if>> <<if _bonuses.dexterity>>Dexterity: +_bonuses.dexterity<br><</if>> <<if _bonuses.strength>>Strength: +_bonuses.strength<br><</if>> <<if _bonuses.intelligence>>Intelligence: +_bonuses.intelligence<br><</if>> <<if _bonuses.description>><em style="color: #666;">_bonuses.description</em><</if>> </div> <<else>> <p style="color: #999; font-style: italic; margin: 5px 0;">No bonuses configured</p> <</if>> <details style="margin-top: 10px;"> <summary style="cursor: pointer; color: #28a745; font-weight: bold;">Configure Bonuses</summary> <div style="padding: 15px; background: #f0f0f0; margin-top: 10px; border-radius: 5px;"> <<set _traitId = _trait.replace(/\s+/g, '')>> <label style="display: block; margin: 10px 0; color: #333;"> Charisma Bonus: <input type="number" @id="'cha_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Dexterity Bonus: <input type="number" @id="'dex_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Strength Bonus: <input type="number" @id="'str_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Intelligence Bonus: <input type="number" @id="'int_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Description: <input type="text" @id="'desc_' + _traitId" placeholder="Effect description" style="margin-left: 10px; padding: 5px; width: 300px;"> </label> <<capture _trait, _traitId>> <<link "<div style='background: #28a745; color: white; padding: 8px 15px; border-radius: 5px; text-align: center; margin-top: 10px; cursor: pointer;'>Save Bonuses</div>">> <<set _cha = parseInt(jQuery('#cha_' + _traitId).val()) || 0>> <<set _dex = parseInt(jQuery('#dex_' + _traitId).val()) || 0>> <<set _str = parseInt(jQuery('#str_' + _traitId).val()) || 0>> <<set _int = parseInt(jQuery('#int_' + _traitId).val()) || 0>> <<set _desc = jQuery('#desc_' + _traitId).val()>> <<if !setup.physicalTraitBonuses>> <<set setup.physicalTraitBonuses = {}>> <</if>> <<set setup.physicalTraitBonuses[_trait] = {}>> <<if _cha > 0>><<set setup.physicalTraitBonuses[_trait].charisma = _cha>><</if>> <<if _dex > 0>><<set setup.physicalTraitBonuses[_trait].dexterity = _dex>><</if>> <<if _str > 0>><<set setup.physicalTraitBonuses[_trait].strength = _str>><</if>> <<if _int > 0>><<set setup.physicalTraitBonuses[_trait].intelligence = _int>><</if>> <<if _desc && _desc.trim()>><<set setup.physicalTraitBonuses[_trait].description = _desc>><</if>> <<goto "TraitBonusManager">> <</link>> <</capture>> </div> </details> </div> <</for>> </div> </div> <!-- MENTAL TRAITS SECTION --> <div style="background: white; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 3px solid #764ba2;"> <h2 style="color: #764ba2; margin-top: 0; border-bottom: 3px solid #764ba2; padding-bottom: 10px;">🧠 Mental Trait Bonuses</h2> <div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #333; margin-top: 0;">Current Mental Trait Bonuses:</h3> <<set _mentalTraitsList = ["Intelligent", "Creative", "Analytical", "Empathetic", "Confident", "Shy", "Outgoing", "Patient", "Ambitious", "Curious", "Witty", "Calm", "Energetic", "Thoughtful", "Competitive", "Friendly", "Logical", "Shrewd", "Extroverted", "Introverted", "Bitchy", "Kind", "Sly", "Honest", "Dominant", "Submissive", "Aggressive", "Passive", "Optimistic", "Pessimistic", "Cruel", "Stubborn", "Flexible", "Jealous", "Supportive"]>> <<for _trait range _mentalTraitsList>> <div style="background: white; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #764ba2;"> <h4 style="color: #764ba2; margin: 0 0 10px 0;">_trait</h4> <<if setup.mentalTraitBonuses && setup.mentalTraitBonuses[_trait]>> <<set _bonuses = setup.mentalTraitBonuses[_trait]>> <div style="color: #333; margin-bottom: 10px;"> <strong>Current Bonuses:</strong><br> <<if _bonuses.charisma>>Charisma: +_bonuses.charisma<br><</if>> <<if _bonuses.dexterity>>Dexterity: +_bonuses.dexterity<br><</if>> <<if _bonuses.strength>>Strength: +_bonuses.strength<br><</if>> <<if _bonuses.intelligence>>Intelligence: +_bonuses.intelligence<br><</if>> <<if _bonuses.description>><em style="color: #666;">_bonuses.description</em><</if>> </div> <<else>> <p style="color: #999; font-style: italic; margin: 5px 0;">No bonuses configured</p> <</if>> <details style="margin-top: 10px;"> <summary style="cursor: pointer; color: #764ba2; font-weight: bold;">Configure Bonuses</summary> <div style="padding: 15px; background: #f0f0f0; margin-top: 10px; border-radius: 5px;"> <<set _traitId = _trait.replace(/\s+/g, '')>> <label style="display: block; margin: 10px 0; color: #333;"> Charisma Bonus: <input type="number" @id="'cha_m_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Dexterity Bonus: <input type="number" @id="'dex_m_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Strength Bonus: <input type="number" @id="'str_m_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Intelligence Bonus: <input type="number" @id="'int_m_' + _traitId" min="0" max="10" value="0" style="margin-left: 10px; padding: 5px; width: 60px;"> </label> <label style="display: block; margin: 10px 0; color: #333;"> Description: <input type="text" @id="'desc_m_' + _traitId" placeholder="Effect description" style="margin-left: 10px; padding: 5px; width: 300px;"> </label> <<capture _trait, _traitId>> <<link "<div style='background: #764ba2; color: white; padding: 8px 15px; border-radius: 5px; text-align: center; margin-top: 10px; cursor: pointer;'>Save Bonuses</div>">> <<set _cha = parseInt(jQuery('#cha_m_' + _traitId).val()) || 0>> <<set _dex = parseInt(jQuery('#dex_m_' + _traitId).val()) || 0>> <<set _str = parseInt(jQuery('#str_m_' + _traitId).val()) || 0>> <<set _int = parseInt(jQuery('#int_m_' + _traitId).val()) || 0>> <<set _desc = jQuery('#desc_m_' + _traitId).val()>> <<if !setup.mentalTraitBonuses>> <<set setup.mentalTraitBonuses = {}>> <</if>> <<set setup.mentalTraitBonuses[_trait] = {}>> <<if _cha > 0>><<set setup.mentalTraitBonuses[_trait].charisma = _cha>><</if>> <<if _dex > 0>><<set setup.mentalTraitBonuses[_trait].dexterity = _dex>><</if>> <<if _str > 0>><<set setup.mentalTraitBonuses[_trait].strength = _str>><</if>> <<if _int > 0>><<set setup.mentalTraitBonuses[_trait].intelligence = _int>><</if>> <<if _desc && _desc.trim()>><<set setup.mentalTraitBonuses[_trait].description = _desc>><</if>> <<goto "TraitBonusManager">> <</link>> <</capture>> </div> </details> </div> <</for>> </div> </div> <!-- EXPORT/IMPORT SECTION --> <div style="background: white; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 3px solid #ffc107;"> <h2 style="color: #e67e00; margin-top: 0; border-bottom: 3px solid #ffc107; padding-bottom: 10px;">💾 Export/Import Configuration</h2> <div style="margin-bottom: 15px;"> <<link "<div style='background: #ffc107; color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold;'>📋 Copy Configuration to Clipboard</div>">> <<set _config = { physical: setup.physicalTraitBonuses || {}, mental: setup.mentalTraitBonuses || {} }>> <<set _configJSON = JSON.stringify(_config, null, 2)>> <<run navigator.clipboard.writeText(_configJSON)>> <<script>>UI.alert("Configuration copied to clipboard!");<</script>> <</link>> </div> <div> <p style="color: #333; font-weight: bold;">Paste Configuration JSON:</p> <textarea id="importConfig" style="width: 100%; height: 150px; padding: 10px; font-family: monospace; background: #f8f9fa; border: 2px solid #ffc107; border-radius: 5px;" placeholder='Paste JSON configuration here...'></textarea> <<link "<div style='background: #28a745; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>📥 Import Configuration</div>">> <<set _importJSON = jQuery('#importConfig').val()>> <<try>> <<set _imported = JSON.parse(_importJSON)>> <<set setup.physicalTraitBonuses = _imported.physical || {}>> <<set setup.mentalTraitBonuses = _imported.mental || {}>> <<script>>UI.alert("Configuration imported successfully!");<</script>> <<goto "TraitBonusManager">> <<catch _error>> <<script>>UI.alert("Error importing configuration: Invalid JSON format");<</script>> <</try>> <</link>> </div> </div> <!-- NAVIGATION --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Back to Game</div>">> <<goto "Alleyway">> <</link>> </div> <</nobr>>
<<nobr>> /* Criminal Heat-Based Arrest Check */ <<if $jobs && $jobs.includes("Criminal")>> <<if !$heat>> <<set $heat = 0>> <</if>> /* Calculate arrest chance: 1% at 0 heat, 90% at 100 heat */ <<set _arrestChance = 1 + ($heat * 0.89)>> <<set _arrestRoll = random(1, 100)>> <<if _arrestRoll <= _arrestChance>> <<goto "CaughtByPolice">> <</if>> <</if>> <<set $lastLocation = "OpahFitness">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("OpahFitness")>> <<run $visitedLocations.push("OpahFitness")>> <</if>> <!-- Initialize gym membership --> <<if !$gymMembershipDaysRemaining>> <<set $gymMembershipDaysRemaining = 0>> <</if>> <!-- Initialize gym workout count for today --> <<if !$gymWorkoutCount>> <<set $gymWorkoutCount = 0>> <<set $lastGymDay = $dayNumber>> <</if>> <!-- Reset counter if it's a new day --> <<if $lastGymDay !== $dayNumber>> <<set $gymWorkoutCount = 0>> <<set $lastGymDay = $dayNumber>> <</if>> <!-- Calculate current hour --> <<set _currentHour = Math.floor($timeInMinutes / 60) % 24>> <!-- Check if gym is open (5 AM to 9 PM) --> <<if _currentHour < 5 || _currentHour >= 21>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">💪 Opah Fitness - CLOSED</h1> <div style="background: #2a2a2a; border: 3px solid #ffc107; padding: 25px; border-radius: 12px; text-align: center; margin: 50px auto; max-width: 600px;"> <p style="color: #ffc107; font-size: 24px; font-weight: bold; margin: 0 0 15px 0;">🔒 Gym is Currently Closed</p> <p style="color: #aaa; font-size: 16px; margin: 0 0 20px 0;"> Opah Fitness is open from <span style="color: #ff6b6b; font-weight: bold;">5:00 AM to 9:00 PM</span> daily. </p> <p style="color: #ccc; font-size: 14px; margin: 0;"> Come back during operating hours to train! </p> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">💪 Opah Fitness</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: white; font-size: 18px; margin: 0;"> The sound of clanking weights and upbeat music fills the air. Rows of treadmills, weight machines, and free weights line the spacious facility. Mirrors cover the walls, and motivational posters encourage members to push their limits. The smell of rubber mats and determination hangs in the air. </p> </div> <!-- Operating Hours Display --> <div style="background: #2a2a2a; border: 2px solid #17a2b8; padding: 15px; border-radius: 8px; margin-bottom: 20px;"> <div style="color: #17a2b8; font-size: 14px; font-weight: bold;"> 🕐 Hours: 5:00 AM - 9:00 PM </div> </div> <!-- Membership Status --> <<set _canAffordMembership = setup.canAffordTotal(70)>> <div style="background: #2a2a2a; border: 3px solid <<if $gymMembershipDaysRemaining > 0>>#51cf66<<else>>#ff6b6b<</if>>; padding: 18px; border-radius: 10px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<if $gymMembershipDaysRemaining > 0>> <div style="color: #51cf66; font-size: 18px; font-weight: bold;"> ✅ Active Membership: <span style="color: #ffc107;"><<print $gymMembershipDaysRemaining>> days remaining</span> </div> <<else>> <div style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin-bottom: 15px;"> ❌ No Active Membership </div> <p style="color: #aaa; font-size: 14px; margin: 0 0 15px 0;"> Purchase a 30-day membership for $70 to access the gym facilities. </p> <<if _canAffordMembership>> <<link "<div style='background: #51cf66; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Purchase Membership ($70)</div>">> <<set _payment = setup.payAmount(70)>> <<if _payment.success>> <<set $gymMembershipDaysRemaining = 30>> <</if>> <<goto "OpahFitness">> <</link>> <<else>> <div style='background: #3a3a3a; color: #666; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold;'>Insufficient Funds</div> <</if>> <</if>> </div> <!-- Workout Limit Display --> <<if $gymMembershipDaysRemaining > 0>> <div style="background: #2a2a2a; border: 3px solid #ffc107; padding: 18px; border-radius: 10px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="color: #ffc107; font-size: 18px; font-weight: bold;"> ⚡ Workout Time Remaining Today: <span style="color: #ff6b6b;"><<print 120 - ($gymWorkoutCount * 120)>> minutes / 120 minutes</span> </div> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> You can train for up to 2 hours per day. Each workout takes 2 hours. </p> </div> <<set _cerberusGymBonus = $physicalTraits.includes("Cerberus") ? 4 : ($physicalTraits.includes("Gym Bunny") ? 4 : ($physicalTraits.includes("Himbo") ? 2 : 1))>> <<set _isLizardman = $physicalTraits.includes("Lizardman")>> <<set _isKakuen = $physicalTraits.includes("Kakuen")>> <<set _isAutomaton = $physicalTraits.includes("Automaton")>> <<if _isLizardman>><<set _cerberusGymBonus = Math.max(_cerberusGymBonus, 3)>><</if>> <!-- Transformation Gym Multiplier Display --> <<if _isAutomaton>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #888; margin-bottom: 20px; box-shadow: 0 0 15px rgba(136,136,136,0.4);"> <p style="color: #888; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> ✗ Automaton: Your mechanical body cannot benefit from physical training. </p> </div> <<elseif _cerberusGymBonus > 1 || _isLizardman || _isKakuen>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #ff6b6b; margin-bottom: 20px; box-shadow: 0 0 15px rgba(255,107,107,0.4);"> <p style="color: #ff6b6b; margin: 0; text-align: center; font-size: 14px; font-weight: bold; text-shadow: 0 0 8px rgba(255,107,107,0.5);"> <<if _isLizardman>>✓ Lizardman: 3x Strength Training (Strength Only — No Other Stats)<<elseif _isKakuen>>✓ Kakuen: Strength Training also grants +1 Charisma and +1 Intelligence<<elseif $physicalTraits.includes("Cerberus")>>✓ Cerberus: <<print _cerberusGymBonus>>x Workout Gains<<elseif $physicalTraits.includes("Gym Bunny")>>✓ Gym Bunny: <<print _cerberusGymBonus>>x Workout Gains<<else>>✓ Himbo: <<print _cerberusGymBonus>>x Workout Gains<</if>> </p> </div> <</if>> <h2 style="color: #ff6b6b;">Workout Programs</h2> <<set _opahStrGain = 2 * _cerberusGymBonus>> <<set _opahDexGain = _isLizardman ? 0 : (2 * _cerberusGymBonus)>> <<set _opahMixedStrGain = _isLizardman ? (2 * _cerberusGymBonus) : (1 * _cerberusGymBonus)>> <<set _opahMixedDexGain = _isLizardman ? 0 : (1 * _cerberusGymBonus)>> <<if _isAutomaton>> <div style="background: #1a1a1a; border: 3px solid #888; padding: 20px; border-radius: 8px; text-align: center; margin-bottom: 25px;"> <p style="color: #888; margin: 0; font-weight: bold; font-size: 18px;">Your mechanical body cannot benefit from physical training.</p> <p style="color: #666; margin: 10px 0 0 0; font-size: 14px;">Automatons are built, not trained. Your body does not respond to exercise.</p> </div> <<elseif $gymWorkoutCount >= 1>> <div style="background: #1a1a1a; border: 3px solid #ffc107; padding: 20px; border-radius: 8px; text-align: center; margin-bottom: 25px;"> <p style="color: #ffc107; margin: 0; font-weight: bold; font-size: 18px;">You've completed your workout for today. Your muscles need rest!</p> <p style="color: #aaa; margin: 10px 0 0 0; font-size: 14px;">Come back tomorrow for more training.</p> </div> <<else>> <!-- Workout Options --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Strength Training --> <div style="border: 3px solid #ff6b6b; border-radius: 12px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0; font-size: 22px;">🏋️ Strength Training</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0; line-height: 1.6;"> Hit the weight room and pump iron. Focus on building raw power through heavy compound lifts like deadlifts, squats, and bench press. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 15px;"> <div style="color: #51cf66; font-size: 14px; font-weight: bold; margin-bottom: 5px;">Gains:</div> <div style="color: #aaa; font-size: 13px;">+<<print _opahStrGain>> Strength<<if _isKakuen>>, +1 Charisma, +1 Intelligence<</if>></div> </div> <<if $stats.strength >= $statMaxCaps.strength>> <div style="background: #3a3a3a; color: #666; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; margin-top: auto;">Max Strength Reached</div> <<else>> <<link "<div style='background: #ff6b6b; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto; font-size: 16px;'>Start Workout (2 hours)</div>">> <<set $stats.strength += _opahStrGain>> <<if $physicalTraits.includes("Kakuen")>> <<set $stats.charisma += 1>> <<set $stats.intelligence += 1>> <</if>> <<set $gymWorkoutCount += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<advancetime 120>> <<if _currentHour >= 21>> <<goto "GymKickout">> <<else>> <<goto "OpahFitness">> <</if>> <</link>> <</if>> </div> <!-- Cardio Training --> <<if _isLizardman>> <div style="border: 3px solid #555; border-radius: 12px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.6;"> <h3 style="color: #555; margin: 0 0 15px 0; font-size: 22px;">🏃 Cardio Training</h3> <p style="color: #666; font-size: 14px; margin: 0 0 15px 0; line-height: 1.6;"> Your Lizardman body is built for raw power, not agility. Cardio training is ineffective for you. </p> <div style="background: #3a3a3a; color: #666; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; margin-top: auto;">Unavailable (Lizardman)</div> </div> <<else>> <div style="border: 3px solid #51cf66; border-radius: 12px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin: 0 0 15px 0; font-size: 22px;">🏃 Cardio Training</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0; line-height: 1.6;"> Get your heart rate up with intense cardio sessions. Run on the treadmill, use the elliptical, or cycle to improve your agility and endurance. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 15px;"> <div style="color: #51cf66; font-size: 14px; font-weight: bold; margin-bottom: 5px;">Gains:</div> <div style="color: #aaa; font-size: 13px;">+<<print _opahDexGain>> Dexterity</div> </div> <<if $stats.dexterity >= $statMaxCaps.dexterity>> <div style="background: #3a3a3a; color: #666; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; margin-top: auto;">Max Dexterity Reached</div> <<else>> <<link "<div style='background: #51cf66; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto; font-size: 16px;'>Start Workout (2 hours)</div>">> <<set $stats.dexterity += _opahDexGain>> <<set $gymWorkoutCount += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<advancetime 120>> <<if _currentHour >= 21>> <<goto "GymKickout">> <<else>> <<goto "OpahFitness">> <</if>> <</link>> <</if>> </div> <</if>> <!-- Mixed Training --> <div style="border: 3px solid #9b59b6; border-radius: 12px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px;">⚡ Mixed Training</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0; line-height: 1.6;"> Combine strength and cardio in a balanced circuit training routine. Get the best of both worlds with compound exercises and high-intensity intervals. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 15px;"> <div style="color: #51cf66; font-size: 14px; font-weight: bold; margin-bottom: 5px;">Gains:</div> <div style="color: #aaa; font-size: 13px;">+<<print _opahMixedStrGain>> Strength<<if _opahMixedDexGain > 0>>, +<<print _opahMixedDexGain>> Dexterity<</if>><<if _isKakuen>>, +1 Charisma, +1 Intelligence<</if>></div> </div> <<if $stats.strength >= $statMaxCaps.strength && $stats.dexterity >= $statMaxCaps.dexterity>> <div style="background: #3a3a3a; color: #666; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; margin-top: auto;">Max Stats Reached</div> <<else>> <<link "<div style='background: #9b59b6; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto; font-size: 16px;'>Start Workout (2 hours)</div>">> <<if $stats.strength < $statMaxCaps.strength>> <<set $stats.strength += _opahMixedStrGain>> <</if>> <<if $stats.dexterity < $statMaxCaps.dexterity && _opahMixedDexGain > 0>> <<set $stats.dexterity += _opahMixedDexGain>> <</if>> <<if $physicalTraits.includes("Kakuen")>> <<set $stats.charisma += 1>> <<set $stats.intelligence += 1>> <</if>> <<set $gymWorkoutCount += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<advancetime 120>> <<if _currentHour >= 21>> <<goto "GymKickout">> <<else>> <<goto "OpahFitness">> <</if>> <</link>> <</if>> </div> </div> <</if>> <!-- Additional Services --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 20px 0; font-size: 24px; border-bottom: 3px solid #17a2b8; padding-bottom: 10px;">🏢 Gym Services</h3> <div style="display: flex; flex-wrap: wrap; gap: 15px; justify-content: center;"> <!-- Personal Training with Fen Ris --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column; flex: 1 1 250px; max-width: 350px;"> <h4 style="color: #ff6b6b; margin: 0 0 10px 0;">🐺 Personal Training</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Train with the gym's elite fitness trainer for intensive one-on-one sessions.</p> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Meet Trainer</div>">> <<goto "FenRisTraining">> <</link>> </div> <!-- Locker Room --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column; flex: 1 1 250px; max-width: 350px;"> <h4 style="color: #667eea; margin: 0 0 10px 0;">🚿 Locker Room</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Clean up after your workout in the locker room facilities.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter</div>">> <<goto "GymLockerRoom">> <</link>> </div> <!-- Meet NPCs --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column; flex: 1 1 250px; max-width: 350px;"> <h4 style="color: #e91e63; margin: 0 0 10px 0;">👥 Gym Floor</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Look around for other gym members to chat with.</p> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Browse</div>">> <<goto "GymNPCs">> <</link>> </div> </div> </div> <</if>> <!-- Fitness Trainer Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Fitness Trainer")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🏋️ Apply: Fitness Trainer</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Fitness Trainer")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🏋️ Apply: Fitness Trainer</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #ff6b35; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b35; margin: 0 0 10px 0;">🏋️ Apply: Fitness Trainer</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $25/hour</p> <<link "<div style='background: #ff6b35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "FitnessTrainerJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Fitness Trainer Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Fitness Trainer">> <div style="border: 3px solid #ff6b35; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b35; margin: 0 0 10px 0;">🏋️ Fitness Trainer Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Teach a fitness class! Choose between Group Fitness, Personal Training, or Boot Camp. (Max 8 hours/day)</p> <<link "<div style='background: #ff6b35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Work Shift</div>">> <<goto "FitnessTrainerWork">> <</link>> </div> <</if>> <br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> /* Criminal Heat-Based Arrest Check */ <<if $jobs && $jobs.includes("Criminal")>> <<if !$heat>> <<set $heat = 0>> <</if>> /* Calculate arrest chance: 1% at 0 heat, 90% at 100 heat */ <<set _arrestChance = 1 + ($heat * 0.89)>> <<set _arrestRoll = random(1, 100)>> <<if _arrestRoll <= _arrestChance>> <<goto "CaughtByPolice">> <</if>> <</if>> <<set $lastLocation = "Cafe">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Cafe")>> <<run $visitedLocations.push("Cafe")>> <</if>> <!-- Check if player is an employee --> <<set _isEmployee = ($jobs && $jobs.includes("Barista"))>> <!-- Calculate current hour --> <<set _currentHour = Math.floor($timeInMinutes / 60) % 24>> <!-- Check if cafe is open (6 AM to 5 PM) --> <<set _isOpen = (_currentHour >= 6 && _currentHour < 17)>> <!-- Employees can access anytime, others need to check hours --> <<if !_isOpen && !_isEmployee>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #8d6e63; text-align: center;">☕ Manta Ray Cafe - CLOSED</h1> <div style="background: #2a2a2a; border: 3px solid #8d6e63; padding: 25px; border-radius: 12px; text-align: center; margin: 50px auto; max-width: 600px;"> <p style="color: #8d6e63; font-size: 24px; font-weight: bold; margin: 0 0 15px 0;">🔒 Cafe is Currently Closed</p> <p style="color: #aaa; font-size: 16px; margin: 0 0 20px 0;"> Manta Ray Cafe is open from <span style="color: #8d6e63; font-weight: bold;">6:00 AM to 5:00 PM</span> daily. </p> <p style="color: #ccc; font-size: 14px; margin: 0;"> Come back during operating hours for coffee and conversation! </p> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #8d6e63; text-align: center;">☕ Manta Ray Cafe</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Cafe.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #8d6e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Manta Ray Cafe"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #8d6e63 0%, #6d4c41 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8d6e63;"> <p style="color: white; font-size: 18px; margin: 0;"> <<if !_isOpen && _isEmployee>> The cafe is closed to the public, but as an employee, you have access. The lights are dim and the space is quiet without customers. Equipment sits clean and ready for the next shift. <<else>> The rich aroma of freshly brewed coffee fills the air. Business professionals sit at sleek tables, laptops open, discussing deals over lattes and cappuccinos. Soft jazz plays in the background, creating an atmosphere of sophisticated productivity. <</if>> </p> </div> <!-- Operating Hours Display --> <div style="background: #2a2a2a; border: 2px solid #8d6e63; padding: 15px; border-radius: 8px; margin-bottom: 20px;"> <div style="color: #8d6e63; font-size: 14px; font-weight: bold;"> 🕐 Hours: 6:00 AM - 5:00 PM <<if _isEmployee>> <span style="color: #51cf66;"> (Employee Access: 24/7)</span> <</if>> </div> </div> <h2 style="color: #8d6e63;">Cafe Services</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- Order Coffee --> <<set _canAffordCoffee = setup.canAffordTotal(5)>> <div style="border: 3px solid #8d6e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #8d6e63; margin: 0 0 10px 0;">☕ Order Coffee</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0; line-height: 1.4;">Grab a premium coffee to energize yourself.</p> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 0 0 auto 0;">Cost: $5</p> <<if _canAffordCoffee>> <<link "<div style='background: linear-gradient(135deg, #8d6e63 0%, #6d4c41 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Order Coffee</div>">> <<set _payment = setup.payAmount(5)>> <<if _payment.success>> <<goto "CafeCoffee">> <</if>> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Insufficient Funds</div> <</if>> </div> <!-- Apply for Job --> <div style="border: 3px solid #4dabf7; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #4dabf7; margin: 0 0 10px 0;">💼 Apply for Barista Position</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0; line-height: 1.4;">Join the team as a barista.</p> <p style="color: #ffd43b; font-size: 14px; margin: 0 0 auto 0;">Requirements: 10 Dexterity, 10 Charisma</p> <<if $jobs && $jobs.includes("Barista")>> <div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>✓ Currently Employed</div> <<elseif $jobs && $jobs.includes("Criminal")>> <<if setup.getTotalStat("dexterity") >= 10 && setup.getTotalStat("charisma") >= 10>> <<link "<div style='background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Apply Now</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Insufficient Stats</div> <</if>> <<elseif setup.getTotalStat("dexterity") >= 10 && setup.getTotalStat("charisma") >= 10>> <<link "<div style='background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Apply Now</div>">> <<set $jobs = ["Barista"]>> <<set $homeless = false>> <<goto "CafeHired">> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Insufficient Stats</div> <</if>> </div> </div> <!-- Work Area (if employed) --> <<if $jobs && $jobs.includes("Barista")>> <h2 style="color: #8d6e63; margin-top: 30px;">Work Area</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">☕ Barista Station</h3> <p style="color: #aaa; margin: 0 0 15px 0;">Your workspace behind the coffee bar.</p> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>⚒️ Start Work Shift</div>" "UniversalWork">><</link>> </div> </div> <</if>> <!-- NPCs Present --> <<set _baristas = setup.getNPCsAtLocation("Cafe")>> <<if _baristas && _baristas.length > 0>> <h2 style="color: #8d6e63; margin-top: 30px;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #8d6e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _baristas>> <<capture _npc>> <div style="border: 3px solid #8d6e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #8d6e63; margin: 0 0 10px 0;"><<= _npc.name>></h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #8d6e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to <<= _npc.name>></div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="color: #8d6e63; margin-top: 30px;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No baristas are working right now. </p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Apartments")>> <<run $visitedLocations.push("Apartments")>> <</if>> <<set $lastLocation = "Apartments">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center;">🏢 Sunfish Apartments</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: white; font-size: 18px; margin: 0;"> A modest apartment building with a clean, professional lobby. The receptionist sits behind a polished desk, ready to help prospective tenants. </p> </div> <!-- Check if player already has an apartment --> <<if $hasApartment>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #51cf66; margin: 0 0 15px 0;">🔑 Your Studio Apartment</h2> <p style="color: #ccc; margin: 0 0 10px 0;">You have a studio apartment here. Your next rent payment is due in <<print $rentDaysRemaining>> days.</p> <p style="color: #aaa; margin: 0; font-size: 14px;">Monthly Rent: $<<print setup.formatMoney(setup.getApartmentRent())>> (due every 30 days)</p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Enter Apartment --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🚪 Enter Your Apartment</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Go inside your studio apartment.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Apartment</div>">> <<goto "StudioApartment">> <</link>> </div> <!-- Pay Rent Early --> <<if $rentDaysRemaining > 0>> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">💰 Pay Rent Early</h3> <<set _aptRent = setup.getApartmentRent()>> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Pay next month's rent ($<<print setup.formatMoney(_aptRent)>>) to extend your lease by 30 days.</p> <<if $money >= _aptRent>> <<set _rentLabel = "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Pay $" + setup.formatMoney(_aptRent) + "</div>">> <<link _rentLabel>> <<set $money -= _aptRent>> <<set $rentDaysRemaining += 30>> <<goto "Apartments">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Enough Money</div> <</if>> </div> <</if>> <!-- Meet the Neighbors --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">👥 Meet the Neighbors</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Visit the common area and meet your fellow tenants.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Meet Neighbors</div>">> <<goto "MeetNeighbors">> <</link>> </div> </div> <<else>> <!-- Player doesn't have an apartment - Show rental options --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #3498db; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #3498db; margin: 0 0 15px 0;">💼 Front Desk Receptionist</h2> <p style="color: #ccc; margin: 0 0 15px 0;">"Welcome to Sunfish Apartments! We have studio apartments available for rent."</p> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66; margin-bottom: 15px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">📋 Studio Apartment Details</h3> <p style="color: #aaa; margin: 0 0 5px 0;">• Down Payment: <strong style="color: #51cf66;">$300</strong> (one-time)</p> <p style="color: #aaa; margin: 0 0 5px 0;">• Monthly Rent: <strong style="color: #51cf66;">$<<print setup.formatMoney(setup.getApartmentRent())>></strong> (due every 30 days)</p> <p style="color: #aaa; margin: 0;">• First month's rent included with down payment</p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #3498db; margin-bottom: 15px;"> <p style="color: #3498db; margin: 0; text-align: center;"> <strong>Your Money:</strong> <<print setup.formatMoney($money)>> </p> </div> <<if $money >= 300>> <<link "<div style='background: #28a745; color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px;'>💳 Pay Down Payment ($300)</div>">> <<set $money -= 300>> <<set $hasApartment = true>> <<set $rentDaysRemaining = 30>> <<set $homeless = false>> <<run setup.achievements.unlock("unlock_apartment")>> <<goto "Apartments">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 15px; border-radius: 8px; text-align: center; font-weight: bold; font-size: 18px;'>💸 Not Enough Money (Need $300)</div> <p style="color: #dc3545; margin: 15px 0 0 0; text-align: center; font-style: italic;">You need $<<print 300 - $money>> more to afford the down payment.</p> <</if>> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* Criminal Heat-Based Arrest Check */ <<if $jobs && $jobs.includes("Criminal")>> <<if !$heat>> <<set $heat = 0>> <</if>> /* Calculate arrest chance: 1% at 0 heat, 90% at 100 heat */ <<set _arrestChance = 1 + ($heat * 0.89)>> <<set _arrestRoll = random(1, 100)>> <<if _arrestRoll <= _arrestChance>> <<goto "CaughtByPolice">> <</if>> <</if>> <<set $lastLocation = "DanceStudio">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("DanceStudio")>> <<run $visitedLocations.push("DanceStudio")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b9d; text-align: center;">🎀 Ribbonfish Dance Studio</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/DanceStudio.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #ff6b9d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Ribbonfish Dance Studio"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b9d 0%, #f06595 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b9d;"> <p style="color: white; font-size: 18px; margin: 0;"> Floor-to-ceiling mirrors reflect dancers practicing their craft. Soft music plays from speakers as people move gracefully across the polished hardwood floor. The energy is electric yet refined. </p> </div> <<if $physicalTraits.includes("Automaton")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 2px solid #555; margin-bottom: 20px;"> <p style="color: #e74c3c; font-size: 16px; text-align: center; margin: 0;">Your mechanical body cannot perform dance movements. Dance classes are unavailable.</p> </div> <div style="text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold;'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <<else>> <!-- Initialize weekly dance lesson trackers (3 per activity per week) --> <<if !$weeklyDanceGroupLessons>> <<set $weeklyDanceGroupLessons = {week: 0, count: 0}>> <</if>> <<if !$weeklyDancePrivateLessons>> <<set $weeklyDancePrivateLessons = {week: 0, count: 0}>> <</if>> <!-- Calculate current week number (weeks start on Monday) --> <<set _currentWeek = Math.floor($dayNumber / 7)>> <!-- Reset weekly counts if new week --> <<if $weeklyDanceGroupLessons.week !== _currentWeek>> <<set $weeklyDanceGroupLessons = {week: _currentWeek, count: 0}>> <</if>> <<if $weeklyDancePrivateLessons.week !== _currentWeek>> <<set $weeklyDancePrivateLessons = {week: _currentWeek, count: 0}>> <</if>> <h2 style="color: #ff6b9d;">Dance Classes</h2> <!-- Weekly Limit Display --> <div style="background: #2a2a2a; border: 3px solid #ff6b9d; padding: 18px; border-radius: 10px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div style="text-align: center;"> <span style="color: #ff6b9d; font-weight: bold;">🩰 Group Lessons:</span> <span style="color: <<if $weeklyDanceGroupLessons.count >= 3>>#ff6b6b<<else>>#51cf66<</if>>; font-weight: bold;"> <<= $weeklyDanceGroupLessons.count>> / 3 this week </span> </div> <div style="text-align: center;"> <span style="color: #FFD700; font-weight: bold;">👥 Private Sessions:</span> <span style="color: <<if $weeklyDancePrivateLessons.count >= 3>>#ff6b6b<<else>>#51cf66<</if>>; font-weight: bold;"> <<= $weeklyDancePrivateLessons.count>> / 3 this week </span> </div> </div> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- Group Dance Lessons --> <<set _canAffordGroupLesson = setup.canAffordTotal(50)>> <<set _groupLessonsRemaining = 3 - $weeklyDanceGroupLessons.count>> <div style="border: 3px solid #ff6b9d; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #ff6b9d; margin: 0 0 10px 0;">🩰 Group Dance Lessons</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0; line-height: 1.4;">Improve your grace and dexterity through dance with other students.</p> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 0 0 5px 0;">Cost: $50</p> <p style="color: <<if _groupLessonsRemaining > 0>>#aaa<<else>>#ff6b6b<</if>>; font-size: 13px; margin: 0 0 auto 0;"> <<if _groupLessonsRemaining > 0>> <<= _groupLessonsRemaining>> lesson<<if _groupLessonsRemaining !== 1>>s<</if>> remaining this week <<else>> Weekly limit reached <</if>> </p> <<if _groupLessonsRemaining <= 0>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Weekly Limit Reached</div> <<elseif _canAffordGroupLesson>> <<link "<div style='background: linear-gradient(135deg, #ff6b9d 0%, #f06595 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Join Class</div>">> <<set _payment = setup.payAmount(50)>> <<if _payment.success>> <<goto "DanceGroupLesson">> <</if>> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Insufficient Funds</div> <</if>> </div> <!-- Private Sessions --> <<set _canAffordPrivateLesson = setup.canAffordTotal(200)>> <<set _privateLessonsRemaining = 3 - $weeklyDancePrivateLessons.count>> <div style="border: 3px solid #FFD700; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #FFD700; margin: 0 0 10px 0;">👥 Private Coaching</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0; line-height: 1.4;">One-on-one instruction with a professional dance coach for maximum results.</p> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 0 0 5px 0;">Cost: $200</p> <p style="color: <<if _privateLessonsRemaining > 0>>#aaa<<else>>#ff6b6b<</if>>; font-size: 13px; margin: 0 0 auto 0;"> <<if _privateLessonsRemaining > 0>> <<= _privateLessonsRemaining>> session<<if _privateLessonsRemaining !== 1>>s<</if>> remaining this week <<else>> Weekly limit reached <</if>> </p> <<if _privateLessonsRemaining <= 0>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Weekly Limit Reached</div> <<elseif _canAffordPrivateLesson>> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Book Session</div>">> <<set _payment = setup.payAmount(200)>> <<if _payment.success>> <<goto "DancePrivateLesson">> <</if>> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Insufficient Funds</div> <</if>> </div> </div> <!-- Dancing Instructor Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Dancing Instructor")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">💃 Apply: Dancing Instructor</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Dancing Instructor")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">💃 Apply: Dancing Instructor</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #ff6b9d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0;">💃 Apply: Dancing Instructor</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $30/hour</p> <<link "<div style='background: #ff6b9d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "DancingInstructorJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Dancing Instructor Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Dancing Instructor">> <div style="border: 3px solid #ff6b9d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0;">💃 Dancing Instructor Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Teach dance classes at the studio! Choose from group classes, private lessons, or advanced workshops. (Max 8 hours/day)</p> <<link "<div style='background: #ff6b9d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Work Shift</div>">> <<goto "DancingInstructorWork">> <</link>> </div> <</if>> <!-- Dancing Instructors Section --> <<set _danceInstructors = []>> <<for _npc range $npcs>> <<set _hasDanceJob = false>> <<if typeof _npc.jobs === "string">> <<if _npc.jobs === "Dancing Instructor">> <<set _hasDanceJob = true>> <</if>> <<elseif Array.isArray(_npc.jobs)>> <<if _npc.jobs.includes("Dancing Instructor")>> <<set _hasDanceJob = true>> <</if>> <</if>> <<if _hasDanceJob>> <<run _danceInstructors.push(_npc)>> <</if>> <</for>> <<if _danceInstructors.length > 0>> <h2 style="color: #ff6b9d;">Instructors Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b9d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 15px; margin: 0 0 15px 0; font-style: italic;"> Professional dance instructors are available... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _danceInstructors>> <<capture _npc>> <div style="border: 3px solid #ff6b9d; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 5px 0;"> <em>Dancing Instructor</em> </p> <<link "<div style='background: #ff6b9d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> /* Criminal Heat-Based Arrest Check */ <<if $jobs && $jobs.includes("Criminal")>> <<if !$heat>> <<set $heat = 0>> <</if>> /* Calculate arrest chance: 1% at 0 heat, 90% at 100 heat */ <<set _arrestChance = 1 + ($heat * 0.89)>> <<set _arrestRoll = random(1, 100)>> <<if _arrestRoll <= _arrestChance>> <<goto "CaughtByPolice">> <</if>> <</if>> <<set $lastLocation = "TrainingCenter">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("TrainingCenter")>> <<run $visitedLocations.push("TrainingCenter")>> <</if>> <!-- Initialize training count for today --> <<if !$trainingCount>> <<set $trainingCount = 0>> <<set $lastTrainingDay = $dayNumber>> <</if>> <!-- Reset counter if it's a new day --> <<if $lastTrainingDay !== $dayNumber>> <<set $trainingCount = 0>> <<set $lastTrainingDay = $dayNumber>> <</if>> <!-- ===== SKILL TREE: Get bonuses ===== --> <<set _trainingReduction = setup.skillTree.getEffect("trainingReduction")>> <<set _statTrainingDiscount = setup.skillTree.getEffect("statTrainingDiscount")>> <!-- Calculate actual stat training cost --> <<set _baseStatCost = 25>> <<set _statTrainingCost = Math.max(5, _baseStatCost - _statTrainingDiscount)>> <!-- Initialize skill training progress --> <<if !$skillTrainingProgress>> <<set $skillTrainingProgress = { "Math Skills": {current: 0, required: 5, timesLearned: 0}, "Coding": {current: 0, required: 5, timesLearned: 0}, "Makeup": {current: 0, required: 5, timesLearned: 0}, "Cooking": {current: 0, required: 5, timesLearned: 0}, "Cleaning": {current: 0, required: 5, timesLearned: 0}, "First Aid": {current: 0, required: 5, timesLearned: 0}, "Painting": {current: 0, required: 5, timesLearned: 0} }>> <</if>> <!-- Check Quick Learner and Skill Tree bonus every time player enters --> <<for _skillName, _skillData range $skillTrainingProgress>> <<if !$skills.includes(_skillName)>> <!-- Calculate base requirement --> <<set _baseRequired = 5>> <!-- Apply Quick Learner reduction (also applies to Werefox transformation) --> <<if $skills.includes("Quick Learner") || $physicalTraits.includes("Werefox")>> <<set _baseRequired = 3>> <</if>> <!-- ===== SKILL TREE: Apply training reduction ===== --> <<if _trainingReduction > 0>> <<set _baseRequired = Math.max(1, _baseRequired - _trainingReduction)>> <</if>> <<set _skillData.required = _baseRequired>> <</if>> <</for>> <!-- Initialize weekly class limit tracker (5 classes per week) --> <<if !$weeklyClassesTaken>> <<set $weeklyClassesTaken = {week: 0, count: 0}>> <</if>> <!-- Calculate current week number (weeks start on Monday) --> <<set _currentWeek = Math.floor($dayNumber / 7)>> <!-- Reset weekly class count if new week --> <<if $weeklyClassesTaken.week !== _currentWeek>> <<set $weeklyClassesTaken = {week: _currentWeek, count: 0}>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #5c6bc0; text-align: center;">🎓 Bluefin Development Center</h1> <div style="padding: 20px; background: linear-gradient(135deg, #5c6bc0 0%, #3f51b5 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #5c6bc0;"> <p style="color: white; font-size: 18px; margin: 0;"> Modern classrooms equipped with the latest technology line the hallways. Whiteboards display complex diagrams and business strategies. Professionals gather here to sharpen their skills and advance their careers. </p> </div> <!-- Training Limit Display --> <div style="background: #2a2a2a; border: 3px solid #ffc107; padding: 18px; border-radius: 10px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="color: #ffc107; font-size: 18px; font-weight: bold;"> ⚡ Stat Training Sessions Remaining Today: <span style="color: #5c6bc0;"><<print 2 - $trainingCount>> / 2</span> </div> <div style="color: #51cf66; font-size: 18px; font-weight: bold; margin-top: 10px;"> 📚 Skill Classes Remaining This Week: <span style="color: <<if $weeklyClassesTaken.count >= 5>>#ff6b6b<<else>>#5c6bc0<</if>>;"> <<print 5 - $weeklyClassesTaken.count>> / 5 </span> </div> </div> <!-- ===== SKILL TREE: Bonus Display ===== --> <<if _trainingReduction > 0 || _statTrainingDiscount > 0>> <div style="background: #2a2a2a; border: 3px solid #9C27B0; padding: 15px; border-radius: 10px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #CE93D8; margin: 0 0 10px 0;">⭐ Skill Tree Bonuses Active</h3> <<if _statTrainingDiscount > 0>> <p style="color: #CE93D8; margin: 5px 0;">• Stat training cost reduced by $<<print _statTrainingDiscount>> (<span style="text-decoration: line-through;">$25</span> → $<<print _statTrainingCost>>)</p> <</if>> <<if _trainingReduction > 0>> <p style="color: #CE93D8; margin: 5px 0;">• Skill courses require <<print _trainingReduction>> fewer class<<if _trainingReduction !== 1>>es<</if>> to complete</p> <</if>> </div> <</if>> <h2 style="color: #5c6bc0;">Training Programs</h2> <!-- Stat Training --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #17a2b8; padding-bottom: 10px;">📊 Stat Training</h3> <p style="color: #aaa; font-size: 15px; margin: 0 0 20px 0;"> Intensive programs to boost your attributes. Train up to 2 times per day for <<if _statTrainingDiscount > 0>> <span style="text-decoration: line-through; color: #666;">$25</span> <span style="color: #51cf66;">$<<print _statTrainingCost>></span> <<else>> $25 <</if>> each. </p> <<if $trainingCount >= 2>> <div style="background: #1a1a1a; border: 3px solid #ffc107; padding: 15px; border-radius: 8px; text-align: center;"> <p style="color: #ffc107; margin: 0; font-weight: bold;">You have completed all training sessions for today. Come back tomorrow!</p> </div> <<else>> <<set _canAffordStatTraining = setup.canAffordTotal(_statTrainingCost)>> <<capture _statTrainingCost, _canAffordStatTraining>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <!-- Charisma Training --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #e91e63; margin: 0 0 10px 0;">💬 Charisma</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Current: $stats.charisma</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0;"> Cost: <<if _statTrainingDiscount > 0>> <span style="text-decoration: line-through; color: #666;">$25</span> $<<print _statTrainingCost>> <<else>> $<<print _statTrainingCost>> <</if>> </p> <<if $stats.charisma >= $statMaxCaps.charisma>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Max Reached</div> <<elseif !_canAffordStatTraining>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Train (+1)</div>">> <<set _payment = setup.payAmount(_statTrainingCost)>> <<if _payment.success>> <<set $stats.charisma += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Dexterity Training --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #51cf66; margin: 0 0 10px 0;">🤸 Dexterity</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Current: $stats.dexterity</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0;"> Cost: <<if _statTrainingDiscount > 0>> <span style="text-decoration: line-through; color: #666;">$25</span> $<<print _statTrainingCost>> <<else>> $<<print _statTrainingCost>> <</if>> </p> <<if $stats.dexterity >= $statMaxCaps.dexterity>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Max Reached</div> <<elseif !_canAffordStatTraining>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Train (+1)</div>">> <<set _payment = setup.payAmount(_statTrainingCost)>> <<if _payment.success>> <<set $stats.dexterity += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Strength Training --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #ff6b6b; margin: 0 0 10px 0;">💪 Strength</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Current: $stats.strength</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0;"> Cost: <<if _statTrainingDiscount > 0>> <span style="text-decoration: line-through; color: #666;">$25</span> $<<print _statTrainingCost>> <<else>> $<<print _statTrainingCost>> <</if>> </p> <<if $stats.strength >= $statMaxCaps.strength>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Max Reached</div> <<elseif !_canAffordStatTraining>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Train (+1)</div>">> <<set _payment = setup.payAmount(_statTrainingCost)>> <<if _payment.success>> <<set $stats.strength += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Intelligence Training --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: #9b59b6; margin: 0 0 10px 0;">🧠 Intelligence</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Current: $stats.intelligence</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0;"> Cost: <<if _statTrainingDiscount > 0>> <span style="text-decoration: line-through; color: #666;">$25</span> $<<print _statTrainingCost>> <<else>> $<<print _statTrainingCost>> <</if>> </p> <<if $stats.intelligence >= $statMaxCaps.intelligence>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Max Reached</div> <<elseif !_canAffordStatTraining>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Train (+1)</div>">> <<set _payment = setup.payAmount(_statTrainingCost)>> <<if _payment.success>> <<set $stats.intelligence += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> </div> <</capture>> <</if>> </div> <!-- Skill Courses --> <<set _canAffordSkillCourse = setup.canAffordTotal(75)>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ffc107; padding-bottom: 10px;">📚 Skill Courses</h3> <p style="color: #aaa; font-size: 15px; margin: 0 0 20px 0;">Learn professional skills through multiple sessions ($75 per session, 8 hours each). You can take up to 5 classes per week total.</p> <<if $weeklyClassesTaken.count >= 5>> <div style="background: #1a1a1a; border: 3px solid #ffc107; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 20px;"> <p style="color: #ffc107; margin: 0; font-weight: bold;">You have taken all 5 classes this week. Come back next week to learn more!</p> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;"> <!-- Math Skills --> <<set _hasSkill = $skills.includes("Math Skills")>> <<set _progress = $skillTrainingProgress["Math Skills"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#9b59b6<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#9b59b6<</if>>; margin: 0 0 10px 0;">🔢 Math Skills</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +5 Intelligence</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["Math Skills"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["Math Skills"].current >= $skillTrainingProgress["Math Skills"].required>> <<set $skills.push("Math Skills")>> <<set $stats.intelligence += 5>> <<set $skillTrainingProgress["Math Skills"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Coding --> <<set _hasSkill = $skills.includes("Coding")>> <<set _progress = $skillTrainingProgress["Coding"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#9b59b6<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#9b59b6<</if>>; margin: 0 0 10px 0;">💻 Coding</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +6 Intelligence</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["Coding"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["Coding"].current >= $skillTrainingProgress["Coding"].required>> <<set $skills.push("Coding")>> <<set $stats.intelligence += 6>> <<set $skillTrainingProgress["Coding"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Makeup --> <<set _hasSkill = $skills.includes("Makeup")>> <<set _progress = $skillTrainingProgress["Makeup"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#e91e63<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#e91e63<</if>>; margin: 0 0 10px 0;">💄 Makeup</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +3 Dexterity, +3 Charisma</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["Makeup"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["Makeup"].current >= $skillTrainingProgress["Makeup"].required>> <<set $skills.push("Makeup")>> <<set $stats.dexterity += 3>> <<set $stats.charisma += 3>> <<set $skillTrainingProgress["Makeup"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Cooking --> <<set _hasSkill = $skills.includes("Cooking")>> <<set _progress = $skillTrainingProgress["Cooking"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#ffc107<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#ffc107<</if>>; margin: 0 0 10px 0;">🍳 Cooking</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +3 Intelligence, +2 Dexterity</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["Cooking"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["Cooking"].current >= $skillTrainingProgress["Cooking"].required>> <<set $skills.push("Cooking")>> <<set $stats.intelligence += 3>> <<set $stats.dexterity += 2>> <<set $skillTrainingProgress["Cooking"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Cleaning --> <<set _hasSkill = $skills.includes("Cleaning")>> <<set _progress = $skillTrainingProgress["Cleaning"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#17a2b8<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#17a2b8<</if>>; margin: 0 0 10px 0;">🧹 Cleaning</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +3 Dexterity</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["Cleaning"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["Cleaning"].current >= $skillTrainingProgress["Cleaning"].required>> <<set $skills.push("Cleaning")>> <<set $stats.dexterity += 3>> <<set $skillTrainingProgress["Cleaning"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- First Aid --> <<set _hasSkill = $skills.includes("First Aid")>> <<set _progress = $skillTrainingProgress["First Aid"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#dc3545<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#dc3545<</if>>; margin: 0 0 10px 0;">🏥 First Aid</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +4 Intelligence</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["First Aid"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["First Aid"].current >= $skillTrainingProgress["First Aid"].required>> <<set $skills.push("First Aid")>> <<set $stats.intelligence += 4>> <<set $skillTrainingProgress["First Aid"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> <!-- Painting --> <<set _hasSkill = $skills.includes("Painting")>> <<set _progress = $skillTrainingProgress["Painting"]>> <div style="border: 3px solid <<if _hasSkill>>#51cf66<<else>>#ff6b6b<</if>>; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 2px 4px rgba(0,0,0,0.3); display: flex; flex-direction: column;"> <h4 style="color: <<if _hasSkill>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 10px 0;">🎨 Painting</h4> <<if _hasSkill>> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0; font-weight: bold;">✓ Mastered</p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Progress: _progress.current / _progress.required</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Cost: $75 per session</p> <p style="color: #666; font-size: 12px; margin: 0 0 10px 0;">Bonus: +4 Dexterity, +3 Intelligence</p> <</if>> <<if _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Already Learned</div> <<elseif $weeklyClassesTaken.count >= 5>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Weekly Limit Reached</div> <<elseif !_canAffordSkillCourse>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;">Insufficient Funds</div> <<else>> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: auto;'>Take Class (8 hours, $75)</div>">> <<set _payment = setup.payAmount(75)>> <<if _payment.success>> <<set $skillTrainingProgress["Painting"].current += 1>> <<set $weeklyClassesTaken.count += 1>> <<if $skillTrainingProgress["Painting"].current >= $skillTrainingProgress["Painting"].required>> <<set $skills.push("Painting")>> <<set $stats.dexterity += 4>> <<set $stats.intelligence += 3>> <<set $skillTrainingProgress["Painting"].current = 0>> <<run setup.achievements.unlock("bluefin_skill")>> <</if>> <<advancetime 480>> <</if>> <<goto "TrainingCenter">> <</link>> <</if>> </div> </div> </div> <br> <!-- NPCs Present --> <<set _npcsHere = setup.getNPCsAtLocation("TrainingCenter")>> <h2 style="color: #5c6bc0;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #5c6bc0; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #5c6bc0; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #5c6bc0; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"> <<if Array.isArray(_npc.jobs)>> <<print _npc.jobs.join(", ")>> <<else>> <<print _npc.jobs>> <</if>> </p> <<link "<div style='background: #5c6bc0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The training center is empty right now. No one else is here. </p> </div> <</if>> <br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- Vending Machine --> <div style="border: 3px solid #00b894; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #55efc4; margin: 0 0 10px 0;">🍫 Vending Machine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Grab a quick snack or drink.</p> <<link "<div style='background: #00b894; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Machine</div>">> <<goto "VendingMachineShop">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "TownHall">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("TownHall")>> <<run $visitedLocations.push("TownHall")>> <</if>> /* Check if player is a Criminal and arrest them */ <<if $jobs && $jobs.includes("Criminal")>> <<set $arrestedAtStation = true>> <<goto "CaughtByPolice">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">🏛️ Town Hall</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/TownHall.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Town Hall"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #8e44ad 0%, #6c3483 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> An imposing stone building with grand columns and marble floors. The halls echo with the footsteps of bureaucrats and citizens alike. Official notices and city announcements line bulletin boards near the entrance. The air carries the weight of civic authority. </p> </div> <!-- Legal Name Change Section --> <h2 style="color: #9b59b6;">📜 City Services</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<if $hasChangedNameLegally>> <!-- Already changed name --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">📝 Legal Name Change</h3> <p style="font-size: 14px; color: #666; margin: 0;">You have already used your one-time legal name change. Sunfish City law only permits one official name change per citizen.</p> </div> <<else>> <!-- Can still change name --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">📝 Legal Name Change</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0;">File paperwork to legally change your name. This service can only be used <strong style="color: #e74c3c;">once</strong>.</p> <p style="font-size: 13px; color: #888; margin: 0 0 15px 0;">Current Name: <strong style="color: #9b59b6;"><<= $firstName>> <<= $lastName>></strong></p> <p style="font-size: 14px; color: #f1c40f; margin: 0 0 15px 0;">💰 Cost: <strong>$2,500</strong></p> <<if $money >= 2500>> <div style="margin-bottom: 15px;"> <label style="color: #ccc; display: block; margin-bottom: 5px;">New First Name:</label> <<textbox "_newLegalFirst" "" autofocus>> </div> <div style="margin-bottom: 15px;"> <label style="color: #ccc; display: block; margin-bottom: 5px;">New Last Name:</label> <<textbox "_newLegalLast" "">> </div> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Submit Name Change ($2,500)</div>">> <<if _newLegalFirst && _newLegalFirst.trim() !== "" && _newLegalLast && _newLegalLast.trim() !== "">> <<set $money -= 2500>> <<set $firstName = _newLegalFirst.trim()>> <<set $lastName = _newLegalLast.trim()>> <<set $hasChangedNameLegally = true>> <<run setup.achievements.unlock("townhall_name_change")>> <<run UI.alert("Your name has been legally changed to " + $firstName + " " + $lastName + "!")>> <<goto "TownHall">> <<else>> <<run UI.alert("Please enter both a first and last name.")>> <</if>> <</link>> <<else>> <div style="background: #3d1a1a; padding: 10px; border-radius: 6px; border: 1px solid #e74c3c;"> <p style="color: #e74c3c; margin: 0; font-size: 14px;">⚠️ You need $2,500 to file for a name change. You only have $<<print $money>>.</p> </div> <</if>> </div> <</if>> <!-- Donate to the City --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-top: 15px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">💚 Donate to Sunfish City</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0;">Support your community by donating all your on-hand money to city improvement projects.</p> <p style="font-size: 13px; color: #888; margin: 0 0 15px 0;">Current On-Hand Cash: <strong style="color: #2ecc71;">$<<print $money>></strong></p> <<if $money > 0>> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Donate All ($<<print $money>>)</div>">> <<set _donationAmount = $money>> <<set $totalDonatedToCity = ($totalDonatedToCity || 0) + _donationAmount>> <<set $money = 0>> <<run UI.alert("Thank you for your generous donation of $" + _donationAmount + " to Sunfish City! Your contribution will help improve our community.")>> <<goto "TownHall">> <</link>> <<else>> <div style="background: #2a2a2a; padding: 10px; border-radius: 6px; border: 1px solid #666;"> <p style="color: #888; margin: 0; font-size: 14px;">You don't have any money to donate.</p> </div> <</if>> <<if $totalDonatedToCity > 0>> <p style="font-size: 12px; color: #666; margin: 15px 0 0 0; text-align: center;">Total donated to date: <strong style="color: #2ecc71;">$<<print $totalDonatedToCity>></strong></p> <</if>> </div> </div> <!-- Property Listings Section --> <<if !$cafeOwnership>><<set $cafeOwnership = {owned: false, cafeName: "Maid Cafe", questsCompleted: [], dayPurchased: 0, upgrades: {decor: 0, kitchen: 0, furniture: 0, entertainment: 0, vipRoom: 0, staffRoom: 0}, staff: [], hasManager: false, finances: {totalRevenue: 0, totalExpenses: 0, totalProfit: 0, yesterdayRevenue: 0, yesterdayExpenses: 0, yesterdayProfit: 0}, reputation: 0, customersToday: 0, menuItems: [], inventory: {flour: 0, sugar: 0, teaLeaves: 0, butter: 0, eggs: 0, freshFish: 0, vegetables: 0, coffeeBeans: 0, milk: 0, chocolate: 0, berries: 0, cream: 0, exoticSpices: 0, honey: 0, vanilla: 0, edibleFlowers: 0}, playerCookingProf: 0, lastMilkProduced: 0, lastHoneyProduced: 0, pendingSupplierOrder: null}>><</if>> <<if !$cafeOwnership.owned>> <<set $cafeOwnership.viewedListings = true>> <h2 style="color: #2ecc71;">🏠 Property Listings</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🏚 Rundown Cafe — Outskirts</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0; line-height: 1.4;">A dilapidated cafe building on the outskirts of town. Needs significant renovation but has potential. The city requires proof of community commitment before approving the sale.</p> <p style="font-size: 14px; color: #ffd700; font-weight: bold; margin: 0 0 15px 0;">Purchase Price: $15,000</p> <!-- Quest Progress Checklist --> <<set _cafeProgress = setup.getCafeQuestProgress()>> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Requirements (<<= _cafeProgress.completed>>/<<= _cafeProgress.total>> complete):</p> <div style="display: grid; gap: 6px; margin-bottom: 15px;"> <<set _q1 = $cafeOwnership.questsCompleted.includes("cafe_donation")>> <p style="margin: 0; font-size: 13px; color: <<if _q1>>#51cf66<<else>>#888<</if>>;"><<if _q1>>✅<<else>>⬜<</if>> Generous Citizen — Donate $5,000 to the city <<if !_q1>>($<<= $totalDonatedToCity || 0>>/$5,000)<</if>></p> <<set _q2 = $cafeOwnership.questsCompleted.includes("cafe_community_service")>> <p style="margin: 0; font-size: 13px; color: <<if _q2>>#51cf66<<else>>#888<</if>>;"><<if _q2>>✅<<else>>⬜<</if>> Hard Worker — Work 40 total hours <<if !_q2>>(<<= $totalHoursWorked || 0>>/40)<</if>></p> <<set _q3 = $cafeOwnership.questsCompleted.includes("cafe_social_standing")>> <p style="margin: 0; font-size: 13px; color: <<if _q3>>#51cf66<<else>>#888<</if>>;"><<if _q3>>✅<<else>>⬜<</if>> Well Connected — 5 NPCs at relationship level 2+</p> <<set _q4 = $cafeOwnership.questsCompleted.includes("cafe_business_exp")>> <p style="margin: 0; font-size: 13px; color: <<if _q4>>#51cf66<<else>>#888<</if>>;"><<if _q4>>✅<<else>>⬜<</if>> Financially Capable — Earn $10,000 total from jobs</p> <<set _q5 = $cafeOwnership.questsCompleted.includes("cafe_culinary")>> <p style="margin: 0; font-size: 13px; color: <<if _q5>>#51cf66<<else>>#888<</if>>;"><<if _q5>>✅<<else>>⬜<</if>> Food Service Ready — Have the Cooking skill</p> <<set _q6 = $cafeOwnership.questsCompleted.includes("cafe_customer_service")>> <p style="margin: 0; font-size: 13px; color: <<if _q6>>#51cf66<<else>>#888<</if>>;"><<if _q6>>✅<<else>>⬜<</if>> People Person — Customer Service skill or Kind trait</p> <<set _q7 = $cafeOwnership.questsCompleted.includes("cafe_city_builder")>> <p style="margin: 0; font-size: 13px; color: <<if _q7>>#51cf66<<else>>#888<</if>>;"><<if _q7>>✅<<else>>⬜<</if>> City Builder — Complete a construction project or donate $7,000+ total</p> </div> <!-- Purchase Button --> <<if _cafeProgress.completed >= 7>> <<if $money >= 15000>> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>🏠 Purchase Cafe — $15,000</div>">> <<set $money -= 15000>> <<goto "CafeAcquisition">> <</link>> <<else>> <div style="background: #444; color: #999; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money ($<<= $money>>/$15,000)</div> <</if>> <<else>> <div style="background: #333; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Complete all requirements first</div> <</if>> </div> </div> <</if>> <!-- City Mayor Work Section --> <<if $jobs && $jobs.length > 0 && $jobs.includes("City Mayor")>> <<if !$mayorHoursWorkedToday>> <<set $mayorHoursWorkedToday = 0>> <</if>> <h2 style="color: #FFD700;">Mayoral Duties</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #FFD700; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #FFD700; margin: 0 0 10px 0;">👑 Oversee City Operations</h3> <<if $mayorHoursWorkedToday >= 4>> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0; font-weight: bold;">You've already completed your mayoral duties for today (4/4 hours).</p> <div style="background: #333; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; border: 2px solid #444;">Perform Mayoral Duties</div> <<else>> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0;">Attend to your mayoral responsibilities... or at least appear to.</p> <p style="font-size: 12px; color: #aaa; margin: 0 0 15px 0;">Hours worked today: <span style="color: #FFD700; font-weight: bold;"><<print $mayorHoursWorkedToday>>/4</span></p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Perform Mayoral Duties</div>">> <<goto "MayorWork">> <</link>> <</if>> </div> </div> <</if>> <!-- Mayor's Secretary Work Section --> <<if $jobs && $jobs.length > 0 && $jobs.includes("Mayor's Secretary")>> <h2 style="color: #9b59b6;">Secretary Work</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<if !$secretaryHoursWorkedToday>> <<set $secretaryHoursWorkedToday = 0>> <</if>> <<if $secretaryHoursWorkedToday >= 8>> <!-- Work limit reached --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">📋 Attend to Secretarial Duties</h3> <p style="font-size: 14px; color: #666; margin: 0 0 15px 0;">You've already worked your full 8-hour shift today.</p> <p style="font-size: 14px; color: #888; margin: 0;">Hours worked today: $secretaryHoursWorkedToday/8</p> </div> <<else>> <!-- Can still work --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">📋 Attend to Secretarial Duties</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0;">Handle your responsibilities as the mayor's secretary.</p> <p style="font-size: 13px; color: #888; margin: 0 0 15px 0;">Hours worked today: $secretaryHoursWorkedToday/8</p> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Begin Work</div>">> <<goto "SecretaryWork">> <</link>> </div> <</if>> </div> <</if>> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<set _secretaryNPCs = setup.getNPCsByJob("Mayor's Secretary")>> <<set _townHallNPCs = setup.getNPCsAtLocation("TownHall")>> <h2 style="color: #9b59b6;">City Government</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 20px;"> <!-- Mayor's Office --> <<if _mayorNPCs.length > 0>> <<set _mayorNPC = _mayorNPCs[0]>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🎩 Mayor's Office</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;"><strong style="color: #9b59b6;"><<print _mayorNPC.name>></strong> - City Mayor</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 15px;">The highest authority in Sunfish City.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Meet the Mayor</div>">> <<set $tradingWithNPC = _mayorNPC>> <<goto "NPCInteraction">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🎩 Mayor's Office</h3> <p style="font-size: 14px; color: #666;">No mayor currently appointed.</p> </div> <</if>> <!-- Secretary's Office --> <<if _secretaryNPCs.length > 0>> <<set _secretaryNPC = _secretaryNPCs[0]>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">📋 Secretary's Office</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;"><strong style="color: #9b59b6;"><<print _secretaryNPC.name>></strong> - Mayor's Secretary</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 15px;">Handles appointments and city business.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Talk to Secretary</div>">> <<set $tradingWithNPC = _secretaryNPC>> <<goto "NPCInteraction">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">📋 Secretary's Office</h3> <p style="font-size: 14px; color: #666;">No secretary currently appointed.</p> </div> <</if>> </div> <<if setup.questSystem && setup.questSystem.isQuestActive("mikla_investigate_city") && $questData.active["mikla_investigate_city"].step === "investigate" && !$miklaTownHallInvestigated && ($jobs.includes("City Mayor") || $jobs.includes("Mayor's Secretary") || _mayorNPCs.length === 0)>> <h2 style="color:#d98a3d; margin-top:25px;">A Closer Look</h2> <div style="border: 3px solid #d98a3d; border-radius: 10px; padding: 15px; background: #1c130b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <p style="font-size: 14px; color: #f0cf95; margin: 0 0 10px 0;">With the run of the offices, you could search this place properly. Read what the city keeps behind its grand doors, and what it does not.</p> <p style="font-size: 12px; color: #b0895a; margin: 0 0 15px 0; font-style: italic;">You may search freely while you hold the City Mayor or Mayor's Secretary post, or while the mayor's seat sits empty.</p> <<link "<div class='mikla-btn'>Search the offices and records</div>">> <<if setup.canCombineTap() && !$miklaTownHallInvestigated>> <<set $miklaTownHallInvestigated = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "TownHallInvestigate">> <</if>> <</link>> </div> <</if>> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("TownHall")>> <<set _otherNPCs = []>> <!-- Filter out Mayor and Secretary since they have dedicated sections --> <<if _npcsHere && _npcsHere.length > 0>> <<for _npc range _npcsHere>> <<set _isMayor = false>> <<set _isSecretary = false>> <<if _npc.jobs.includes("City Mayor")>> <<set _isMayor = true>> <</if>> <<if _npc.jobs.includes("Mayor's Secretary")>> <<set _isSecretary = true>> <</if>> <<if !_isMayor && !_isSecretary>> <<run _otherNPCs.push(_npc)>> <</if>> <</for>> <</if>> <<if _otherNPCs.length > 0>> <h2 style="color: #9b59b6; margin-top: 25px;">🏛️ Visitors</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #b19cd9; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic;"> Others are here conducting city business... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _otherNPCs>> <<capture _npc>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #b19cd9; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <</if>> <br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Gym">> <h1>💪 Training Complete!</h1> <div style="padding: 25px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); text-align: center;"> <h2 style="color: white; margin: 0 0 10px 0; font-size: 32px;">✅ Workout Session Complete</h2> <p style="color: white; margin: 0; font-size: 18px;">You've finished your training</p> </div> <!-- Training Message Based on Strength Level --> <div style="background: white; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e74c3c; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"> <<if $stats.strength >= 100>> <h2 style="color: #ffd700; margin-top: 0; text-align: center;">🏆 LEGENDARY PHYSIQUE</h2> <p style="color: #333; font-size: 16px; line-height: 1.8; text-align: center;"> You've achieved the pinnacle of human strength. Your body is a perfect sculpture of muscle and power. Other gym-goers stop their workouts just to watch you in awe. The weights you lift seem impossibly heavy to everyone else, yet you handle them with casual ease. You've transcended ordinary fitness - you're a living legend. </p> <<elseif $stats.strength >= 71>> <h2 style="color: #e74c3c; margin-top: 0; text-align: center;">💪 ELITE ATHLETE</h2> <p style="color: #333; font-size: 16px; line-height: 1.8;"> You crush your workout with incredible intensity. The heavy weights that once seemed impossible now feel manageable. Your form is impeccable, every rep controlled and powerful. Other gym members frequently ask you for advice, recognizing your expertise. Your body has transformed into a powerhouse of muscle and definition. You're approaching the limits of natural human strength. </p> <<elseif $stats.strength >= 51>> <h2 style="color: #e74c3c; margin-top: 0; text-align: center;">🔥 ADVANCED LIFTER</h2> <p style="color: #333; font-size: 16px; line-height: 1.8;"> You power through an intense training session. The weights feel heavy but manageable as you push yourself harder than before. Your muscles burn with satisfying exertion. You're noticing significant changes in your physique - more definition, more mass, more power. People are starting to notice your transformation. You're becoming a regular force in the gym. </p> <<elseif $stats.strength >= 21>> <h2 style="color: #e74c3c; margin-top: 0; text-align: center;">💪 INTERMEDIATE GAINS</h2> <p style="color: #333; font-size: 16px; line-height: 1.8;"> You complete a solid workout, feeling the satisfying pump in your muscles. The exercises are getting easier as your body adapts and grows stronger. You're starting to see real changes in the mirror - your arms are filling out your sleeves a bit more, your shoulders are broader. The initial soreness is fading, replaced by a sense of capability and confidence. </p> <<else>> <h2 style="color: #e74c3c; margin-top: 0; text-align: center;">🌱 BEGINNER GAINS</h2> <p style="color: #333; font-size: 16px; line-height: 1.8;"> You work through your training routine, muscles trembling from the unfamiliar exertion. Everything feels heavy and awkward, but you push through it. Sweat pours down your face as you struggle with weights that more experienced lifters handle easily. Your form needs work, but you're learning. By the end, you're exhausted but proud - you showed up and did the work. That's what matters at this stage. </p> <</if>> </div> <!-- Stats Display --> <div style="background: white; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745;"> <h3 style="color: #28a745; margin-top: 0; text-align: center;">📊 Strength Progress</h3> <div style="text-align: center;"> <p style="color: #333; font-size: 18px; margin: 10px 0;"> <strong>Previous Strength:</strong> <span style="color: #666;"><<print $stats.strength - 1>></span> </p> <p style="color: #28a745; font-size: 24px; font-weight: bold; margin: 10px 0;"> ⬆️ +1 Strength </p> <p style="color: #333; font-size: 18px; margin: 10px 0;"> <strong>Current Strength:</strong> <span style="color: #e74c3c; font-weight: bold;">$stats.strength</span> / $statMaxCaps.strength </p> </div> </div> <!-- Time Display --> <div style="background: #fff3cd; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; margin-bottom: 25px; text-align: center;"> <p style="color: #856404; margin: 0; font-weight: bold;"> ⏰ Time passed: 1 hour </p> </div> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.2);'>Continue Training</div>">> <<goto "Gym">> <</link>> <br><br> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.2);'>Leave Gym</div>">> <<goto "BusinessDistrict">> <</link>> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> /* Quesha unique-dialogue safety hook: attach if missing on existing saves. */ <<if _npc && (_npc.originalName === "Quesha Epo" || _npc.name === "Quesha Epo") && !_npc.uniqueDialogue && setup.queshaDialogue>> <<set _npc.uniqueDialogue = setup.queshaDialogue>> <</if>> <<if !_npc>> <<set _exitTo = $preNPCLocation || $lastLocation || "Downtown">> <<goto _exitTo>> <<else>> <<set _relationship = $relationships[_npc.name] || {level: 1, points: 0}>> <<set _relLevel = _relationship.level>> <<set _npcPrefs = setup.getNPCPreferences(_npc)>> <<set _moodData = setup.calculateNPCMood(_npc, true)>> <<set _moodDef = setup.moodDefinitions[_moodData.name] || setup.moodDefinitions.neutral>> <<set _moodDesc = setup.getMoodDescription(_npc)>> <<set _relColor = setup.getRelationshipColor(_relLevel)>> <<set _levelData = setup.getRelationshipLevelData(_relLevel)>> <<set _levelName = _levelData ? _levelData.name : "Unknown">> <<set _isRomantic = setup.romance.isRomantic(_npc.name)>> <<if _isRomantic>> <<set _romLevel = setup.romance.getRomanceLevel(_npc.name)>> <<set _romData = setup.romance.levels[_romLevel]>> <<if _romData>> <<set _levelName = _romData.icon + " " + _romData.name>> <<set _relColor = _romData.color>> <</if>> <</if>> <<set _npcJob = _npc.jobs[0] || "Unemployed">> <<set _ilKey = setup.islandLore.keyForNPC(_npc)>> <<if setup.islandLore.isAskable(_ilKey)>> <div style="background:linear-gradient(135deg,#1a1430,#0e0a1c); border:2px solid #7a6aa8; border-radius:10px; padding:14px 16px; margin-bottom:15px;"> <p style="color:#cdbdf0; font-size:15px; line-height:1.6; margin:0 0 10px 0;">You steer the talk toward the island itself. How does this place work? How long has it stood?</p> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#7a6aa8,#4a3d70); color:white; padding:9px 22px; border-radius:9px; font-weight:bold; cursor:pointer;'>Ask about the island</div>">> <<if setup.canCombineTap()>> <<set $lastLocationBeforeAsk = $preNPCLocation || $lastLocation>> <<run setup.islandLore.recordAsk(_ilKey)>> <<goto "IslandLoreAccount">> <</if>> <</link>> </div> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> /* Header: NPC Name + Job + Mood Emoji */ <div style="background: #2a2a2a; padding: 15px 20px; border-radius: 12px; margin-bottom: 15px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #667eea; box-shadow: 0 3px 6px rgba(0,0,0,0.4);"> <div> <div style="color: white; font-size: 26px; font-weight: bold; margin: 0;">_npc.name</div> <div style="color: #aaa; font-size: 14px; margin-top: 4px;"><<print _npcJob>></div> </div> <span style="font-size: 36px;"><<print _moodDef.icon>></span> </div> /* Relationship Progress Bar */ <<if _isRomantic>> <<set _romLevelOrder = ["dating", "exclusive", "lover", "soulmate"]>> <<set _romThresholds = [75, 175, 350, 600]>> <<set _romIdx = _romLevelOrder.indexOf(_romLevel)>> <<if _romIdx < 0>><<set _romIdx = 0>><</if>> <<set _currentLevelMin = _romThresholds[_romIdx]>> <<if _romIdx < 3>> <<set _nextThreshold = _romThresholds[_romIdx + 1]>> <<else>> <<set _nextThreshold = _romThresholds[3]>> <</if>> <<set _barPoints = ($npcRomance && $npcRomance[_npc.name] && typeof $npcRomance[_npc.name].romancePoints === "number") ? $npcRomance[_npc.name].romancePoints : 0>> <<set _xpInLevel = _barPoints - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <<if _xpPercent < 0>><<set _xpPercent = 0>><</if>> <<if _xpPercent > 100>><<set _xpPercent = 100>><</if>> <<set _showProgressBar = (_romLevel !== "soulmate")>> <<elseif _relLevel < 5>> <<set _showProgressBar = true>> <<if _relLevel === -1>> <<set _currentLevelMin = -50>> <<set _nextThreshold = 0>> <<elseif _relLevel === 0>> <<set _currentLevelMin = 0>> <<set _nextThreshold = 25>> <<elseif _relLevel === 1>> <<set _currentLevelMin = 25>> <<set _nextThreshold = 75>> <<elseif _relLevel === 2>> <<set _currentLevelMin = 75>> <<set _nextThreshold = 175>> <<elseif _relLevel === 3>> <<set _currentLevelMin = 175>> <<set _nextThreshold = 425>> <<else>> <<set _currentLevelMin = 425>> <<set _nextThreshold = 600>> <</if>> <<set _barPoints = _relationship.points>> <<set _xpInLevel = _relationship.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <<if _xpPercent < 0>><<set _xpPercent = 0>><</if>> <<if _xpPercent > 100>><<set _xpPercent = 100>><</if>> <<else>> <<set _showProgressBar = false>> <</if>> <div style="background: #2a2a2a; padding: 12px 15px; border-radius: 10px; margin-bottom: 15px; border: 1px solid #444;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> <span @style="'color: ' + _relColor + '; font-weight: bold; font-size: 15px;'"><<print _levelName>></span> <<if _showProgressBar>> <span style="color: #888; font-size: 13px;"><<print _barPoints>> / <<print _nextThreshold>> pts</span> <<else>> <span style="color: #ffd700; font-size: 13px; font-weight: bold;">MAX</span> <</if>> </div> <<if _showProgressBar>> <div @style="'background: #111; border: 1px solid ' + _relColor + '; border-radius: 6px; height: 14px; position: relative; overflow: hidden;'"> <div @style="'background: ' + _relColor + '; height: 100%; width: ' + _xpPercent + '%; transition: width 0.3s ease; border-radius: 6px;'"></div> </div> <<else>> <div @style="'background: #111; border: 1px solid ' + _relColor + '; border-radius: 6px; height: 14px; position: relative; overflow: hidden;'"> <div @style="'background: ' + _relColor + '; height: 100%; width: 100%; border-radius: 6px;'"></div> </div> <</if>> </div> /* Mood Card */ <div @style="'background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 15px; border: 2px solid ' + _moodDef.color + ';'"> <div style="display: flex; align-items: center; gap: 12px;"> <span style="font-size: 28px;"><<print _moodDef.icon>></span> <div> <span @style="'color: ' + _moodDef.color + '; font-weight: bold; font-size: 16px;'"><<print _moodDef.label>></span> <div style="color: #999; font-size: 13px; margin-top: 2px;"><<print _moodDesc>></div> </div> </div> </div> <<if setup.traitEvolution && setup.traitEvolution.hasRecentEvolution(_npc.name)>> <div style="color: #FFD54F; font-size: 14px; margin-bottom: 8px; font-style: italic;"> ✨ Something about <<= _npc.name>> seems different lately... </div> <</if>> /* NPC Greeting */ <div style="background: #2a2a2a; padding: 18px; border-radius: 10px; margin-bottom: 15px; border-left: 4px solid #9b59b6;"> <<set _greetParsed = setup.extractEmote(setup.getNPCGreeting(_npc, _relLevel))>> <<if _greetParsed.emote>><div style="color: #999; font-size: 15px; margin-bottom: 8px; font-style: italic;"><<= _greetParsed.emote>></div><</if>> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "<<= _greetParsed.text>>" </div> </div> /* Conversation Options - grouped by category */ <<set _availableOptions = setup.getAvailableConversationOptions(_npc, _relLevel)>> <<for _adjIdx = 0; _adjIdx < _availableOptions.length; _adjIdx++>><<set _availableOptions[_adjIdx].option.label = setup.getMemoryAdjustedLabel(_npc.name, _availableOptions[_adjIdx].option)>><</for>> <<set _groupOrder = ["core", "personality", "shared", "relationship", "risky", "moodGated", "memoryGated", "npcSocial", "romantic"]>> <<set _grouped = {}>> <<for _opt range _availableOptions>> <<if !_grouped[_opt.category]>><<set _grouped[_opt.category] = []>><</if>> <<run _grouped[_opt.category].push(_opt)>> <</for>> <<set _catBorderColors = { "core": "#17a2b8", "personality": "#e91e63", "shared": "#00e5ff", "relationship": "#9b59b6", "risky": "#ff6b6b", "moodGated": "#ff9800", "memoryGated": "#CE93D8", "npcSocial": "#26c6da", "romantic": "#e91e63" }>> <<set _catNames = { "core": "💬 General", "personality": "🎭 Personality", "shared": "🤝 Shared Interests", "relationship": "💜 Relationship", "risky": "⚡ Risky", "moodGated": "🌤️ Mood", "memoryGated": "🧠 Memories", "npcSocial": "🗣️ Social", "romantic": "💕 Romance" }>> <style> .npc-dropdown summary { list-style: none; cursor: pointer; } .npc-dropdown summary::-webkit-details-marker { display: none; } .npc-dropdown summary::marker { display: none; content: ""; } .npc-dropdown .npc-chevron { transition: transform 0.25s ease; display: inline-block; } .npc-dropdown[open] .npc-chevron { transform: rotate(180deg); } .npc-dropdown[open] summary { border-radius: 12px 12px 0 0; border-bottom: none; } .npc-dropdown:not([open]) summary { border-radius: 12px; } .npc-dropdown .npc-options { border-radius: 0 0 12px 12px; border-top: none; } @keyframes questPulse { 0%, 100% { box-shadow: 0 0 10px #ffd70044; } 50% { box-shadow: 0 0 20px #ffd70088, 0 0 30px #ffd70044; } } </style> /* Witch spells cast in conversation */ <<if setup.witchSpells && setup.witchSpells.isSpellcaster() && (setup.witchSpells.knows("Beguile") || setup.witchSpells.knows("Entrancement"))>> <div style="background: #1c1028; border: 1px solid #7b1fa2; border-radius: 10px; padding: 10px 14px; margin-bottom: 12px;"> <div style="color: #CE93D8; font-size: 13px; font-weight: bold; margin-bottom: 6px;">🪄 Spells</div> <<if setup.witchSpells.knows("Beguile")>> <<if setup.witchSpells.beguileActiveFor(_npc.name)>> <div style="color: #a78bfa; font-size: 12px;">💫 Beguile is woven around <<print _npc.name>> until tomorrow.</div> <<elseif ($witchMana || 0) >= 20>> <<link "<span style='color: #e040fb; cursor: pointer; font-size: 13px;'>💫 Cast Beguile (20 mana)</span>">> <<if setup.witchSpells.canTap()>> <<run setup.witchSpells.spendMana(20)>> <<set $beguileTarget = _npc.name>> <<set $beguileDay = $dayNumber>> <<run setup.questSystem.addNotification("updated", "Beguile settles over " + State.variables.beguileTarget + ". Your words will land twice as warmly today.")>> <<goto "NPCTalk">> <</if>> <</link>> <<else>> <div style="color: #555; font-size: 12px;">💫 Beguile (not enough mana)</div> <</if>> <</if>> <<if setup.witchSpells.knows("Entrancement")>> <<if setup.witchSpells.sandmanActiveFor(_npc.name)>> <div style="color: #a78bfa; font-size: 12px;">✨ <<print _npc.name>> drifts in your sandman haze until tomorrow.</div> <<elseif ($witchMana || 0) >= 30>> <<link "<span style='color: #e040fb; cursor: pointer; font-size: 13px;'>✨ Cast Entrancement (30 mana)</span>">> <<if setup.witchSpells.canTap()>> <<run setup.witchSpells.spendMana(30)>> <<set $sandmanTarget = _npc.name>> <<set $sandmanDay = $dayNumber>> <<run setup.questSystem.addNotification("updated", State.variables.sandmanTarget + "'s eyes soften. Their wants drift to the surface for the day.")>> <<goto "NPCTalk">> <</if>> <</link>> <<else>> <div style="color: #555; font-size: 12px;">✨ Entrancement (not enough mana)</div> <</if>> <</if>> </div> <</if>> /* NPC Quest Section */ <<set _npcQuests = setup.getNPCQuests(_npc.name)>> <<if _npcQuests.length > 0>> <details class="npc-dropdown" open style="margin-bottom: 10px;"> <summary style="background: #2a2a2a; padding: 12px 15px; border: 2px solid #ffd700; display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ffd700; font-weight: bold; font-size: 15px;">📜 Quests <span style="color: #666; font-size: 12px; font-weight: normal;">(<<= _npcQuests.length>>)</span></span> <span class="npc-chevron" style="color: #ffd700; font-size: 14px;">▾</span> </summary> <div class="npc-options" style="background: #2a2a2a; padding: 10px 15px 15px; border: 2px solid #ffd700; display: grid; gap: 8px;"> <<for _nqIdx = 0; _nqIdx < _npcQuests.length; _nqIdx++>> <<set _nq = _npcQuests[_nqIdx]>> <<set _nqDlg = _nq.quest.dialoguePassage || "">> <<if _nq.state === "available">> <<if _nqDlg>> <<capture _nq, _nqDlg>> <div style="background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 2px solid #ffd700; cursor: pointer; box-shadow: 0 0 10px #ffd70044; animation: questPulse 2s ease-in-out infinite;"> <<link `'<span style="color: #ffd700; font-weight: bold;">' + _nq.quest.name + '</span>'`>> <<set $questDialogueTarget = _nq.id>> <<set $xanitharQuestTarget = _nq.id>> <<goto _nqDlg>> <</link>> </div> <</capture>> <<else>> <div style="background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 2px solid #ffd700; box-shadow: 0 0 10px #ffd70044; animation: questPulse 2s ease-in-out infinite;"> <div style="color: #ffd700; font-weight: bold; margin-bottom: 4px;"><<= _nq.quest.name>></div> <div style="color: #aaa; font-size: 13px; line-height: 1.5;"><<= _nq.quest.description>></div> </div> <</if>> <<elseif _nq.state === "active">> <<if _nqDlg>> <<capture _nq, _nqDlg>> <div style="background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 2px solid #4dabf7; cursor: pointer;"> <<link `'<span style="color: #4dabf7; font-weight: bold;">▶ ' + _nq.quest.name + '</span>'`>> <<set $questDialogueTarget = _nq.id>> <<set $xanitharQuestTarget = _nq.id>> <<goto _nqDlg>> <</link>> </div> <</capture>> <<else>> <div style="background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 2px solid #4dabf7;"> <div style="color: #4dabf7; font-weight: bold; margin-bottom: 4px;">▶ <<= _nq.quest.name>></div> <div style="color: #aaa; font-size: 13px; line-height: 1.5;"><<= _nq.quest.description>></div> </div> <</if>> <<elseif _nq.state === "completed">> <div style="background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 1px solid #51cf66; opacity: 0.7;"> <span style="color: #51cf66; font-weight: bold;">✅ <<= _nq.quest.name>></span> </div> <</if>> <</for>> </div> </details> <</if>> <<for _catKey range _groupOrder>> <<if _grouped[_catKey] && _grouped[_catKey].length > 0>> <details class="npc-dropdown" @open="_catKey === 'core' || undefined" style="margin-bottom: 10px;"> <summary @style="'background: #2a2a2a; padding: 12px 15px; border: 2px solid ' + (_catBorderColors[_catKey] || '#444') + '; display: flex; justify-content: space-between; align-items: center;'"> <span @style="'color: ' + (_catBorderColors[_catKey] || '#888') + '; font-weight: bold; font-size: 15px;'"><<= _catNames[_catKey] || _catKey>> <span style="color: #666; font-size: 12px; font-weight: normal;">(<<= _grouped[_catKey].length>>)</span></span> <span class="npc-chevron" @style="'color: ' + (_catBorderColors[_catKey] || '#666') + '; font-size: 14px;'">▾</span> </summary> <div class="npc-options" @style="'background: #2a2a2a; padding: 10px 15px 15px; border: 2px solid ' + (_catBorderColors[_catKey] || '#444') + '; display: grid; gap: 8px;'"> <<for _opt range _grouped[_catKey]>> <<capture _opt>> <div @style="'background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 2px solid ' + _opt.option.color + '; cursor: pointer;'"> <<link `'<span style="color: ' + _opt.option.color + '; font-weight: bold;">' + _opt.option.label + '</span>'`>> <<set $currentTopic = _opt.option.id>> <<set $currentTopicData = _opt.option>> <<if _opt.option.category === "npcSocial">> <<goto "NPCSocialSelect">> <<else>> <<goto "NPCTalkResponse">> <</if>> <</link>> </div> <</capture>> <</for>> </div> </details> <</if>> <</for>> /* Gift Section */ <<set _giftableItems = setup.getPlayerGiftableItems()>> <<set _canGift = setup.canGiftNPC(_npc.name)>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 15px; border: 2px solid #e91e63;"> <div style="color: #e91e63; margin: 0 0 12px 0; font-size: 20px; font-weight: bold; border-bottom: 2px solid #e91e63; padding-bottom: 10px;">🎁 Give a Gift</div> <<if !_canGift>> <div style="color: #888; font-style: italic; text-align: center; padding: 10px;">They've received enough gifts this week.</div> <<elseif _giftableItems.length === 0>> <div style="color: #888; font-style: italic; text-align: center; padding: 10px;">You don't have any gifts. Buy some from shops around the city!</div> <<else>> <div style="display: grid; gap: 8px; max-height: 350px; overflow-y: auto;"> <<set _lastGroup = "">> <<for _gi range _giftableItems>> <<capture _gi>> <<if _gi.group !== _lastGroup>> <<set _lastGroup = _gi.group>> <<if _gi.group === "store">> <div style="color: #51cf66; font-size: 14px; font-weight: bold; margin-top: 8px; padding: 4px 0; border-bottom: 1px solid #333;">🛒 Store-Bought</div> <<elseif _gi.group === "cooked">> <div style="color: #ffa500; font-size: 14px; font-weight: bold; margin-top: 8px; padding: 4px 0; border-bottom: 1px solid #333;">🍳 Cooked Meals</div> <<elseif _gi.group === "fish">> <div style="color: #339af0; font-size: 14px; font-weight: bold; margin-top: 8px; padding: 4px 0; border-bottom: 1px solid #333;">🐟 Fish</div> <<elseif _gi.group === "homemade">> <div style="color: #e91e63; font-size: 14px; font-weight: bold; margin-top: 8px; padding: 4px 0; border-bottom: 1px solid #333;">🏠 Homemade</div> <</if>> <</if>> <div style="background: #1a1a1a; padding: 10px 14px; border-radius: 8px; border: 1px solid #555; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 18px;"><<print _gi.icon>></span> <span style="color: #ccc; font-weight: bold; margin-left: 8px;"><<print _gi.name>></span> <<if _gi.qty > 1>><span style="color: #888; font-size: 12px;"> x<<print _gi.qty>></span><</if>> <<if _gi.freshness>><div style="font-size: 12px; margin-top: 3px; margin-left: 30px;"><<print setup.getFreshnessLabel(_gi.freshness)>></div><</if>> <<if _gi.rarity>><div style="font-size: 12px; margin-top: 3px; margin-left: 30px; color: <<if _gi.rarity === 'mythical'>>#ff6b9d<<elseif _gi.rarity === 'legendary'>>#ffd700<<elseif _gi.rarity === 'epic'>>#a855f7<<elseif _gi.rarity === 'rare'>>#339af0<<elseif _gi.rarity === 'uncommon'>>#51cf66<<else>>#aaa<</if>>;"><<print _gi.rarity>></div><</if>> </div> <<link "<span style='background: #e91e63; color: white; padding: 6px 14px; border-radius: 6px; font-weight: bold; font-size: 13px;'>Give</span>">> <<set $giftToGive = _gi>> <<goto "NPCGiftResponse">> <</link>> </div> <</capture>> <</for>> </div> <</if>> </div> /* Back Button */ <div style="text-align: center;"> <<if $homeVisitReturn>> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🏠 Back Home</div>">> <<set $homeVisitReturn = false>> <<set $homeTalkBonus = 1>> <<goto setup.homeVisit.getPlayerHomePassage()>> <</link>> <<else>> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Back</div>">> <<goto "NPCInteraction">> <</link>> <</if>> </div> </div> <</if>> <</nobr>>
<div style="display: grid; gap: 15px; margin: 0; padding: 0;"> <<for _traitName, _traitDesc range $availableTraits>><<capture _traitName, _traitDesc>><<set _isSelected = $selectedTraits.has(_traitName)>><div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid <<if _isSelected>>#51cf66<<else>>#666<</if>>;"><div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"><strong style="color: <<if _isSelected>>#51cf66<<else>>#ccc<</if>>; font-size: 18px;">_traitName</strong><<if _isSelected>><<link "<span style='color: #ff6b6b; font-weight: bold; font-size: 16px;'>REMOVE</span>">><<run $selectedTraits.delete(_traitName)>><<replace "#trait-list">><<include "TraitListDisplay">><</replace>><<replace "#trait-counter">><div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #51cf66;"><p style="color: #51cf66; margin: 0; font-size: 16px; font-weight: bold;">You may choose up to <span style="color: #ffc107;">1</span> trait.</p></div><</replace>><</link>><<else>><<link "<span style='color: #51cf66; font-weight: bold; font-size: 16px;'>SELECT</span>">><<if $selectedTraits.size < $maxTraits>><<run $selectedTraits.add(_traitName)>><<replace "#trait-list">><<include "TraitListDisplay">><</replace>><<replace "#trait-counter">><div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #51cf66;"><p style="color: #51cf66; margin: 0; font-size: 16px; font-weight: bold;">You may choose up to <span style="color: #ffc107;">1</span> trait.</p></div><</replace>><<else>><<script>>UI.alert("You can only select 1 trait!");<</script>><</if>><</link>><</if>></div><p style="color: #aaa; margin: 0; font-style: italic; font-size: 15px;">_traitDesc</p></div><</capture>><</for>> </div>
<<nobr>> <<set $lastLocation = "ShadyShop">> <h1>🕶️ Shady Shop</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 20px;"> <p style="color: #ccc; font-size: 18px; margin: 0;"> The dim interior reeks of cigarette smoke and desperation. An old man sits behind the counter, cackling to himself. His eyes light up when he sees you. "Welcome, welcome! Looking for a little excitement? A little chaos in your life? I can help with that... hehehehe!" </p> </div> <h2>Shop Services</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <div style="border: 2px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; opacity: 0.6;"> <h3 style="color: #666; margin-top: 0;">🎲 Shady Deal</h3> <p style="font-size: 14px; color: #ccc;">The old man loves chaos. Gain a positive trait, but receive a negative one too.</p> <p style="font-size: 13px; color: #999; font-style: italic; margin: 8px 0;">This feature will be fixed in a future update.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Disabled</div> </div> <div style="border: 2px solid #ff4444; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #ff4444; margin-top: 0;">💊 Black Market Goods</h3> <p style="font-size: 14px; color: #ccc;">Questionable items of dubious origin.</p> <<link "<div style='background: #ff4444; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Browse</div>">> <<goto "BlackMarketGoods">> <</link>> </div> <div style="border: 2px solid #ff4444; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #ff4444; margin-top: 0;">🔓 Illegal Services</h3> <p style="font-size: 14px; color: #ccc;">Off-the-books transactions and services.</p> <<link "<div style='background: #ff4444; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter</div>">> <<goto "IllegalServices">> <</link>> </div> <div style="border: 2px solid #ff4444; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #ff4444; margin-top: 0;">💰 Fence Stolen Goods</h3> <p style="font-size: 14px; color: #ccc;">Sell items without asking questions.</p> <p style="font-size: 13px; color: #999; font-style: italic;">Coming soon...</p> </div> </div> <br><br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #434343; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Alleyway</div>">> <<goto "Alleyway">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ShadyDeal">> <!-- Initialize shady deals counter if it doesn't exist --> <<if !$shadyDealsToday>> <<set $shadyDealsToday = 0>> <<set $lastShadyDealDay = $dayNumber>> <</if>> <!-- Reset counter if it's a new day --> <<if $lastShadyDealDay !== $dayNumber>> <<set $shadyDealsToday = 0>> <<set $lastShadyDealDay = $dayNumber>> <</if>> <h1>🕶️ Shady Deal</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #ff4444;"> <p style="color: #ccc; font-size: 18px; margin: 0;"> The old man cackles with glee, his eyes gleaming with malicious amusement. "Hehehehe... I just love watching people squirm! I got connections to some real special folks. They can change you... make you better, make you worse. Who knows?" He grins wickedly. "I just do it for the entertainment, ya know? Watching you deal with the consequences... priceless!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107;"> <h2 style="color: #ffc107; margin-top: 0;">⚠️ How It Works</h2> <ul style="color: #ccc; font-size: 15px;"> <li><strong>You will receive:</strong> One random positive physical or mental trait (value: 1-20+)</li> <li><strong>You will also receive:</strong> One random negative trait (value: -20 to -1)</li> <li><strong>Cost:</strong> FREE - The old man just likes the chaos</li> <li><strong>Limit:</strong> 3 deals per day</li> <li><strong>Warning:</strong> The negative trait could be severe. This is pure gambling.</li> </ul> </div> <div style="background: #3a3a3a; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 20px; border: 2px solid #666;"> <p style="color: #ffc107; font-size: 18px; font-weight: bold; margin: 0;"> 🎲 Deals Remaining Today: <<print 3 - $shadyDealsToday>> / 3 </p> </div> <<if $shadyDealsToday < 3>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff4444 0%, #cc0000 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🎲 Roll the Dice (FREE)</div>">> <<set $shadyDealsToday += 1>> <!-- Get all positive traits player doesn't have --> <<set _positivePhysical = ["Tall", "Curvy", "Lean", "Muscular", "Soft", "Sharp Features", "Smooth Skin", "Pierced", "Youthful", "Mature", "Attractive", "Fit", "Graceful", "Strong", "Flexible", "Freckled", "Tattooed", "Athletic Build", "Petite", "Voluptuous", "Broad-shouldered", "Quick", "Sturdy"]>> <<set _positiveMental = ["Extroverted", "Kind", "Sly", "Dominant", "Confident", "Optimistic", "Empathetic", "Supportive", "Friendly", "Competitive", "Logical", "Shrewd", "Hardworking", "Humble", "Trusting", "Ambitious", "Creative", "Brave", "Patient", "Wise", "Intelligent", "Analytical", "Outgoing", "Curious", "Witty", "Calm", "Energetic", "Thoughtful"]>> <<set _negativePhysical = ["Plain", "Ugly", "Overweight", "Underweight", "Clumsy", "Weak", "Stiff", "Blemished", "Short", "Scarred"]>> <<set _negativeMental = ["Bitchy", "Cruel", "Jealous", "Lazy", "Arrogant", "Complacent", "Dull", "Cowardly", "Impatient", "Foolish", "Introverted", "Submissive", "Shy", "Aggressive", "Passive", "Pessimistic", "Stubborn", "Paranoid"]>> <!-- Filter out traits player already has or are blocked by transformation --> <<set _availablePositivePhysical = []>> <<for _trait range _positivePhysical>> <<set _blockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation(_trait, "physical")>> <<if !$physicalTraits.includes(_trait) && !_blockedByTransform>> <<run _availablePositivePhysical.push(_trait)>> <</if>> <</for>> <<set _availablePositiveMental = []>> <<for _trait range _positiveMental>> <<set _blockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation(_trait, "mental")>> <<if !$mentalTraits.includes(_trait) && !_blockedByTransform>> <<run _availablePositiveMental.push(_trait)>> <</if>> <</for>> <<set _availableNegativePhysical = []>> <<for _trait range _negativePhysical>> <<set _blockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation(_trait, "physical")>> <<if !$physicalTraits.includes(_trait) && !_blockedByTransform>> <<run _availableNegativePhysical.push(_trait)>> <</if>> <</for>> <<set _availableNegativeMental = []>> <<for _trait range _negativeMental>> <<set _blockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation(_trait, "mental")>> <<if !$mentalTraits.includes(_trait) && !_blockedByTransform>> <<run _availableNegativeMental.push(_trait)>> <</if>> <</for>> <!-- Combine all available positive and negative traits --> <<set _allPositive = _availablePositivePhysical.concat(_availablePositiveMental)>> <<set _allNegative = _availableNegativePhysical.concat(_availableNegativeMental)>> <<if _allPositive.length === 0 || _allNegative.length === 0>> <<set $shadyDealResult = { success: false, reason: "insufficient_traits" }>> <<else>> <!-- Pick random positive trait --> <<set _positiveTrait = _allPositive[Math.floor(Math.random() * _allPositive.length)]>> <<set _isPositivePhysical = _availablePositivePhysical.includes(_positiveTrait)>> <!-- Pick random negative trait --> <<set _negativeTrait = _allNegative[Math.floor(Math.random() * _allNegative.length)]>> <<set _isNegativePhysical = _availableNegativePhysical.includes(_negativeTrait)>> <!-- Add traits to player --> <<if _isPositivePhysical>> <<run $physicalTraits.push(_positiveTrait)>> <<else>> <<run $mentalTraits.push(_positiveTrait)>> <</if>> <<if _isNegativePhysical>> <<run $physicalTraits.push(_negativeTrait)>> <<else>> <<run $mentalTraits.push(_negativeTrait)>> <</if>> <!-- Calculate values --> <<set _positiveValue = setup.getTraitValue(_isPositivePhysical ? "physical" : "mental", _positiveTrait)>> <<set _negativeValue = setup.getTraitValue(_isNegativePhysical ? "physical" : "mental", _negativeTrait)>> <<set $shadyDealResult = { success: true, positiveTrait: _positiveTrait, positiveType: _isPositivePhysical ? "Physical" : "Mental", positiveValue: _positiveValue, negativeTrait: _negativeTrait, negativeType: _isNegativePhysical ? "Physical" : "Mental", negativeValue: _negativeValue }>> <</if>> <<goto "ShadyDealResult">> <</link>> </div> <<else>> <div style="background: #3a3a3a; padding: 20px; border-radius: 12px; text-align: center; border: 2px solid #666;"> <p style="color: #ff6b6b; font-size: 18px; margin: 0;"> ❌ You've used all your deals for today. </p> <p style="color: #999; font-size: 14px; margin: 10px 0 0 0;"> <em>The old man cackles: "That's enough chaos for one day! Come back tomorrow if you want more!"</em> </p> </div> <</if>> <br><br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #434343; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Shop</div>">> <<goto "ShadyShop">> <</link>> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <<if $shadyDealResult.success>> <!-- SUCCESS --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 3px solid #ff4444;"> <h1 style="color: #ff4444; margin: 0 0 10px 0; font-size: 36px;">🎲 The Deal is Done</h1> <p style="color: #ccc; margin: 0; font-size: 18px;">The shopkeeper smiles wickedly as the transformation takes hold...</p> </div> <!-- What You Gained --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #51cf66; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #51cf66; padding-bottom: 10px;">✅ What You Gained</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #51cf66; text-align: center;"> <h3 style="color: #51cf66; margin: 0 0 10px 0; font-size: 22px;">$shadyDealResult.positiveTrait</h3> <p style="color: #aaa; margin: 5px 0; font-size: 16px;"> <strong>Type:</strong> $shadyDealResult.positiveType Trait </p> <p style="color: #51cf66; margin: 5px 0; font-size: 18px; font-weight: bold;"> Trade Value: +$shadyDealResult.positiveValue </p> </div> </div> <!-- What You Lost --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ff6b6b; padding-bottom: 10px;">❌ The Price You Paid</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; font-size: 22px;">$shadyDealResult.negativeTrait</h3> <p style="color: #aaa; margin: 5px 0; font-size: 16px;"> <strong>Type:</strong> $shadyDealResult.negativeType Trait </p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 18px; font-weight: bold;"> Trade Value: $shadyDealResult.negativeValue </p> </div> </div> <!-- Net Result --> <<set _netValue = $shadyDealResult.positiveValue + $shadyDealResult.negativeValue>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; text-align: center; border: 3px solid <<if _netValue >= 0>>#17a2b8<<else>>#ffc107<</if>>; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: <<if _netValue >= 0>>#17a2b8<<else>>#ffc107<</if>>; margin: 0 0 10px 0;">📊 Net Result</h3> <p style="color: #ccc; font-size: 20px; font-weight: bold; margin: 0;"> <<if _netValue > 0>> You came out ahead! Net value: <span style="color: #51cf66;">+_netValue</span> <<elseif _netValue === 0>> It is a wash. Net value: <span style="color: #ffc107;">0</span> <<else>> You got the short end of the stick. Net value: <span style="color: #ff6b6b;">_netValue</span> <</if>> </p> </div> <<else>> <!-- FAILURE --> <div style="background: linear-gradient(135deg, #ff6b6b 0%, #dc3545 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 3px solid #ff6b6b;"> <h1 style="color: white; margin: 0 0 10px 0; font-size: 36px;">❌ Deal Cancelled</h1> <p style="color: white; margin: 0; font-size: 18px;">You do not have enough available traits to make this deal.</p> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; text-align: center; font-size: 16px; margin: 0;"> The shopkeeper shrugs. "Come back when you are less full of yourself. Or more full of problems. Either way." </p> </div> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue</div>">> <<goto "ShadyShop">> <</link>> </div> </div> <</nobr>>
<!-- Reset shady deals counter --> <<set $shadyDealsToday = 0>>
https://www.patreon.com/Grankor <!-- Return to Game Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044; display: inline-block;'>← Return to Game</div>">> <<goto $lastLocation>> <</link>> </div>
https://discord.gg/z9eDdQC6zA <!-- Return to Game Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044; display: inline-block;'>← Return to Game</div>">> <<goto $lastLocation>> <</link>> </div>
''Alpha Version: 0.32.1''
<<nobr>> <<set $lastLocation = "Brothel">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Brothel")>> <<run $visitedLocations.push("Brothel")>> <</if>> <!-- Check job availability --> <<set _alreadyHasBrothelJob = $jobs && $jobs.includes("Brothel Worker")>> <<set _meetsRequirements = false>> <!-- Check all requirements --> <!-- Use effective charisma (base + trait bonuses + TF multipliers) so traits that boost CHA count toward the 35 hiring bar, matching the behaviour of setup.getJobApplicationStatus. --> <<set _effectiveCha = (typeof setup.getTotalStat === "function") ? setup.getTotalStat("charisma") : (($stats && $stats.charisma) || 0)>> <<if $bodyParts.gender === "female" && $skills && ($skills.includes("Sexually Skilled") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju")) && _effectiveCha >= 35>> <<set _meetsRequirements = true>> <</if>> <<set _brothelWorkerNPCs = setup.getNPCsByJob("Brothel Worker")>> <<set _brothelWorkerCount = _brothelWorkerNPCs ? _brothelWorkerNPCs.length : 0>> <<set _canHire = _brothelWorkerCount < 8>> <!-- Check requirements --> <<set _canWorkBrothel = $bodyParts.gender === "female" && ($skills && $skills.includes("Sexually Skilled") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju"))>> <!-- Initialize Brothel Work System --> <<if !$brothelLevel>> <<set $brothelLevel = 1>> <<set $brothelLevelExp = 0>> <<set $brothelMaxExp = 100>> <<set $brothelClients = 0>> <<set $brothelClientsToday = 0>> <<set $brothelLastWorkDay = 0>> <</if>> <!-- Initialize sexual skills if needed --> <<if _canWorkBrothel>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Reset daily client count if new day --> <<if $brothelLastWorkDay !== $dayNumber>> <<set $brothelClientsToday = 0>> <<set $brothelLastWorkDay = $dayNumber>> <</if>> <!-- Calculate max work hours per day based on brothel level --> <<set _maxBrothelHours = 3>> <<if $brothelLevel === 2>> <<set _maxBrothelHours = 4>> <<elseif $brothelLevel === 3>> <<set _maxBrothelHours = 5>> <<elseif $brothelLevel === 4>> <<set _maxBrothelHours = 6>> <<elseif $brothelLevel >= 5>> <<set _maxBrothelHours = 8>> <</if>> <!-- Calculate bonus money from relevant traits/skills --> <<set _brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion", "Oral Expert", "Anal Expert", "Rough Sex Enthusiast", "Sensual Lover", "BDSM Enthusiast - Dom", "BDSM Enthusiast - Sub", "Roleplay Expert", "Dirty Talker", "Exhibitionist", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master"]>> <<set _brothelBonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if ($mentalTraits && $mentalTraits.includes(_trait)) || ($physicalTraits && $physicalTraits.includes(_trait)) || ($skills && $skills.includes(_trait))>> <<set _brothelBonusMoney += 15>> <</if>> <</for>> <!-- Display level up messages --> <<if $brothelLevelUpMessages && $brothelLevelUpMessages.length > 0>> <<for _msg range $brothelLevelUpMessages>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #FFD700; box-shadow: 0 6px 12px rgba(255,215,0,0.5); text-align: center;"> <h2 style="color: #000; margin: 0; font-size: 24px; text-shadow: 2px 2px 4px rgba(255,255,255,0.3);">_msg</h2> </div> <</for>> <<set $brothelLevelUpMessages = []>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #007FFF; text-align: center;">💋 Azure Angelfish Lounge</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Brothel.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #007FFF; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Azure Angelfish Lounge"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #007FFF 0%, #0059b3 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #007FFF;"> <p style="color: white; font-size: 18px; margin: 0;"> Plush velvet furniture and dim mood lighting create an atmosphere of luxury and discretion. Well-dressed hosts and hostesses attend to clients with professional grace. The air carries hints of expensive perfume and champagne. </p> </div> <!-- REQUIREMENTS NOT MET WARNING (Only shows if player already has Brothel Worker job) --> <<if $jobs && $jobs.includes("Brothel Worker")>> <<if ($bodyParts.gender || "").toLowerCase() !== "female">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin: 0 0 10px 0;">❌ Employment Requirements Not Met</h2> <p style="color: #ccc; margin: 0;">This establishment only hires <strong style="color: #e91e63;">female</strong> workers. You do not meet this requirement.</p> </div> <</if>> <<if !$skills.includes("Sexually Skilled") && (!$physicalTraits.includes("Succubus") && !$physicalTraits.includes("Voluptuous Succubus")) && !$physicalTraits.includes("Slut") && !$physicalTraits.includes("Pyrow") && !$physicalTraits.includes("Raiju")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin: 0 0 10px 0;">❌ Skills Requirement Not Met</h2> <p style="color: #ccc; margin: 0;">To work at the Azure Angelfish Lounge, you need the <strong style="color: #e91e63;">"Sexually Skilled"</strong> trait or be a <strong style="color: #e91e63;">Succubus/Slut</strong>. This is a professional establishment that requires experienced workers.</p> <p style="color: #888; margin: 10px 0 0 0; font-size: 14px; font-style: italic;">Hint: You can acquire this trait through various means in the city...</p> </div> <</if>> <</if>> <!-- Apply for Job Section --> <<if !$jobs || !$jobs.includes("Brothel Owner")>> <h2 style="color: #007FFF;">Employment</h2> <div style="display: grid; grid-template-columns: 1fr; gap: 15px; margin-bottom: 25px;"> <<if _alreadyHasBrothelJob>> <!-- Already working here --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">💼 Employment Status</h3> <p style="font-size: 14px; color: #51cf66; margin-bottom: 15px;">You're already employed here!</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Already Employed</div> </div> <<elseif !_meetsRequirements>> <!-- Doesn't meet requirements --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">💼 Apply for Position</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">You don't meet the requirements to work here.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif !_canHire>> <!-- Brothel is fully staffed --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">💼 Apply for Position</h3> <p style="font-size: 14px; color: #ff6b6b; margin-bottom: 10px;">The lounge is fully staffed (<<print _brothelWorkerCount>>/8 workers)</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <!-- Can apply for the job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 10px 0;">💼 Apply for Position</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;">Join the Azure Angelfish Lounge as a professional companion.</p> <p style="font-size: 13px; color: #aaa; margin-bottom: 6px;">High-end establishment | Professional discretion required</p> <p style="font-size: 13px; color: #ffd43b; margin-bottom: 15px;">Requires: CHA 35, female, and Sexually Skilled</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "BrothelJobOffer">> <</link>> </div> <</if>> </div> <</if>> <!-- Management Area (Only shows if player has Brothel Owner job) --> <<if $jobs && $jobs.length > 0 && $jobs.includes("Brothel Owner")>> <h2 style="color: #FFD700;">Brothel Management</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #FFD700; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #FFD700; margin: 0 0 10px 0;">👑 Manage Your Business</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 15px 0;">Oversee operations, finances, and staff at the Azure Angelfish Lounge.</p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Enter Management Office</div>">> <<goto "BrothelManagement">> <</link>> </div> </div> <</if>> <!-- Work Area (Only shows if player has Brothel Worker job AND meets requirements) --> <<if $jobs && $jobs.length > 0 && $jobs.includes("Brothel Worker")>> <<if _canWorkBrothel>> <h2 style="color: #007FFF;">Your Work</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #007FFF; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <!-- Professional Level Display --> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #007FFF;"> <h3 style="color: #007FFF; margin: 0 0 10px 0;"> Professional Level: $brothelLevel <<if $brothelLevel === 1>> <span style="color: #999; font-size: 14px;">(Novice)</span> <<elseif $brothelLevel === 2>> <span style="color: #51cf66; font-size: 14px;">(Experienced)</span> <<elseif $brothelLevel === 3>> <span style="color: #ffc107; font-size: 14px;">(Professional)</span> <<elseif $brothelLevel === 4>> <span style="color: #ff9800; font-size: 14px;">(Expert)</span> <<elseif $brothelLevel >= 5>> <span style="color: #e91e63; font-size: 14px;">(Elite)</span> <</if>> </h3> <!-- XP Progress Bar --> <<if $brothelLevel < 5>> <<set _brothelLevelProgress = Math.floor(($brothelLevelExp / $brothelMaxExp) * 100)>> <div style="margin-bottom: 10px;"> <div style="background-color: #0a0a0a; border-radius: 10px; height: 12px; overflow: hidden; border: 1px solid #444; box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);"> <div @style="'background: linear-gradient(90deg, #007FFF 0%, #00bfff 100%); height: 100%; width: ' + _brothelLevelProgress + '%; transition: width 0.3s ease; box-shadow: 0 0 10px #007FFF;'"></div> </div> <p style="color: #aaa; margin: 5px 0 0 0; font-size: 13px; text-align: center;"> <<print $brothelLevelExp>> / <<print $brothelMaxExp>> XP to Level <<print $brothelLevel + 1>> </p> </div> <<else>> <p style="color: #e91e63; margin: 10px 0 0 0; font-weight: bold; text-align: center;">★ MAX LEVEL REACHED ★</p> <</if>> <!-- Level Benefits --> <div style="background: #0a0a0a; padding: 10px; border-radius: 6px; margin-top: 10px; border: 1px solid #444;"> <p style="color: #ccc; margin: 0 0 5px 0; font-size: 14px;"><strong style="color: #007FFF;">Current Benefits:</strong></p> <ul style="color: #aaa; font-size: 13px; margin: 5px 0 0 20px; padding: 0;"> <li>Available Clients: <span style="color: #51cf66;"><<print 3 + $brothelLevel>></span></li> <li>Max Work Hours/Day: <span style="color: #51cf66;"><<print _maxBrothelHours>></span></li> <li>Max Client Difficulty: <<if $brothelLevel <= 2>> <span style="color: #ffc107;">Medium</span> <<elseif $brothelLevel <= 4>> <span style="color: #ff9800;">Hard</span> <<else>> <span style="color: #e91e63;">Very Hard</span> <</if>> </li> </ul> </div> <p style="color: #ccc; margin: 10px 0 0 0;">Total Clients Served: <span style="color: #007FFF;">$brothelClients</span></p> <p style="color: #ffc107; margin: 5px 0 0 0;"> Today's Sessions: $brothelClientsToday / _maxBrothelHours hours <<if _brothelBonusMoney > 0>> <span style="color: #51cf66;"> (+$<<print _brothelBonusMoney>> per client from skills/traits)</span> <</if>> </p> </div> <!-- Work Button --> <<if $brothelClientsToday >= _maxBrothelHours>> <div style="background: #1a1a1a; border: 3px solid #666; padding: 15px; border-radius: 8px; text-align: center;"> <p style="color: #ff6b6b; margin: 0; font-weight: bold;">You're exhausted for today. Come back tomorrow.</p> <p style="color: #888; margin: 10px 0 0 0; font-size: 14px;">You've worked $brothelClientsToday / _maxBrothelHours hours today.</p> </div> <<else>> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💼 Wait for Client</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 15px 0;">Take the next available client. Each session lasts 1 hour.</p> <<link "<div style='background: #e91e63; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Service Next Client (<<print _maxBrothelHours - $brothelClientsToday>> hours remaining)</div>">> <<goto "BrothelClientSelection">> <</link>> </div> <</if>> </div> <<else>> <h2 style="color: #ff6b6b;">Cannot Work</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 10px 0;">You no longer meet the requirements to work here:</p> <ul style="color: #ccc; margin: 0; padding-left: 20px;"> <<if ($bodyParts.gender || "").toLowerCase() !== "female">> <li>You must be <strong style="color: #e91e63;">female</strong></li> <</if>> <<if !$skills.includes("Sexually Skilled") && (!$physicalTraits.includes("Succubus") && !$physicalTraits.includes("Voluptuous Succubus")) && !$physicalTraits.includes("Slut") && !$physicalTraits.includes("Pyrow") && !$physicalTraits.includes("Raiju")>> <li>You must have the <strong style="color: #e91e63;">"Sexually Skilled"</strong> trait or be a <strong style="color: #e91e63;">Succubus/Slut</strong></li> <</if>> </ul> </div> <</if>> <</if>> <!-- NPCs Present (schedule-aware) --> <<set _npcsHere = setup.getNPCsAtLocation("Brothel")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="color: #007FFF;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #007FFF; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #007FFF; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #007FFF; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #007FFF; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="color: #007FFF;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The lounge is quiet right now. No one is available. </p> </div> <</if>> <!-- Navigation Buttons --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #ff1493; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClub">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("StripClub")>> <<run $visitedLocations.push("StripClub")>> <</if>> <!-- Check if player is an employee --> <<set _isEmployee = ($jobs.includes("Stripper") || $jobs.includes("Bouncer"))>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9D00FF; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(157, 0, 255, 0.8), 0 0 40px rgba(255, 20, 147, 0.6);">🪼 Electric Jelly Revue</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/StripClub.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #9D00FF; box-shadow: 0 0 30px rgba(157, 0, 255, 0.5), 0 4px 8px rgba(0,0,0,0.6);" alt="Electric Jelly Revue"> </div> <</if>> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #9D00FF; box-shadow: 0 0 30px rgba(157, 0, 255, 0.4), inset 0 0 20px rgba(255, 20, 147, 0.2);"> <p style="color: #fff; font-size: 20px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Bass-heavy music throbs through the air as colorful lights pulse across the stage in hypnotic patterns—purple, pink, electric blue. Dancers move gracefully on gleaming chrome poles while patrons sip drinks and watch from plush velvet booths. </p> <p style="color: #D8BFD8; font-size: 18px; margin: 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The atmosphere crackles with energy and anticipation. Money flows freely here, and desire hangs thick in the air. </p> </div> <!-- Work Section (only shows if player has Stripper or Bouncer job) --> <<if $jobs.includes("Stripper") || $jobs.includes("Bouncer")>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💼 Employee Options</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-top: 20px; margin-bottom: 30px;"> <<if $jobs.includes("Stripper")>> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 25px rgba(255, 20, 147, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h4 style="color: #FF1493; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);">💃 Work as Stripper</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;">Clock in for your shift. Perform on stage, work the floor, or take private bookings. Your body is your business, and business is good.</p> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6);'>🎭 Start Shift</div>">> <<goto "StripClubWorkStripper">> <</link>> </div> <</if>> <<if $jobs.includes("Bouncer")>> <div style="border: 3px solid #9D00FF; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); box-shadow: 0 0 20px rgba(157, 0, 255, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #9D00FF, transparent); opacity: 0.6;"></div> <h4 style="color: #9D00FF; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(157, 0, 255, 0.8);">🛡️ Work as Bouncer</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;">Maintain security and keep the peace. Make sure everyone follows the rules and nobody gets too handsy with the dancers.</p> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(157, 0, 255, 0.5);'>💪 Start Shift</div>">> <<goto "StripClubWorkBouncer">> <</link>> </div> <</if>> </div> <</if>> <!-- Stripper Apply for Work --> <<if !($jobs && $jobs.includes("Stripper"))>> <<set _stripAppStatus = setup.getJobApplicationStatus("Stripper")>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; margin-top: 40px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💃 Join the Club</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-top: 20px; margin-bottom: 30px;"> <<if _stripAppStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 8px 16px rgba(0,0,0,0.6); opacity: 0.65;"> <h4 style="color: #999; margin: 0 0 12px 0; font-size: 22px;">💃 Apply: Stripper</h4> <p style="color: #bbb; font-size: 15px; margin: 0 0 8px 0; line-height: 1.5;">The manager looks you over. "Come back when you have the charm and the moves for the stage."</p> <p style="color: #888; font-size: 13px; margin: 0;">Requires: <<print setup.getJobRequirementDisplay("Stripper")>></p> </div> <<elseif _stripAppStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 8px 16px rgba(0,0,0,0.6);"> <h4 style="color: #ff6b6b; margin: 0 0 12px 0; font-size: 22px;">💃 Apply: Stripper</h4> <p style="color: #ddd; font-size: 15px; margin: 0;">The roster is full right now. Check back later.</p> </div> <<else>> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 25px rgba(255, 20, 147, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h4 style="color: #FF1493; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);">💃 Apply: Stripper</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;">Audition for the stage. Strut, dance, and own the spotlight. The pay is $30 an hour plus generous tips.</p> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6);'>💃 Audition Now</div>">> <<set $jobs = ["Stripper"]>> <<set $homeless = false>> <<run setup.achievements.unlock("get_hired")>> <<goto "StripClub">> <</link>> </div> <</if>> </div> <</if>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; margin-top: 40px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">📍 Club Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-top: 20px; margin-bottom: 30px;"> <!-- VIP Lounge --> <<if $stripClubVIPMember || $jobs.includes("Stripper") || $jobs.includes("Bouncer")>> <div style="border: 3px solid #FFD700; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); box-shadow: 0 0 25px rgba(255, 215, 0, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FFD700, transparent); opacity: 0.6;"></div> <h4 style="color: #FFD700; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);">👑 VIP Lounge</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> <<if $jobs.includes("Stripper") || $jobs.includes("Bouncer")>> Access the exclusive VIP area behind the velvet rope. As an employee, you can enter anytime to network with the club's wealthiest clientele. <<else>> Behind the velvet rope lies the VIP section—exclusive, luxurious, and decadent. Private booths, premium service, and intimate entertainment await members. <</if>> </p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 215, 0, 0.6);'>✨ Enter VIP Lounge</div>">> <<goto "StripClubVIP">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); box-shadow: 0 0 15px rgba(102, 102, 102, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #666, transparent); opacity: 0.6;"></div> <h4 style="color: #999; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(153, 153, 153, 0.8);">👑 VIP Lounge</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 15px 0; line-height: 1.5;">Exclusive access to private entertainment and premium services. Elite members only.</p> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: auto; border: 2px solid #FFD700;"> <p style="color: #FFD700; font-size: 18px; font-weight: bold; margin: 0; text-align: center; text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);"> Membership: $5,000 </p> </div> <<if $money >= 5000>> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(255, 215, 0, 0.5);'>💳 Purchase Membership</div>">> <<set $money -= 5000>> <<set $stripClubVIPMember = true>> <<goto "StripClub">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; margin-top: 15px; cursor: not-allowed; border: 2px solid #666;'>❌ Insufficient Funds</div> <</if>> </div> <</if>> </div> <!-- NPCs Present (schedule-aware) --> <<set _npcsHere = setup.getNPCsAtLocation("StripClub")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-top: 40px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">👥 People Here</h2> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.3);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #9D00FF; border-radius: 12px; padding: 18px; background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); box-shadow: 0 0 15px rgba(157, 0, 255, 0.2), 0 4px 8px rgba(0,0,0,0.6); position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, transparent, #9D00FF, transparent); opacity: 0.6;"></div> <h3 style="color: #FF69B4; margin: 0 0 10px 0; font-size: 20px; text-shadow: 0 0 8px rgba(255, 105, 180, 0.6);">_npc.name</h3> <p style="font-size: 14px; color: #D8BFD8; margin: 0 0 12px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 10px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(157, 0, 255, 0.4);'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-top: 40px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">👥 People Here</h2> <div style="background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 0 15px rgba(102, 102, 102, 0.2);"> <p style="text-align: center; color: #888; margin: 0; font-style: italic; font-size: 16px;"> The club is quiet right now. No dancers or staff are currently available to chat. </p> </div> <</if>> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #444 100%); color: white; padding: 14px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #888;'>← Back to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Casino")>> <<run $visitedLocations.push("Casino")>> <</if>> <<set $lastLocation = "Casino">> <!-- Check for gambling addiction forced play --> <<if setup.checkGamblingAddiction() && !$forcedGambling>> <<goto "ForcedGambling">> <</if>> <!-- Clear forced gambling flag if set --> <<if $forcedGambling>> <<set $forcedGambling = false>> <</if>> <!-- Check if player has bank account --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">🎰 Silver Marlin Casino</h1> <div style="padding: 20px; background: linear-gradient(135deg, #d4af37 0%, #8b7355 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700;"> <p style="color: white; font-size: 18px; margin: 0;"> Neon lights flash in rhythmic patterns across walls lined with slot machines and gaming tables. The constant chiming of wins mixes with the shuffle of cards and the roll of dice. Cocktail servers weave through crowds of hopeful gamblers while security watches from discrete corners. The air is thick with cigarette smoke and expensive cologne. </p> </div> <!-- Casino Activities Section --> <h2 style="color: #ffd700;">Casino Games</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px;"> <!-- Slot Machines --> <<set _canPlaySlots = $money >= 50>> <div style="border: 3px solid <<if _canPlaySlots>>#ffd700<<else>>#666<</if>>; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if _canPlaySlots>>rgba(255, 215, 0, 0.3)<<else>>rgba(102, 102, 102, 0.2)<</if>>;"> <h3 style="color: <<if _canPlaySlots>>#ffd700<<else>>#666<</if>>; margin: 0 0 10px 0;">🎰 Slot Machines</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 5px;">Pull the lever for instant wins!</p> <p style="font-size: 13px; color: #f39c12; margin-bottom: 10px;">💵 $50 per spin</p> <<if $slotMachineSystem && $slotMachineSystem.totalPlays > 0>> <p style="font-size: 13px; color: #4dabf7; margin-bottom: 10px;"> Total plays: $slotMachineSystem.totalPlays </p> <</if>> <<if _canPlaySlots>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 15px rgba(255, 215, 0, 0.3);'>🎰 Play Slots</div>">> <<goto "SlotMachine">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Enough Money</div> <p style="font-size: 13px; color: #888; margin: 8px 0 0 0; font-style: italic; text-align: center;">You need at least $50 to play slots</p> <</if>> </div> <!-- Roulette --> <<set _rouletteAccess = setup.canPlayRoulette()>> <<set _hasRouletteAccess = _rouletteAccess.canPlay && $money >= 100>> <<set _rouletteBanned = !_rouletteAccess.canPlay>> <<set _rouletteColor = _hasRouletteAccess ? "#ffd700" : (_rouletteBanned ? "#c62828" : "#666")>> <div style="border: 3px solid <<print _rouletteColor>>; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if _hasRouletteAccess>>rgba(255, 215, 0, 0.3)<<elseif _rouletteBanned>>rgba(198, 40, 40, 0.3)<<else>>rgba(102, 102, 102, 0.2)<</if>>;"> <h3 style="color: <<print _rouletteColor>>; margin: 0 0 10px 0;">🎡 Roulette</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 5px;">Bet on numbers or colors</p> <p style="font-size: 13px; color: #f39c12; margin-bottom: 10px;">⚠️ Limit: $50,000 (30-day cooldown after limit)</p> <<if $rouletteSystem.periodWinnings > 0 && !$rouletteSystem.kickedOut>> <p style="font-size: 13px; color: <<if $rouletteSystem.periodWinnings >= 50000>>#c62828<<elseif $rouletteSystem.periodWinnings >= 25000>>#f39c12<<else>>#51cf66<</if>>; margin-bottom: 10px;"> Winnings: $<<print $rouletteSystem.periodWinnings.toLocaleString()>> / $50,000 </p> <</if>> <<if _hasRouletteAccess>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 15px rgba(255, 215, 0, 0.3);'>🎡 Enter Roulette Room</div>">> <<goto "RouletteRoom">> <</link>> <<elseif _rouletteBanned>> <<set _daysRemaining = 30 - ($dayNumber - $rouletteSystem.lockoutStartDay)>> <<if _daysRemaining < 0>><<set _daysRemaining = 0>><</if>> <div style='background: #c62828; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-bottom: 8px;'>🚫 Banned for <<print _daysRemaining>> more day<<if _daysRemaining !== 1>>s<</if>></div> <p style="font-size: 13px; color: #ff6b6b; margin: 0; font-style: italic;"><<print _rouletteAccess.reason>></p> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Enough Money</div> <p style="font-size: 13px; color: #888; margin: 8px 0 0 0; font-style: italic; text-align: center;">You need at least $100 to play roulette</p> <</if>> </div> </div> <!-- NPCs at Casino Section --> <<set _rouletteNPCs = setup.getNPCsAtLocation("Casino")>> <<if _rouletteNPCs && _rouletteNPCs.length > 0>> <h2 style="color: #ffd700;">🎰 Gamblers at the Tables</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(255, 215, 0, 0.2);"> <p style="color: #ffa500; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic; text-shadow: 0 0 10px rgba(255, 165, 0, 0.5);"> High rollers and hopeful gamblers gather around the tables... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _rouletteNPCs>> <<capture _npc>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 215, 0, 0.2);"> <h3 style="color: #ffd700; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(255, 215, 0, 0.5);">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 5px 0;"> <<if typeof _npc.jobs === "string">> <em>_npc.jobs</em> <<else>> <<set _displayJob = _npc.jobs[0]>> <em>_displayJob</em> <</if>> </p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 15px rgba(255, 215, 0, 0.3);'>💬 Approach _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="color: #ffd700;">Casino Patrons</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #666; font-size: 15px; margin: 0; font-style: italic; text-align: center;"> The casino floor is busy, but you don't see anyone you know at the moment. </p> </div> <</if>> <!-- Compact ATM Section - Bottom --> <div style="background: #2a2a2a; padding: 12px 20px; border-radius: 8px; margin-bottom: 20px; border: 2px solid <<if _hasBankAccount>>#4dabf7<<else>>#555<</if>>; display: flex; align-items: center; justify-content: space-between; gap: 15px; flex-wrap: wrap;"> <div style="flex: 1; min-width: 200px;"> <span style="color: <<if _hasBankAccount>>#4dabf7<<else>>#888<</if>>; font-size: 16px; font-weight: bold;">🏧 ATM</span> <<if _hasBankAccount>> <span style="color: #aaa; font-size: 12px; margin-left: 10px;">FREE - no fees! • $30K/day • 24/7</span> <<else>> <span style="color: #ff6b6b; font-size: 12px; margin-left: 10px;">Requires bank account ($250 at Downtown Bank, open 8 AM - 5 PM)</span> <</if>> </div> <div> <<if _hasBankAccount>> <<link "<div style='display: inline-block; background: #4dabf7; color: white; padding: 8px 20px; border-radius: 6px; font-weight: bold; font-size: 14px;'>Use ATM</div>" "ATM">><</link>> <<else>> <div style='display: inline-block; background: #444; color: #888; padding: 8px 20px; border-radius: 6px; font-weight: bold; font-size: 14px; cursor: not-allowed; border: 1px solid #555;'> No Account </div> <</if>> </div> </div> <!-- Cocktail Waitress Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Cocktail Waitress")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🍸 Apply: Cocktail Waitress</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Cocktail Waitress")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🍸 Apply: Cocktail Waitress</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #e91e9e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e91e9e; margin: 0 0 10px 0;">🍸 Apply: Cocktail Waitress</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $15/hour + tips</p> <<link "<div style='background: #e91e9e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "CocktailWaitressJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Cocktail Waitress Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Cocktail Waitress">> <div style="border: 3px solid #e91e9e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e91e9e; margin: 0 0 10px 0;">🍸 Cocktail Waitress Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Clock in for your cocktail service shift. Work the casino floor and earn tips! (Max 8 hours/day)</p> <<link "<div style='background: #e91e9e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Work Shift</div>">> <<goto "CocktailWaitressWork">> <</link>> </div> <</if>> <!-- Musician Discovery --> <<if (!$jobs || $jobs.length === 0 || $jobs[0] !== "Musician") && (!$discoveredJobs || !$discoveredJobs.includes("Musician")) && setup.playerHasTrait("Musical")>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a1a3e 0%, #1a1a2e 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🎵 Musical Opportunity</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0; line-height: 1.4;">You notice a sign by the stage: "Open Mic Nights - Musicians Welcome!" With your musical skills, you could start performing here and build a career.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🎵 Start Your Music Career</div>">> <<if !$discoveredJobs>><<set $discoveredJobs = []>><</if>> <<run $discoveredJobs.push("Musician")>> <<set $jobs = ["Musician"]>> <<goto "Casino">> <</link>> </div> <</if>> <!-- Musician Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Musician">> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🎵 Musician Gig</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Head to your venue and perform for the crowd! Pick your gig level and earn flat pay plus tips. (Max 8 hours/day)</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Work Shift</div>">> <<goto "AmateurMusicianWork">> <</link>> </div> <</if>> <!-- Navigation --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<workShift>> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<set _alreadyTalkedToday = ($dailyConversations[_npc.name] !== undefined && $dailyConversations[_npc.name] >= $dayNumber)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Player's Dialogue --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 15px 0; font-size: 22px;">You say...</h3> <<if $physicalTraits && $physicalTraits.includes("Cerberus")>> <<for _cerbHd range setup.getCerberusHeadDialogues($currentTopic)>> <<set _cerbParsed = setup.extractEmote(_cerbHd.line)>> <div style="font-size: 17px; line-height: 1.8; margin-bottom: 12px;"> <<if _cerbParsed.emote>><div @style="'font-size: 15px; margin-bottom: 4px; font-style: italic; opacity: 0.75; color: ' + _cerbHd.color + ';'"><<= _cerbParsed.emote>></div><</if>> <<if _cerbParsed.text>><div @style="'font-style: italic; color: ' + _cerbHd.color + ';'">"<<= _cerbParsed.text>>"</div><</if>> </div> <</for>> <<else>> <<set _playerParsed = setup.extractEmote(setup.getPlayerDialogue($currentTopic))>> <div style="color: #ccc; font-size: 17px; line-height: 1.8;"> <<if _playerParsed.emote>><div style="color: #999; font-size: 15px; margin-bottom: 8px; font-style: italic;"><<= _playerParsed.emote>></div><</if>> <<if _playerParsed.text>><div style="font-style: italic;">"<<= _playerParsed.text>>"</div><</if>> </div> <</if>> </div> <<set _confessResult = null>> <<if $currentTopic === "confessFeelings">> <<set _confessResult = setup.romance.confess(_npc)>> <</if>> <!-- NPC's Response --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px;"><<= _npc.name>> responds...</h3> <<set _relationship = $relationships[_npc.name] || {level: 1, points: 0}>> <<set _relLevel = _relationship.level>> <<set _npcParsed = setup.extractEmote(setup.getNPCResponse(_npc, $currentTopic, _relLevel))>> <div style="color: #ccc; font-size: 17px; line-height: 1.8;"> <<if _npcParsed.emote>><div style="color: #999; font-size: 15px; margin-bottom: 8px; font-style: italic;"><<= _npcParsed.emote>></div><</if>> <<if _npcParsed.text>><div style="font-style: italic;">"<<= _npcParsed.text>>"</div><</if>> </div> </div> <<if $currentTopic === "endThings">> <<run setup.romance.breakup(_npc.name, "voluntary")>> <div style="background: #4a2a2a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 15px; text-align: center;"> <span style="color: #ff6b6b; font-weight: bold;">💔 Your romantic relationship has ended. You remain Close Friends.</span> </div> <</if>> <<if _confessResult && _confessResult.cheatingBreakup>> <div style="background: #4a2a2a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 15px; text-align: center;"> <span style="color: #ff6b6b; font-weight: bold;">💔 <<= _confessResult.cheatingBreakup>> found out and broke up with you!</span> </div> <</if>> <!-- Relationship Change - ONLY if not already talked today --> <<if !_alreadyTalkedToday>> <!-- Block relationship gains if NPC has no positive mental traits --> <<if !setup.hasPositiveMentalTraits(_npc)>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #555; text-align: center;"> <span style="color: #888; font-style: italic;">This person seems impossible to connect with.</span> </div> <<set $dailyConversations[_npc.name] = $dayNumber>> <<else>> <!-- Use new dynamic calculation system --> <<set _backfired = false>> <<set _flirtResult = null>> <!-- Special handling for flirt topic --> <<if $currentTopic === "flirt">> <<set _flirtResult = setup.calculateFlirtOutcome(_npc, _relLevel)>> <<set _basePointsChange = _flirtResult.points>> <<if !_flirtResult.success && _flirtResult.points < 0>> <<set _backfired = true>> <</if>> <<else>> <!-- Use dynamic calculation for other topics --> <<set _dynamicResult = setup.calculateDynamicRelationshipChange(_npc, $currentTopic, _relLevel)>> <<set _basePointsChange = _dynamicResult.points>> <<set _backfired = _dynamicResult.backfired>> <</if>> <!-- No relationship points for asking about someone the NPC doesn't know --> <<if $currentTopic === "askAboutNPC" && $socialTarget>> <<set _askRel = setup.getNpcToNpcRelationship(_npc.name, $socialTarget)>> <<if (!_askRel || _askRel.type === "strangers") && !setup.npcSocial.shareWorkplace(_npc.name, $socialTarget)>> <<set _basePointsChange = 0>> <</if>> <</if>> <!-- ===== SKILL TREE: Daily Talk Bonus ===== --> <<set _skillTreeTalkBonus = setup.skillTree.getEffect("dailyTalkBonus")>> <<if _skillTreeTalkBonus > 0 && _basePointsChange > 0>> <<set _basePointsChange += _skillTreeTalkBonus>> <</if>> <!-- ===== BUFF: Daily Talk Bonus (well_rested, satisfied, food_social_glow, food_hearty_meal, etc.) ===== --> <<set _buffTalkBonus = 0>> <<if typeof setup.getBuffEffect === 'function'>> <<set _buffTalkBonus = setup.getBuffEffect("dailyTalkBonus") + setup.getBuffEffect("relationshipBonus")>> <</if>> <<if _buffTalkBonus > 0 && _basePointsChange > 0>> <<set _basePointsChange += _buffTalkBonus>> <</if>> <<set _finalPointsChange = _basePointsChange>> <!-- Mood modifier on relationship gains --> <<set _moodData = setup.calculateNPCMood(_npc, false)>> <<set _moodMod = setup.moodRelationshipModifiers[_moodData.name] || 1.0>> <<if _moodData.name === "flirty" && ($currentTopic === "flirt" || $currentTopic === "flirtPlayfully")>><<set _moodMod = 1.3>><</if>> <<if _moodMod !== 1.0>><<set _finalPointsChange = Math.round(_finalPointsChange * _moodMod)>><</if>> <!-- Home visit bonus (1.5x) --> <<if $homeTalkBonus && $homeTalkBonus > 1 && _finalPointsChange > 0>> <<set _finalPointsChange = Math.round(_finalPointsChange * $homeTalkBonus)>> <</if>> <<if _finalPointsChange !== 0>> <<run setup.addRelationshipPoints(_npc.name, _finalPointsChange)>> <<run setup.updateNPCMemory(_npc.name, $currentTopic, _finalPointsChange, _backfired)>> <<set $dailyConversations[_npc.name] = $dayNumber>> <<set _displayPoints = _finalPointsChange>> <<set _hasCupid = $physicalTraits && $physicalTraits.includes("Cupid") && _finalPointsChange > 0>> <<if _hasCupid>><<set _displayPoints = _displayPoints * 4>><</if>> <<set _hasWeresheep = $physicalTraits && $physicalTraits.includes("Weresheep") && _finalPointsChange > 0>> <<if _hasWeresheep>><<set _displayPoints = _displayPoints * 2>><</if>> <<set _hasNaiadBonus = ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad"))) && _finalPointsChange > 0>> <<if _hasNaiadBonus>><<set _displayPoints = _displayPoints * 8>><</if>> <div style="background: <<if _finalPointsChange > 0>>#2a4a2a<<else>>#4a2a2a<</if>>; border: 2px solid <<if _finalPointsChange > 0>>#51cf66<<else>>#ff6b6b<</if>>; padding: 15px; border-radius: 8px; margin-bottom: 25px; text-align: center;"> <span style="color: <<if _finalPointsChange > 0>>#51cf66<<else>>#ff6b6b<</if>>; font-weight: bold; font-size: 16px;"> <<if _backfired>> ⚠️ The conversation backfired! <br>(<<= _finalPointsChange>> points) <<elseif _finalPointsChange > 0>> 💚 Relationship improved! <<if _skillTreeTalkBonus > 0>> <span style="color: #9C27B0;">(⭐ +<<= _skillTreeTalkBonus>> Skill Tree)</span> <</if>> <<if _buffTalkBonus > 0>> <span style="color: #51cf66;">(🍽️ +<<= _buffTalkBonus>> Buff Bonus)</span> <</if>> <<if ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #e91e63;">(💖 8x Bonus!)</span> <</if>> <<if _hasCupid>> <span style="color: #ff69b4;">(💘 4x Cupid!)</span> <</if>> <<if _hasWeresheep>> <span style="color: #f0e6ff;">(🐑 2x Weresheep!)</span> <</if>> <<if _flirtResult && _flirtResult.sexualIntensity >= 1>> <span style="color: #ff69b4;">(🔥 Intense!)</span> <</if>> <<if _moodMod !== 1.0>> <span style="color: #ff9800;">(<<if _moodMod > 1.0>>☀️<<else>>☁️<</if>> Mood <<if _moodMod > 1.0>>+<<else>>-<</if>>)</span> <</if>> <<if $homeTalkBonus && $homeTalkBonus > 1>> <span style="color: #51cf66;">(🏠 1.5x Home Bonus!)</span> <</if>> <br>(+<<= _displayPoints>> points) <<else>> 💔 Relationship worsened! <<if _moodMod !== 1.0>> <span style="color: #ff9800;">(<<if _moodMod > 1.0>>☀️<<else>>☁️<</if>> Mood <<if _moodMod > 1.0>>+<<else>>-<</if>>)</span> <</if>> <br>(<<= _finalPointsChange>> points) <</if>> </span> </div> <</if>> <</if>> <</if>> <!-- Continue Button --> <div style="text-align: center;"> <<if $currentTopic === "inviteHomeFriend" || $currentTopic === "inviteHomeRomantic">> <<link "<div style='display: inline-block; background: #e91e63; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🏠 Head Home Together</div>">> <<run setup.homeVisit.invite(_npc.name)>> <<run advanceTime(15)>> <<goto setup.homeVisit.getPlayerHomePassage()>> <</link>> <<elseif $homeVisitReturn>> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🏠 Back Home</div>">> <<set $homeVisitReturn = false>> <<set $homeTalkBonus = 1>> <<goto setup.homeVisit.getPlayerHomePassage()>> <</link>> <<else>> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Conversation</div>">> <<goto "NPCTalk">> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<set _gift = $giftToGive>> <<if !_npc || !_gift>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <p style="color: #ff6b6b;">Error: Missing gift data.</p> [[Go Back|NPCTalk]] </div> <<else>> <<set _giftResult = setup.giveGift(_npc, _gift.id, _gift.type, _gift.foodIndex !== undefined ? _gift.foodIndex : _gift.fishIndex)>> /* Apply relationship points (with Gift Giver skill bonus) */ <<set _giftPts = _giftResult.points>> <<if _giftPts > 0 && typeof setup.skillTree !== "undefined">> <<set _giftPts = Math.floor(_giftPts * (1 + (setup.skillTree.getEffect("giftRelationshipBonus") || 0) / 100))>> <</if>> <<if setup.hasPositiveMentalTraits(_npc)>> <<run setup.addRelationshipPoints(_npc.name, _giftPts)>> <<run setup.updateNPCMemory(_npc.name, "gift", _giftResult.points, false)>> <</if>> /* Record gift for weekly cooldown */ <<run setup.recordGift(_npc.name)>> /* Mood shift from gifting */ <<run setup.shiftMoodFromInteraction(_npc, "gift", _giftResult.points)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> /* Gift Given Display */ <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4); text-align: center;"> <div style="font-size: 48px; margin-bottom: 10px;"><<print _giftResult.giftIcon>></div> <div style="color: #e91e63; font-size: 20px; font-weight: bold; margin-bottom: 8px;">You gave <<print _npc.name>> a <<print _giftResult.giftName>></div> </div> /* NPC Reaction */ <<set _reactionParsed = setup.extractEmote(_giftResult.reaction)>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px;"><<= _npc.name>> says...</h3> <div style="color: #ccc; font-size: 17px; line-height: 1.8;"> <<if _reactionParsed.emote>><div style="color: #999; font-size: 15px; margin-bottom: 8px; font-style: italic;"><<= _reactionParsed.emote>></div><</if>> <div style="font-style: italic;">"<<= _reactionParsed.text>>"</div> </div> </div> /* Relationship Change */ <<set _giftDisplayPts = _giftPts>> <<set _giftHasCupid = $physicalTraits && $physicalTraits.includes("Cupid") && _giftPts > 0>> <<set _giftHasWeresheep = $physicalTraits && $physicalTraits.includes("Weresheep") && _giftPts > 0>> <<set _giftHasNaiad = ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad"))) && _giftPts > 0>> <<if _giftHasCupid>><<set _giftDisplayPts = _giftDisplayPts * 4>><</if>> <<if _giftHasWeresheep>><<set _giftDisplayPts = _giftDisplayPts * 2>><</if>> <<if _giftHasNaiad>><<set _giftDisplayPts = _giftDisplayPts * 8>><</if>> <<if setup.hasPositiveMentalTraits(_npc) && _giftResult.points > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #51cf66; text-align: center;"> <span style="color: #51cf66; font-size: 18px; font-weight: bold;"> <<if _giftResult.quality === "perfect">> 💖 Perfect Gift! (+<<print _giftDisplayPts>> relationship) <<elseif _giftResult.quality === "loved">> ❤️ They loved it! (+<<print _giftDisplayPts>> relationship) <<elseif _giftResult.quality === "liked">> 💙 They liked it! (+<<print _giftDisplayPts>> relationship) <<else>> 🤍 (+<<print _giftDisplayPts>> relationship) <</if>> <<if _giftHasCupid>> <span style="color: #ff69b4;">(💘 4x Cupid!)</span> <</if>> <<if _giftHasWeresheep>> <span style="color: #f0e6ff;">(🐑 2x Weresheep!)</span> <</if>> <<if _giftHasNaiad>> <span style="color: #e91e63;">(💖 8x Bonus!)</span> <</if>> </span> </div> <<elseif _giftResult.quality === "refused">> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #555; text-align: center;"> <span style="color: #888; font-style: italic;">They refused the gift.</span> </div> <<elseif _giftResult.points < 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #ff6b6b; text-align: center;"> <span style="color: #ff6b6b; font-size: 18px; font-weight: bold;"> 💔 (<<print _giftResult.points>> relationship) </span> </div> <<elseif !setup.hasPositiveMentalTraits(_npc)>> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #555; text-align: center;"> <span style="color: #888; font-style: italic;">This person seems impossible to connect with.</span> </div> <</if>> /* Back Button */ <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Conversation</div>">> <<goto "NPCTalk">> <</link>> </div> </div> <</if>> <</nobr>>
<<silently>> <<if !$showScrollbar>> <<run $('<style id="scrollbar-toggle">::-webkit-scrollbar { display: none; } body { -ms-overflow-style: none; scrollbar-width: none; }</style>').appendTo('head')>> <<else>> <<run $('style#scrollbar-toggle').remove()>> <</if>> /* Save migration: inject maid cafe NPCs (Mochi/Ren/Clover) into old saves that predate the Maid Cafe update. Idempotent — skips when all three are already in $npcs. */ <<if setup.cafe && typeof setup.cafe.ensureMaidNPCs === "function">> <<run setup.cafe.ensureMaidNPCs()>> <</if>> <</silently>>
<<nobr>> <<set $lastLocation = "VIPLounge">> <<run setup.tickOjouRefinement("casinoVip", 5)>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("VIPLounge")>> <<run $visitedLocations.push("VIPLounge")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9D00FF; text-align: center;">🔒 VIP Lounge</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9D00FF;"> <p style="color: white; font-size: 18px; margin: 0;"> Private rooms with soundproof walls and exclusive service. Only the most privileged patrons are allowed access to this area. Ambient music plays softly while elegant decor creates an intimate atmosphere. </p> </div> <h2 style="color: #9D00FF;">This area is currently under development.</h2> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("VIPLounge")>> <h2 style="color: #9D00FF;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9D00FF; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="background: #1e1e1e; padding: 15px; border-radius: 8px; border: 2px solid #9D00FF; transition: all 0.3s;"> <<set _relLevel = setup.getRelationshipLevel(_npc.originalName || _npc.name)>> <<set _relColor = setup.getRelationshipColor(_relLevel)>> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> <span style="color: #9D00FF; font-weight: bold; font-size: 16px;"><<print _npc.name>></span> <span @style="'color: ' + _relColor + '; font-size: 13px; font-weight: bold;'"> <<print setup.getRelationshipStatus(_npc.originalName || _npc.name)>> </span> </div> <div style="color: #aaa; font-size: 14px; margin-bottom: 12px;"> <div><strong style="color: #9D00FF;">Job:</strong> <<print _npc.job>></div> <<if _npc.primaryPersonality>> <div><strong style="color: #9D00FF;">Personality:</strong> <<print _npc.primaryPersonality>></div> <</if>> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<link "<div style='background: #9D00FF; color: white; padding: 8px 15px; border-radius: 6px; font-weight: bold; font-size: 13px; text-align: center; flex: 1; min-width: 80px;'>Talk</div>">> <<set $talkingToNPC = _npc>> <<goto "NPCTalk">> <</link>> <<link "<div style='background: #444; color: #9D00FF; padding: 8px 15px; border-radius: 6px; border: 2px solid #9D00FF; font-weight: bold; font-size: 13px; text-align: center; flex: 1; min-width: 80px;'>Trade</div>">> <<set $tradingWithNPC = _npc>> <<goto "TradeHub">> <</link>> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 2px solid #444; margin-bottom: 25px;"> <p style="color: #888; text-align: center; margin: 0; font-size: 15px;"> No one is currently in the VIP lounge. </p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #9D00FF; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Strip Club</div>">> <<goto "StripClub">> <</link>> </div> </div> <</nobr>>
:: DayAdvancement <<widget "advanceDay">> <<set $dayNumber += 1>> <<set $dayCount = $dayNumber>> /* Advance day of week */ <<set _currentDayIndex = setup.dayOrder.indexOf($dayOfWeek)>> <<set _nextDayIndex = (_currentDayIndex + 1) % 7>> <<set $dayOfWeek = setup.dayOrder[_nextDayIndex]>> /* Check if new week */ <<if $dayOfWeek === "Monday">> <<set $weekNumber += 1>> <</if>> /* Reset daily trades (base 5 + bonus from home offices) */ <<set $tradesRemainingToday = 5 + ($bonusDailyTrades || 0)>> <<set $failedTradesWithToday = []>> /* Check if hair styling has expired */ <<if $hairStyleExpiry && $dayNumber >= $hairStyleExpiry>> <<run setup.setHairMessy()>> <<set $hairStyleExpiry = null>> <</if>> /* Reset secretary work hours */ <<if $secretaryHoursWorkedToday>> <<set $secretaryHoursWorkedToday = 0>> <</if>> /* Reset time to morning */ <<set $timeInMinutes = 480>> /* Reset daily conversations and gifts */ <<set $dailyConversations = {}>> <<set $dailyGifts = {}>> /* FISH BUCKET RESET AT DAY CHANGE */ <<if $fishBucketCount > 0 && !$giantChickenUnlocked>> <<if $lastLocation === "CoralReef">> <<set $fishBucketBlackoutPending = true>> <</if>> <<set $fishBucketCount = 0>> <</if>> <!-- RUINS PUZZLE DAILY RESET --> <<set $ruinsPuzzleAttemptedToday = false>> <<set $ruinsPathOrder = []>> <!-- TRANSFORMATION ABILITY DAILY RESETS --> <<set $youkoHypnotizeUsedToday = false>> <<set $ocelomehFreeTomeToday = false>> <<set $bansheeDrainUsedTonight = false>> <<set $cheshireSexToday = false>> <<set $homeGymHoursToday = 0>> <!-- MILK BOTTLING DAILY RESET --> <<set $milkedToday = false>> <<set $madeHoneyMilkToday = false>> <!-- GIFT COOLDOWN CLEANUP --> <<run setup.cleanGiftCooldowns()>> <!-- ATM AND ROULETTE RESETS --> <<run setup.resetATMLimit()>> <<run setup.checkRouletteReset()>> <!-- CONSTRUCTION AND GARDEN --> <<if typeof setup.construction !== 'undefined' && typeof setup.construction.dailyProcess === 'function'>> <<run setup.construction.dailyProcess()>> <</if>> <<if typeof setup.garden !== 'undefined' && typeof setup.garden.dailyProcess === 'function'>> <<run setup.garden.dailyProcess()>> <</if>> <!-- ROISIN WEEKLY RESET --> <<if $dayOfWeek === "Monday">> <<set $roisinTraitsSoldValue = 0>> <<set $sellWeeklyBonusUsed = false>> <</if>> <</widget>> <<widget "masturbationImage">><<nobr>> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _location = _args[0] || "bed">> <<set _gender = $bodyParts.gender || "Female">> <<set _genderType = _gender.toLowerCase() === "male" ? ($physicalTraits.includes("Cuntboy") ? "cuntboy" : "male") : ($physicalTraits.includes("Dickgirl") ? "futanari" : "female")>> <<set _ageType = $appearance.age === "Mature Adult" ? "mature" : "adult">> <<set _povImagePath = "Images/M/pov/masturbation_" + _location + "_" + _genderType + ".webp">> <<set _regularImagePath = "Images/M/regular/masturbation_" + _location + "_" + _genderType + "_" + _ageType + ".webp">> <div style="display: flex; gap: 20px; justify-content: center; margin-bottom: 15px; flex-wrap: wrap;"> <div style="text-align: center;"><img @src="_povImagePath" style="max-width: 350px; height: auto; border-radius: 10px; border: 2px solid #ff6b6b;" onerror="this.onerror=null; this.style.display='none'; this.nextElementSibling.style.display='block';"><div style="display: none; width: 300px; height: 200px; border-radius: 10px; border: 2px solid #ff6b6b; background: #1a1a1a;"></div></div> <div style="text-align: center;"><img @src="_regularImagePath" style="max-width: 350px; height: auto; border-radius: 10px; border: 2px solid #ff6b6b;" onerror="this.onerror=null; this.style.display='none'; this.nextElementSibling.style.display='block';"><div style="display: none; width: 300px; height: 200px; border-radius: 10px; border: 2px solid #ff6b6b; background: #1a1a1a;"></div></div> </div> <</if>> <</nobr>><</widget>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("StudioApartment")>> <<run $visitedLocations.push("StudioApartment")>> <</if>> <<set $lastLocation = "StudioApartment">> <<set _home = "StudioApartment">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(26, 26, 26, 0.9); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("StudioApartment")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <!-- Home Visitor Card --> <<if $homeVisitor>> <<set _visitorNPC = setup.homeVisit.getVisitorNPC()>> <<if _visitorNPC>> <<set _visMood = setup.calculateNPCMood(_visitorNPC, false)>> <<set _visMoodDef = setup.moodDefinitions[_visMood.name] || setup.moodDefinitions.neutral>> <div style="background: linear-gradient(135deg, #2a1a2e 0%, #1a2a1e 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; box-shadow: 0 4px 12px rgba(0,0,0,0.4);"> <div style="display: flex; align-items: center; gap: 15px; margin-bottom: 15px;"> <span style="font-size: 32px;"><<if $homeVisitor.type === 'romantic'>>💕<<else>>👋<</if>></span> <div> <h3 style="color: <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; margin: 0;"><<= _visitorNPC.name>> is here</h3> <span style="color: #aaa; font-size: 14px;"><<if $homeVisitor.type === 'romantic'>>Romantic visit<<else>>Hanging out<</if>> · <span style="color: <<= _visMoodDef.color>>;"><<= _visMoodDef.icon>> <<= _visMoodDef.label>></span></span> </div> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<if !$homeVisitor.homeTalkUsed>> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>💬 Chat</div>">> <<set $homeVisitor.homeTalkUsed = true>> <<set $dailyConversations[_visitorNPC.name] = 0>> <<set $homeTalkBonus = 1.5>> <<set $homeVisitReturn = true>> <<set $tradingWithNPC = _visitorNPC>> <<goto "NPCTalk">> <</link>> <<else>> <div style="display: inline-block; background: #333; color: #666; padding: 10px 20px; border-radius: 8px; font-weight: bold;">💬 Already Chatted</div> <</if>> <<if setup.homeVisit.canHomeIntimate()>> <<link "<div style='display: inline-block; background: #e91e63; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>❤️ Get Intimate</div>">> <<set $romanceTarget = _visitorNPC.name>> <<goto "HomeIntimateSelect">> <</link>> <<elseif $homeVisitor && !$homeVisitor.homeIntimateUsed>> <<set _intimateHint = setup.homeVisit.getIntimateHint()>> <<if _intimateHint>> <div style="display: inline-block; background: #2a1a2a; color: #c9a9ff; padding: 8px 16px; border-radius: 8px; font-size: 13px; font-style: italic; border: 1px dashed #6e4ea8;">💔 <<= _intimateHint>></div> <</if>> <</if>> <<link "<div style='display: inline-block; background: #666; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>👋 Say Goodbye</div>">> <<run setup.homeVisit.dismiss()>> <<goto _home>> <</link>> </div> </div> <</if>> <</if>> <h2 style="color: #51cf66;">Main Room</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bedroom --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🛏️ Bedroom</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Your sleeping area with a fold-out bed.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bedroom</div>">> <<run advanceTime(1)>> <<goto "StudioBedroom">> <</link>> </div> <!-- Kitchenette --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🍳 Kitchenette</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A small cooking area with basic appliances.</p> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Cook Something</div>">> <<run advanceTime(1)>> <<goto "HomeKitchen">> <</link>> </div> <!-- TV Area --> <<if $hasTV>> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">📺 Television</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Watch TV and relax.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Watch TV</div>">> <<goto "WatchTV">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">📺 TV Stand</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An empty TV stand. You could buy a television to place here.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic; margin-top: 10px;'>No TV</div> </div> <</if>> <!-- Laptop Area --> <<if $hasLaptop>> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💻 Laptop</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Use your laptop for various activities.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Laptop</div>">> <<set $laptopReturnLocation = "StudioApartment">> <<goto "UseLaptop">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">💻 Desk</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An empty desk. You could buy a laptop to place here.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic; margin-top: 10px;'>No Laptop</div> </div> <</if>> <!-- Milk Bottling (Hucow/Lactating only) --> <<if ($physicalTraits && ($physicalTraits.includes("Hucow") || $physicalTraits.includes("Lactating")))>> <div style="border: 3px solid #f8bbd0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f8bbd0; margin: 0 0 10px 0;">🥛 Milk Bottling</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Express and bottle milk for gifting.</p> <<link "<div style='background: #f8bbd0; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Bottle Milk</div>">> <<goto "MilkBottling">> <</link>> </div> <</if>> </div> <h2 style="color: #51cf66;">Other Rooms</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bathroom --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Bathroom</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A small bathroom with shower, toilet, mirror, and storage cabinet.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bathroom</div>">> <<run advanceTime(1)>> <<goto "StudioBathroom">> <</link>> </div> </div> <h2 style="color: #51cf66;">Home Management</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Invite Someone Over --> <<if !$homeVisitor>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #444;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏠 Invite Someone Over</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Invite a friend or partner over</p> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>Choose Guest</div>">> <<goto "HomeInviteSelect">> <</link>> </div> <</if>> <!-- Decor Manager --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🎨 Decor Manager</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">View and manage your placed decorations.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Manage Decor</div>">> <<goto "HomeDecorManager">> <</link>> </div> <!-- Wall Color --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🖌️ Wall Paint</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Change your wall colors.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Paint Walls</div>">> <<goto "WallColorPicker">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Leave Apartment</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* Prevent infinite loop - only process once per work session */ <<if $lastWorkProcessed === true>> <<goto $lastLocation || "Home">> <</if>> <<set $lastWorkProcessed = true>> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes($lastWorkJob)>> <<run $jobsWorked.push($lastWorkJob)>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <!-- SAVE CASH TO PREVENT ACCIDENTAL DOUBLE ADDITIONS --> <<set _savedMoney = $money>> <<set _savedBankBalance = $bankAccount ? $bankAccount.balance : 0>> <!-- ===== SKILL TREE: Get hourly pay bonus ===== --> <<set _hourlyPayBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _hourlyPayBonus = setup.skillTree.getEffect("hourlyPayBonus") || 0>> <</if>> <!-- Universal hours counter for trait gain (guaranteed every 40 hours) --> <<if typeof $hourlyJobHoursWorked === "undefined">> <<set $hourlyJobHoursWorked = 0>> <</if>> <<set $hourlyJobHoursWorked += $lastWorkHours>> <<set $totalHoursWorked = ($totalHoursWorked || 0) + $lastWorkHours>> <<set $totalMoneyEarned = ($totalMoneyEarned || 0) + ($lastWorkEarnings || 0)>> <<set _gainedWorkTrait = false>> <<set _gainedWorkTraitName = "">> <<set _gainedWorkTraitType = "">> <<set _hasConflict = false>> <<set _conflictingTrait = "">> <<set _pendingTrait = null>> <!-- Gain a trait every 40 hours worked (reduced by skill tree) --> <<set _traitHoursNeeded = 40 - setup.skillTree.getEffect("traitHoursReduction")>> <<if $hourlyJobHoursWorked >= _traitHoursNeeded && !$clairFormActive>> <<set $hourlyJobHoursWorked -= _traitHoursNeeded>> <<set _jobTraitPools = { "Dock Worker": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Relaxed", type: "mental"}, {name: "Strong", type: "physical"}, {name: "Sturdy", type: "physical"}, {name: "Forklift Certified", type: "skill"}, {name: "Heavy Lifting", type: "skill"} ], "Tech Store Clerk": [ {name: "Deep Thinker", type: "mental"}, {name: "Analytical", type: "mental"}, {name: "Direct", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Intelligent", type: "mental"}, {name: "Resourceful", type: "mental"}, {name: "Customer Service", type: "skill"}, {name: "Inventory Management", type: "skill"}, {name: "Product Knowledge", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Sales", type: "skill"}, {name: "Tech-Savvy", type: "skill"} ], "Adult Store Clerk": [ {name: "Product Knowledge", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Sales", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Perceptive", type: "mental"}, {name: "Charming", type: "mental"}, {name: "Chill", type: "mental"}, {name: "Curious", type: "mental"}, {name: "Flirty", type: "mental"}, {name: "Nonchalant", type: "mental"}, {name: "Sly", type: "mental"} ], "Ecentric Shop Worker": [ {name: "Product Knowledge", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Sales", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Perceptive", type: "mental"}, {name: "Goth", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Introverted", type: "mental"} ], "Baker": [ {name: "Baking", type: "skill"}, {name: "Cooking", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Hardworking", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Organized", type: "mental"}, {name: "Detail-Oriented", type: "mental"} ], "Fitness Shop Clerk": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Sales", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Product Knowledge", type: "skill"}, {name: "Friendly", type: "mental"}, {name: "Energetic", type: "mental"} ], "Beauty Salon Stylist": [ {name: "Hair Styling", type: "skill"}, {name: "Makeup", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Creative", type: "mental"}, {name: "Perceptive", type: "mental"}, {name: "Friendly", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Customer Service", type: "skill"} ], "Barista": [ {name: "Customer Service", type: "skill"}, {name: "Friendly", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Energetic", type: "mental"}, {name: "Charming", type: "mental"}, {name: "Cooking", type: "skill"}, {name: "Organized", type: "mental"}, {name: "Warm", type: "mental"} ], "Package Courier": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Energetic", type: "mental"}, {name: "Hardworking", type: "mental"}, {name: "Resourceful", type: "mental"}, {name: "Focused", type: "mental"} ], "Construction Worker": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Strong", type: "physical"}, {name: "Sturdy", type: "physical"}, {name: "Hardworking", type: "mental"}, {name: "Heavy Lifting", type: "skill"} ], "Security Guard": [ {name: "Disciplined", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Wise", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Sturdy", type: "physical"}, {name: "Broad-shouldered", type: "physical"} ], "Maid": [ {name: "Organized", type: "mental"}, {name: "Hardworking", type: "mental"}, {name: "Detail-Oriented", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Maid", type: "skill"}, {name: "Cleaning", type: "skill"} ], "Bouncer": [ {name: "Broad-shouldered", type: "physical"}, {name: "Strong", type: "physical"}, {name: "Confident", type: "mental"}, {name: "Disciplined", type: "mental"}, {name: "Direct", type: "mental"}, {name: "Athletic Build", type: "physical"} ], "Clinic Assistant": [ {name: "Intelligent", type: "mental"}, {name: "Analytical", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Kind", type: "mental"}, {name: "Perceptive", type: "mental"}, {name: "Detail-Oriented", type: "mental"} ], "Data Analyst": [ {name: "Intelligent", type: "mental"}, {name: "Analytical", type: "mental"}, {name: "Deep Thinker", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Tech-Savvy", type: "skill"}, {name: "Organized", type: "mental"} ], "Enforcer": [ {name: "Broad-shouldered", type: "physical"}, {name: "Strong", type: "physical"}, {name: "Aggressive", type: "mental"}, {name: "Direct", type: "mental"}, {name: "Shrewd", type: "mental"}, {name: "Cruel", type: "mental"} ], "Police Station Janitor": [ {name: "Hardworking", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Organized", type: "mental"}, {name: "Cleaning", type: "skill"}, {name: "Wise", type: "mental"}, {name: "Humble", type: "mental"} ], "Police Station Receptionist": [ {name: "Customer Service", type: "skill"}, {name: "Organized", type: "mental"}, {name: "Friendly", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Perceptive", type: "mental"}, {name: "Efficient", type: "mental"} ], "Bus Driver": [ {name: "Patient", type: "mental"}, {name: "Calm", type: "mental"}, {name: "Driving", type: "skill"}, {name: "Navigation", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Observant", type: "mental"} ], "Donuts Deliverer": [ {name: "Quick", type: "mental"}, {name: "Energetic", type: "mental"}, {name: "Driving", type: "skill"}, {name: "Hardworking", type: "mental"}, {name: "Customer Service", type: "skill"}, {name: "Fit", type: "physical"} ], "Cocktail Waitress": [ {name: "Charming", type: "mental"}, {name: "Graceful", type: "physical"}, {name: "Serving", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Flirty", type: "mental"}, {name: "Persuasion", type: "skill"}, {name: "Quick", type: "mental"} ], "Fitness Trainer": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Energetic", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Coaching", type: "skill"}, {name: "Hardworking", type: "mental"}, {name: "Strong", type: "physical"}, {name: "Muscular", type: "physical"} ], "Prostitute": [ {name: "Streetwise", type: "mental"}, {name: "Sexually Skilled", type: "skill"}, {name: "Persuasion", type: "skill"}, {name: "Tough", type: "physical"}, {name: "Alert", type: "mental"}, {name: "Charming", type: "mental"} ], "Street Performer": [ {name: "Performer", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Entertainer", type: "skill"}, {name: "Outgoing", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Showmanship", type: "skill"} ], "Musician": [ {name: "Musical", type: "skill"}, {name: "Performer", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Showmanship", type: "skill"}, {name: "Charming", type: "mental"} ], "Dancing Instructor": [ {name: "Graceful", type: "physical"}, {name: "Flexible", type: "physical"}, {name: "Dancing", type: "skill"}, {name: "Patient", type: "mental"}, {name: "Artistic", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Charming", type: "mental"} ], "Social Media Influencer": [ {name: "Social Media", type: "skill"}, {name: "Photography", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Trendy", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Charming", type: "mental"} ], "Black Market Dealer": [ {name: "Streetwise", type: "skill"}, {name: "Persuasion", type: "skill"}, {name: "Analytical", type: "mental"}, {name: "Sly", type: "mental"}, {name: "Shrewd", type: "mental"}, {name: "Risk-Taker", type: "skill"} ], "Negotiator": [ {name: "Persuasion", type: "skill"}, {name: "Analytical", type: "mental"}, {name: "Diplomatic", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Observant", type: "skill"}, {name: "Shrewd", type: "mental"} ], "Model": [ {name: "Modeling", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Graceful", type: "physical"}, {name: "Photogenic", type: "skill"}, {name: "Confident", type: "mental"}, {name: "Poised", type: "skill"}, {name: "Striking", type: "skill"} ], "Porn Star": [ {name: "Sexually Skilled", type: "skill"}, {name: "Acting", type: "skill"}, {name: "Exhibitionist", type: "skill"}, {name: "Confident", type: "mental"}, {name: "Seductive", type: "mental"}, {name: "Charming", type: "mental"}, {name: "Performer", type: "skill"} ] }>> <!-- Check if this job has a trait pool --> <<if _jobTraitPools[$lastWorkJob]>> <<set _availableWorkTraits = []>> <!-- Filter out traits the player already has --> <<for _i = 0; _i < _jobTraitPools[$lastWorkJob].length; _i++>> <<set _traitData = _jobTraitPools[$lastWorkJob][_i]>> <<set _hasIt = false>> <<if _traitData.type === "physical" && $physicalTraits.includes(_traitData.name)>> <<set _hasIt = true>> <<elseif _traitData.type === "mental" && $mentalTraits.includes(_traitData.name)>> <<set _hasIt = true>> <<elseif _traitData.type === "skill" && $skills.includes(_traitData.name)>> <<set _hasIt = true>> <</if>> <<if !_hasIt>> <<set _availableWorkTraits.push(_traitData)>> <</if>> <</for>> <!-- If there are traits available to gain, pick one randomly --> <<if _availableWorkTraits.length > 0>> <<set _selectedWorkTrait = _availableWorkTraits.random()>> <<set _gainedWorkTraitName = _selectedWorkTrait.name>> <<set _gainedWorkTraitType = _selectedWorkTrait.type>> <!-- Check for mutually exclusive trait conflict --> <<set _existingTraits = []>> <<if _gainedWorkTraitType === "physical">> <<set _existingTraits = $physicalTraits>> <<elseif _gainedWorkTraitType === "mental">> <<set _existingTraits = $mentalTraits>> <</if>> <!-- Only check for conflicts on physical/mental traits, not skills --> <<if (_gainedWorkTraitType === "physical" || _gainedWorkTraitType === "mental") && typeof setup.getConflictingTrait === "function">> <<set _conflictingTrait = setup.getConflictingTrait(_gainedWorkTraitName, _existingTraits)>> <</if>> <<if _conflictingTrait>> <!-- Has conflict - store pending trait for popup, DON'T add yet --> <<set _hasConflict = true>> <<set _pendingTrait = _selectedWorkTrait>> <!-- Store for the result passage --> <<set $pendingWorkTrait = _selectedWorkTrait>> <<set $pendingWorkTraitConflict = _conflictingTrait>> <<else>> <!-- No conflict - add trait directly --> <<if _selectedWorkTrait.type === "skill">> <<if !$skills.includes(_gainedWorkTraitName)>> <<set $skills.push(_gainedWorkTraitName)>> <</if>> <<elseif _selectedWorkTrait.type === "mental">> <<if !$mentalTraits.includes(_gainedWorkTraitName)>> <<set $mentalTraits.push(_gainedWorkTraitName)>> <</if>> <<elseif _selectedWorkTrait.type === "physical">> <<if !$physicalTraits.includes(_gainedWorkTraitName)>> <<set $physicalTraits.push(_gainedWorkTraitName)>> <</if>> <</if>> <<set _gainedWorkTrait = true>> <</if>> <</if>> <</if>> <</if>> <!-- Co-worker relationship bonus (if worked 2+ hours with co-workers) --> <<set _coworkerBonuses = []>> <<if $lastWorkHours >= 2>> <<set _coworkers = setup.getNPCsByJob($lastWorkJob)>> <<if _coworkers && _coworkers.length > 0>> <<for _i = 0; _i < _coworkers.length; _i++>> <<set _coworker = _coworkers[_i]>> <<set _coworkerName = _coworker.name>> <!-- 50% chance to gain relationship points with each co-worker --> <<if random(1, 100) <= 50>> <!-- Random 1-5 points --> <<set _relPoints = random(1, 5)>> <!-- Ensure we've "met" this co-worker --> <<run setup.meetNPC(_coworker)>> <!-- Add relationship points --> <<run setup.addRelationshipPoints(_coworkerName, _relPoints)>> <!-- Track for display --> <<run _coworkerBonuses.push({name: _coworkerName, points: _relPoints})>> <</if>> <</for>> <</if>> <</if>> <<set $lastWorkCoworkerBonuses = _coworkerBonuses>> <!-- Calculate earnings breakdown for display (skip if job handled payment internally) --> <<if !$lastWorkPaymentHandled>> <!-- $lastWorkEarnings already has stat/trait modifiers and Pearl bonus applied from workShift --> <!-- $lastWorkBasePay is the true base (hours × hourlyPay without any modifiers) --> <<set _pearlActive = $currentArtifact === "The Pearl of Abundance">> <!-- Extract base pay with stat/trait modifiers but WITHOUT Pearl bonus --> <<set _baseWithModifiers = _pearlActive ? Math.floor($lastWorkEarnings / 1.5) : $lastWorkEarnings>> <<set _pearlBonus = _pearlActive ? ($lastWorkEarnings - _baseWithModifiers) : 0>> <!-- ===== SKILL TREE: Calculate hourly pay bonus ===== --> <<set _skillTreeBonus = 0>> <<if _hourlyPayBonus > 0>> <<set _skillTreeBonus = Math.floor(_baseWithModifiers * (_hourlyPayBonus / 100))>> <</if>> <!-- ===== BUFF: Food money bonuses ===== --> <<set _foodMoneyBonus = 0>> <<if typeof setup.getBuffEffect === 'function'>> <<set _buffMoneyBonusMin = setup.getBuffEffect("moneyBonusMin")>> <<set _buffMoneyBonusMax = setup.getBuffEffect("moneyBonusMax")>> <<set _buffMoneyBonus = setup.getBuffEffect("moneyBonus")>> <<if _buffMoneyBonusMin > 0 || _buffMoneyBonusMax > 0>> <<set _foodMoneyBonus += Math.floor(Math.random() * (_buffMoneyBonusMax - _buffMoneyBonusMin + 1)) + _buffMoneyBonusMin>> <</if>> <<if _buffMoneyBonus > 0>> <<set _foodMoneyBonus += _buffMoneyBonus>> <</if>> <</if>> <!-- Total earnings before bank bonus --> <<set _totalEarningsBeforeBank = _baseWithModifiers + _pearlBonus + _skillTreeBonus + _foodMoneyBonus>> <!-- Check if player has bank account for direct deposit --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<set _totalDeposited = 0>> <!-- RESTORE CASH/BANK TO PREVENT DOUBLE ADDITIONS FROM HELPER FUNCTIONS --> <<set $money = _savedMoney>> <<if $bankAccount>> <<set $bankAccount.balance = _savedBankBalance>> <</if>> <<if _hasBankAccount>> <!-- Calculate 5% direct deposit bonus --> <<set _creditBonus = Math.floor(_totalEarningsBeforeBank * 0.05)>> <<set _totalDeposited = _totalEarningsBeforeBank + _creditBonus>> <!-- Add directly to bank account --> <<set $bankAccount.balance += _totalDeposited>> <<else>> <!-- No bank account - pay in cash only --> <<set $money += _totalEarningsBeforeBank>> <</if>> <!-- Store earnings info for trait result passage if needed --> <<set $lastWorkPearlActive = _pearlActive>> <<set $lastWorkBaseEarnings = _baseWithModifiers>> <!-- Base + stat/trait modifiers, no Pearl/skill bonuses --> <<set $lastWorkPearlBonus = _pearlBonus>> <<set $lastWorkSkillTreeBonus = _skillTreeBonus>> <<set $lastWorkFoodMoneyBonus = _foodMoneyBonus>> <<set $lastWorkHasBankAccount = _hasBankAccount>> <<set $lastWorkCreditBonus = _creditBonus>> <<set $lastWorkTotalDeposited = _totalDeposited>> <<set $lastWorkTotalEarningsBeforeBank = _totalEarningsBeforeBank>> <<else>> <!-- Payment already handled by job macro (e.g. Social Media Influencer) --> <<set $lastWorkBaseEarnings = 0>> <<set $lastWorkPearlBonus = 0>> <<set $lastWorkSkillTreeBonus = 0>> <<set $lastWorkFoodMoneyBonus = 0>> <<set $lastWorkHasBankAccount = false>> <<set $lastWorkCreditBonus = 0>> <<set $lastWorkTotalDeposited = 0>> <<set $lastWorkTotalEarningsBeforeBank = 0>> <</if>> <<set $lastWorkGainedTrait = _gainedWorkTrait>> <<set $lastWorkGainedTraitName = _gainedWorkTraitName>> <<set $lastWorkGainedTraitType = _gainedWorkTraitType>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #28a745 0%, #20c997 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 2px solid #28a745;"> <h1 style="color: white; margin: 0 0 10px 0; font-size: 36px;">✅ Shift Complete!</h1> <p style="color: white; margin: 0; font-size: 18px;">You've finished your shift as a <<print $lastWorkJob>></p> </div> <!-- MUTUALLY EXCLUSIVE TRAIT CONFLICT POPUP --> <<if _hasConflict && _pendingTrait>> <div style="background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); padding: 25px; border-radius: 12px; border: 3px solid #f39c12; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(243, 156, 18, 0.5); margin-bottom: 25px;"> <h2 style="color: white; margin: 0 0 15px 0; text-align: center;">⚡ Trait Conflict Detected!</h2> <p style="color: #fff; font-size: 16px; margin: 0 0 15px 0; text-align: center;"> Your work experience would grant you <strong style="color: #ffd43b;"><<print _gainedWorkTraitName>></strong>, but it conflicts with your existing trait <strong style="color: #ff6b6b;"><<print _conflictingTrait>></strong>. </p> <p style="color: #ffd; font-size: 14px; margin: 0 0 20px 0; text-align: center; font-style: italic;"> These traits are mutually exclusive - you can only have one. </p> <!-- Trait Comparison --> <div style="display: grid; grid-template-columns: 1fr auto 1fr; gap: 15px; margin-bottom: 20px; align-items: center;"> <!-- Current Trait --> <div style="background: #3a2020; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center;"> <p style="color: #ff6b6b; font-size: 12px; margin: 0 0 5px 0;">CURRENT</p> <p style="color: #fff; font-size: 18px; font-weight: bold; margin: 0;"><<print _conflictingTrait>></p> <<if typeof setup.getTraitValue === "function">> <p style="color: #aaa; font-size: 12px; margin: 5px 0 0 0;">Value: <<print setup.getTraitValue(_pendingTrait.type, _conflictingTrait)>></p> <</if>> </div> <!-- Arrow --> <div style="color: #ffd43b; font-size: 24px;">→</div> <!-- New Trait --> <div style="background: #203a20; padding: 15px; border-radius: 8px; border: 2px solid #51cf66; text-align: center;"> <p style="color: #51cf66; font-size: 12px; margin: 0 0 5px 0;">NEW</p> <p style="color: #fff; font-size: 18px; font-weight: bold; margin: 0;"><<print _gainedWorkTraitName>></p> <<if typeof setup.getTraitValue === "function">> <p style="color: #aaa; font-size: 12px; margin: 5px 0 0 0;">Value: <<print setup.getTraitValue(_pendingTrait.type, _gainedWorkTraitName)>></p> <</if>> </div> </div> <!-- Choice Buttons --> <div style="display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='display: inline-block; background: #28a745; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>✓ Replace with New Trait</div>">> <<set $workTraitSwapped = true>> <<goto "WorkCompleteTraitResult">> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>✗ Keep Current Trait</div>">> <<set $workTraitSwapped = false>> <<goto "WorkCompleteTraitResult">> <</link>> </div> </div> <<else>> <!-- No conflict - show normal trait gain notification --> <<if _gainedWorkTrait>> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 25px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(155, 89, 182, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: white; margin: 0 0 15px 0;">✨ Work Experience Gained!</h2> <p style="color: #ffd; font-size: 18px; margin: 0 0 10px 0;"> Your hard work has paid off!<br> You gained: <strong style="color: #ffd43b;"><<print _gainedWorkTraitName>></strong> </p> <p style="color: #ccc; font-size: 14px; margin: 0;"> <<if _gainedWorkTraitType === "skill">> (New Skill) <<elseif _gainedWorkTraitType === "mental">> (Mental Trait) <<elseif _gainedWorkTraitType === "physical">> (Physical Trait) <</if>> </p> </div> <!-- Transformation text for gained trait --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; text-align: center;">🔄 Transformation</h3> <<if _gainedWorkTraitType === "skill">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<set _transformText = "">> <<if typeof setup.getSkillGainText === "function">> <<set _transformText = setup.getSkillGainText(_gainedWorkTraitName)>> <</if>> <<if _transformText && _transformText.length > 0>> <<print _transformText>> <<else>> Through dedicated practice at work, you've developed a new ability: <strong><<print _gainedWorkTraitName>></strong>. This skill will serve you well in future endeavors. <</if>> </p> </div> <<elseif _gainedWorkTraitType === "mental">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #764ba2;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<set _transformText = "">> <<if typeof setup.getMentalTraitChangeText === "function">> <<set _transformText = setup.getMentalTraitChangeText(_gainedWorkTraitName, true)>> <</if>> <<if _transformText && _transformText.length > 0>> <<print _transformText>> <<else>> Your experiences at work have subtly changed your mindset. You find yourself becoming more <strong><<print _gainedWorkTraitName>></strong> as each day passes. <</if>> </p> </div> <<elseif _gainedWorkTraitType === "physical">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #28a745;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<set _transformText = "">> <<if typeof setup.getPhysicalTraitChangeText === "function">> <<set _transformText = setup.getPhysicalTraitChangeText(_gainedWorkTraitName, true)>> <</if>> <<if _transformText && _transformText.length > 0>> <<print _transformText>> <<else>> The physical demands of your job have transformed your body over time. You now possess the trait: <strong><<print _gainedWorkTraitName>></strong>. <</if>> </p> </div> <</if>> </div> <</if>> <</if>> <<if $lastWorkTraitChanges && $lastWorkTraitChanges.length > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffc107; margin-top: 0; font-size: 24px; border-bottom: 3px solid #ffc107; padding-bottom: 10px;">⭐ Personal Changes</h2> <<for _i, _change range $lastWorkTraitChanges>> <<if _change.type === "gain">> <div style="background: #1a3a1a; padding: 15px; border-radius: 8px; margin-top: 10px; border: 2px solid #28a745;"> <p style="color: #28a745; margin: 0; font-size: 16px; font-weight: bold;">✨ Gained New Trait: <<print _change.trait>></p> </div> <<elseif _change.type === "upgrade">> <div style="background: #1a1a3a; padding: 15px; border-radius: 8px; margin-top: 10px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-size: 16px; font-weight: bold;">⬆️ Upgraded: <<print _change.oldTrait>> → <<print _change.newTrait>></p> </div> <<elseif _change.type === "remove">> <div style="background: #3a1a1a; padding: 15px; border-radius: 8px; margin-top: 10px; border: 2px solid #dc3545;"> <p style="color: #dc3545; margin: 0; font-size: 16px; font-weight: bold;">❌ Removed: <<print _change.trait>></p> </div> <<elseif _change.type === "replace">> <div style="background: #3a1a3a; padding: 15px; border-radius: 8px; margin-top: 10px; border: 2px solid #9b59b6;"> <p style="color: #9b59b6; margin: 0; font-size: 16px; font-weight: bold;">🔄 Replaced: <<print _change.oldTrait>> → <<print _change.newTrait>></p> </div> <</if>> <</for>> </div> <</if>> <!-- Co-worker relationship bonuses --> <<if _coworkerBonuses && _coworkerBonuses.length > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin-top: 0; font-size: 24px; border-bottom: 3px solid #667eea; padding-bottom: 10px;">👥 Co-Worker Bonding</h2> <p style="color: #aaa; font-size: 14px; margin-bottom: 15px;">Working alongside your co-workers has strengthened your relationships!</p> <<for _cwb range _coworkerBonuses>> <div style="background: #1a2a3a; padding: 12px 15px; border-radius: 8px; margin-top: 10px; border: 2px solid #51cf66; display: flex; justify-content: space-between; align-items: center;"> <span style="color: #fff; font-size: 16px;">💚 <<print _cwb.name>></span> <span style="color: #51cf66; font-weight: bold;">+<<print _cwb.points>> points</span> </div> <</for>> </div> <</if>> <!-- Show earnings - always show this now, even with conflict (earnings already processed) --> <<if $lastWorkPaymentHandled>> <!-- Earnings already shown by job macro, show bank deposit confirmation --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #28a745; margin-top: 0;">🏦 Earnings Deposited</h2> <p style="color: #ccc;">Your earnings have been deposited directly to your bank account.</p> <<if $bankAccount>><p style="color: #4dabf7;">Bank Balance: $<<print $bankAccount.balance>></p><</if>> </div> <<elseif !_hasConflict>> <<include "WorkCompleteEarnings">> <<else>> <!-- Show earnings summary for conflict case too --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #28a745; margin-top: 0; font-size: 24px; border-bottom: 3px solid #28a745; padding-bottom: 10px;">💰 Earnings</h2> <p style="color: #ccc; font-size: 16px; margin: 10px 0;">Base Pay: <span style="color: #51cf66;">$<<print _baseEarnings>></span></p> <<if _pearlBonus > 0>> <p style="color: #ccc; font-size: 16px; margin: 10px 0;">✨ Pearl Bonus: <span style="color: #ffd43b;">+$<<print _pearlBonus>></span></p> <</if>> <<if _skillTreeBonus > 0>> <p style="color: #ccc; font-size: 16px; margin: 10px 0;">⭐ Skill Tree Bonus: <span style="color: #9C27B0;">+$<<print _skillTreeBonus>></span></p> <</if>> <<if _hasBankAccount>> <p style="color: #ccc; font-size: 16px; margin: 10px 0;">🏦 Direct Deposit Bonus (5%): <span style="color: #3498db;">+$<<print _creditBonus>></span></p> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 15px 0;">Total Deposited: $<<print _totalDeposited>></p> <<else>> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 15px 0;">Total Earned: $<<print _totalEarningsBeforeBank>></p> <</if>> </div> <p style="color: #888; text-align: center; font-style: italic;">Choose whether to accept or reject the new trait above, then continue.</p> <</if>> <!-- Trait Progress Section --> <<set _jobTraitPoolsForProgress = { "Dock Worker": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Relaxed", type: "mental"}, {name: "Strong", type: "physical"}, {name: "Sturdy", type: "physical"}, {name: "Forklift Certified", type: "skill"}, {name: "Heavy Lifting", type: "skill"} ], "Tech Store Clerk": [ {name: "Deep Thinker", type: "mental"}, {name: "Analytical", type: "mental"}, {name: "Direct", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Intelligent", type: "mental"}, {name: "Resourceful", type: "mental"}, {name: "Customer Service", type: "skill"}, {name: "Inventory Management", type: "skill"}, {name: "Product Knowledge", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Sales", type: "skill"}, {name: "Tech-Savvy", type: "skill"} ], "Adult Store Clerk": [ {name: "Product Knowledge", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Sales", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Perceptive", type: "mental"}, {name: "Charming", type: "mental"}, {name: "Chill", type: "mental"}, {name: "Curious", type: "mental"}, {name: "Flirty", type: "mental"}, {name: "Nonchalant", type: "mental"}, {name: "Sly", type: "mental"} ], "Ecentric Shop Worker": [ {name: "Product Knowledge", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Sales", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Perceptive", type: "mental"}, {name: "Goth", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Introverted", type: "mental"} ], "Baker": [ {name: "Baking", type: "skill"}, {name: "Cooking", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Hardworking", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Organized", type: "mental"}, {name: "Detail-Oriented", type: "mental"} ], "Fitness Shop Clerk": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Sales", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Retail", type: "skill"}, {name: "Product Knowledge", type: "skill"}, {name: "Friendly", type: "mental"}, {name: "Energetic", type: "mental"} ], "Beauty Salon Stylist": [ {name: "Hair Styling", type: "skill"}, {name: "Makeup", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Creative", type: "mental"}, {name: "Perceptive", type: "mental"}, {name: "Friendly", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Customer Service", type: "skill"} ], "Barista": [ {name: "Customer Service", type: "skill"}, {name: "Friendly", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Energetic", type: "mental"}, {name: "Charming", type: "mental"}, {name: "Cooking", type: "skill"}, {name: "Organized", type: "mental"}, {name: "Warm", type: "mental"} ], "Package Courier": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Energetic", type: "mental"}, {name: "Hardworking", type: "mental"}, {name: "Resourceful", type: "mental"}, {name: "Focused", type: "mental"} ], "Construction Worker": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Strong", type: "physical"}, {name: "Sturdy", type: "physical"}, {name: "Hardworking", type: "mental"}, {name: "Heavy Lifting", type: "skill"} ], "Security Guard": [ {name: "Disciplined", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Wise", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Sturdy", type: "physical"}, {name: "Broad-shouldered", type: "physical"} ], "Maid": [ {name: "Organized", type: "mental"}, {name: "Hardworking", type: "mental"}, {name: "Detail-Oriented", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Maid", type: "skill"}, {name: "Cleaning", type: "skill"} ], "Bouncer": [ {name: "Broad-shouldered", type: "physical"}, {name: "Strong", type: "physical"}, {name: "Confident", type: "mental"}, {name: "Disciplined", type: "mental"}, {name: "Direct", type: "mental"}, {name: "Athletic Build", type: "physical"} ], "Clinic Assistant": [ {name: "Intelligent", type: "mental"}, {name: "Analytical", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Kind", type: "mental"}, {name: "Perceptive", type: "mental"}, {name: "Detail-Oriented", type: "mental"} ], "Data Analyst": [ {name: "Intelligent", type: "mental"}, {name: "Analytical", type: "mental"}, {name: "Deep Thinker", type: "mental"}, {name: "Focused", type: "mental"}, {name: "Tech-Savvy", type: "skill"}, {name: "Organized", type: "mental"} ], "Enforcer": [ {name: "Broad-shouldered", type: "physical"}, {name: "Strong", type: "physical"}, {name: "Aggressive", type: "mental"}, {name: "Direct", type: "mental"}, {name: "Shrewd", type: "mental"}, {name: "Cruel", type: "mental"} ], "Police Station Janitor": [ {name: "Hardworking", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Organized", type: "mental"}, {name: "Cleaning", type: "skill"}, {name: "Wise", type: "mental"}, {name: "Humble", type: "mental"} ], "Police Station Receptionist": [ {name: "Customer Service", type: "skill"}, {name: "Organized", type: "mental"}, {name: "Friendly", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Perceptive", type: "mental"}, {name: "Efficient", type: "mental"} ], "Bus Driver": [ {name: "Patient", type: "mental"}, {name: "Calm", type: "mental"}, {name: "Kind", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Flirty", type: "mental"}, {name: "Driving", type: "skill"}, {name: "Navigation", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Mechanical Repair", type: "skill"}, {name: "Observant", type: "skill"} ], "Donuts Deliverer": [ {name: "Quick", type: "physical"}, {name: "Energetic", type: "mental"}, {name: "Driving", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Hardworking", type: "mental"}, {name: "Fit", type: "physical"} ], "Cocktail Waitress": [ {name: "Charming", type: "mental"}, {name: "Graceful", type: "physical"}, {name: "Serving", type: "skill"}, {name: "Customer Service", type: "skill"}, {name: "Flirty", type: "mental"}, {name: "Persuasion", type: "skill"}, {name: "Quick", type: "physical"} ], "Fitness Trainer": [ {name: "Athletic Build", type: "physical"}, {name: "Fit", type: "physical"}, {name: "Energetic", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Coaching", type: "skill"}, {name: "Hardworking", type: "mental"}, {name: "Strong", type: "physical"}, {name: "Muscular", type: "physical"}, {name: "Kind", type: "mental"}, {name: "Dominant", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Humorous", type: "mental"}, {name: "Competitive", type: "mental"}, {name: "Flirty", type: "mental"}, {name: "Aggressive", type: "mental"}, {name: "Athletics", type: "skill"}, {name: "Combat", type: "skill"} ], "Street Performer": [ {name: "Performer", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Entertainer", type: "skill"}, {name: "Outgoing", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Showmanship", type: "skill"} ], "Musician": [ {name: "Musical", type: "skill"}, {name: "Performer", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Showmanship", type: "skill"}, {name: "Charming", type: "mental"} ], "Dancing Instructor": [ {name: "Graceful", type: "physical"}, {name: "Flexible", type: "physical"}, {name: "Dancing", type: "skill"}, {name: "Patient", type: "mental"}, {name: "Artistic", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Charming", type: "mental"} ], "Social Media Influencer": [ {name: "Social Media", type: "skill"}, {name: "Photography", type: "skill"}, {name: "Creative", type: "mental"}, {name: "Trendy", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Charming", type: "mental"} ], "Black Market Dealer": [ {name: "Streetwise", type: "skill"}, {name: "Persuasion", type: "skill"}, {name: "Analytical", type: "mental"}, {name: "Sly", type: "mental"}, {name: "Shrewd", type: "mental"}, {name: "Risk-Taker", type: "skill"} ], "Negotiator": [ {name: "Persuasion", type: "skill"}, {name: "Analytical", type: "mental"}, {name: "Diplomatic", type: "mental"}, {name: "Confident", type: "mental"}, {name: "Patient", type: "mental"}, {name: "Observant", type: "skill"}, {name: "Shrewd", type: "mental"} ], "Model": [ {name: "Modeling", type: "skill"}, {name: "Fashionable", type: "physical"}, {name: "Graceful", type: "physical"}, {name: "Photogenic", type: "skill"}, {name: "Confident", type: "mental"}, {name: "Poised", type: "skill"}, {name: "Striking", type: "skill"} ], "Porn Star": [ {name: "Sexually Skilled", type: "skill"}, {name: "Exhibitionist", type: "skill"}, {name: "Confident", type: "mental"}, {name: "Seductive", type: "mental"}, {name: "Acting", type: "skill"}, {name: "Charming", type: "mental"} ] }>> <<set _traitHoursMax = 40 - setup.skillTree.getEffect("traitHoursReduction")>> <<set _hoursUntilNextTrait = _traitHoursMax - $hourlyJobHoursWorked>> <<if _hoursUntilNextTrait < 0>> <<set _hoursUntilNextTrait = 0>> <</if>> <<set _currentJobPool = _jobTraitPoolsForProgress[$lastWorkJob]>> <<set _traitsObtained = 0>> <<set _totalJobTraits = 0>> <<if _currentJobPool>> <<set _totalJobTraits = _currentJobPool.length>> <<for _t range _currentJobPool>> /* Count by whether the player actually has the trait in ANY array, not by the pool's declared type. Some traits (e.g. Observant) are typed inconsistently across pools and can live in a different array than declared, which made a held trait read as not-obtained. Using setup.playerHasTrait matches the award logic and avoids that. */ <<if setup.playerHasTrait(_t.name)>> <<set _traitsObtained++>> <</if>> <</for>> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #17a2b8; margin-top: 0; font-size: 24px; border-bottom: 3px solid #17a2b8; padding-bottom: 10px;">📊 Trait Progress</h2> <!-- Hours until next trait --> <div style="background: #1a2a3a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #3498db;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> <span style="color: #ccc; font-size: 16px;">⏱️ Hours until next trait:</span> <span style="color: #3498db; font-size: 18px; font-weight: bold;"><<print _hoursUntilNextTrait>> hours</span> </div> <<set _progressPercent = Math.round(($hourlyJobHoursWorked / _traitHoursMax) * 100)>> <<if _progressPercent > 100>><<set _progressPercent = 100>><</if>> <div style="background: #000000; border: 2px solid #3498db; border-radius: 10px; height: 25px; position: relative; overflow: hidden; box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);"> <div @style="'background: linear-gradient(90deg, #3498db 0%, #2980b9 100%); height: 100%; width: ' + _progressPercent + '%; transition: width 0.3s ease; position: absolute; left: 0; top: 0;'"></div> <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-weight: bold; font-size: 12px; text-shadow: 1px 1px 2px rgba(0,0,0,0.8); z-index: 10;"> <<print $hourlyJobHoursWorked>> / <<print _traitHoursMax>> hours worked </div> </div> </div> <!-- Traits from current job --> <<if _currentJobPool>> <div style="background: #1a3a2a; padding: 15px; border-radius: 8px; border: 2px solid #28a745;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> <span style="color: #ccc; font-size: 16px;">🎯 <<print $lastWorkJob>> traits obtained:</span> <span style="color: #28a745; font-size: 18px; font-weight: bold;"><<print _traitsObtained>> / <<print _totalJobTraits>></span> </div> <<set _traitProgressPercent = _totalJobTraits > 0 ? Math.round((_traitsObtained / _totalJobTraits) * 100) : 0>> <<if _traitProgressPercent > 100>><<set _traitProgressPercent = 100>><</if>> <div style="background: #000000; border: 2px solid #28a745; border-radius: 10px; height: 25px; position: relative; overflow: hidden; box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);"> <div @style="'background: linear-gradient(90deg, #28a745 0%, #20c997 100%); height: 100%; width: ' + _traitProgressPercent + '%; transition: width 0.3s ease; position: absolute; left: 0; top: 0;'"></div> <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-weight: bold; font-size: 12px; text-shadow: 1px 1px 2px rgba(0,0,0,0.8); z-index: 10;"> <<print _traitsObtained>> / <<print _totalJobTraits>> traits (<<print _traitProgressPercent>>%) </div> </div> <<if _traitsObtained >= _totalJobTraits>> <p style="color: #ffd43b; font-size: 14px; margin: 10px 0 0 0; text-align: center; font-weight: bold;">✨ You've mastered all traits from this job!</p> <</if>> </div> <<else>> <div style="background: #3a3a2a; padding: 15px; border-radius: 8px; border: 2px solid #f39c12;"> <p style="color: #f39c12; font-size: 14px; margin: 0; text-align: center;">This job doesn't have a trait pool.</p> </div> <</if>> </div> <!-- Continue Button (always shown for self-handled payment or conflict) --> <<if $lastWorkPaymentHandled || _hasConflict>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Continue</div>">> <<set $lastWorkTraitChanges = []>> <<set $lastWorkProcessed = false>> <<set $lastWorkPaymentHandled = false>> <<goto $lastLocation || "Downtown">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("StudioBathroom")>> <<run $visitedLocations.push("StudioBathroom")>> <</if>> <<set $lastLocation = "StudioBathroom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">🚿 Bathroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0;"> A small but functional bathroom. White tiles line the walls, and everything is kept reasonably clean. The mirror above the sink reflects your image back at you. </p> </div> <h2 style="color: #3498db;">Bathroom Features</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Shower --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Shower</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A basic shower with hot water. Clean yourself up.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Shower</div>">> <<set $bathroomMode = "shower">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Toilet --> <div style="border: 3px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #95a5a6; margin: 0 0 10px 0;">🚽 Toilet</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A standard toilet. Nothing special.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Mirror --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🪞 Mirror</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Look at yourself and check your appearance.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Look in Mirror</div>">> <<set $mirrorReturnLocation = "StudioBathroom">> <<goto "MirrorView">> <</link>> </div> <!-- Storage Cabinet --> <div style="border: 3px solid #8e44ad; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8e44ad; margin: 0 0 10px 0;">🗄️ Storage Cabinet</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A small cabinet for storing bathroom items and supplies.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Main Room</div>">> <<goto "StudioApartment">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="max-width: 600px; margin: 0 auto; padding: 20px;"> <div style="background: #2a2a2a; padding: 30px; border-radius: 15px; border: 3px solid #51cf66; text-align: center;"> <h1 style="color: #51cf66; margin-top: 0;">Confirm Home Purchase</h1> <p style="color: #ccc; font-size: 18px; margin-bottom: 20px;">Are you sure you want to purchase this home?</p> <p style="color: #ffc107; font-size: 28px; font-weight: bold; margin-bottom: 10px;"> Price: <<print setup.formatMoney($pendingHomePurchase.price)>> </p> <p style="color: #51cf66; font-size: 16px; margin-bottom: 30px;"> No rent required - this home is yours forever! </p> <p style="color: #aaa; margin-bottom: 30px;"> Your current balance: <<print setup.formatMoney($money)>> </p> <div style="display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;"> <<link "<div style='background: #51cf66; color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; cursor: pointer;'>Confirm Purchase</div>">> <<set $money -= $pendingHomePurchase.price>> <<set $ownsHouse = true>> <<set $houseLocation = $pendingHomePurchase.location>> <<set $housePurchaseDate = $dayNumber>> <<set $homeless = false>> <<if $pendingHomePurchase.location === "ResidentialNormalHomes">><<run setup.achievements.unlock("home_normal")>><</if>> <<if $pendingHomePurchase.location === "ResidentialExpensiveHomes">><<run setup.achievements.unlock("home_expensive")>><</if>> <<if $pendingHomePurchase.location === "ResidentialMansions">><<run setup.achievements.unlock("home_mansion")>><</if>> <<set _dest = $pendingHomePurchase.destination>> <<unset $pendingHomePurchase>> <<goto _dest>> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; cursor: pointer;'>Cancel</div>">> <<set _returnTo = $pendingHomePurchase.returnTo>> <<unset $pendingHomePurchase>> <<goto _returnTo>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("PlayerSuburbanHome")>> <<run $visitedLocations.push("PlayerSuburbanHome")>> <</if>> <<set $lastLocation = "PlayerSuburbanHome">> <<set _home = "PlayerSuburbanHome">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(26, 26, 26, 0.9); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("PlayerSuburbanHome")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <!-- Home Visitor Card --> <<if $homeVisitor>> <<set _visitorNPC = setup.homeVisit.getVisitorNPC()>> <<if _visitorNPC>> <<set _visMood = setup.calculateNPCMood(_visitorNPC, false)>> <<set _visMoodDef = setup.moodDefinitions[_visMood.name] || setup.moodDefinitions.neutral>> <div style="background: linear-gradient(135deg, #2a1a2e 0%, #1a2a1e 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; box-shadow: 0 4px 12px rgba(0,0,0,0.4);"> <div style="display: flex; align-items: center; gap: 15px; margin-bottom: 15px;"> <span style="font-size: 32px;"><<if $homeVisitor.type === 'romantic'>>💕<<else>>👋<</if>></span> <div> <h3 style="color: <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; margin: 0;"><<= _visitorNPC.name>> is here</h3> <span style="color: #aaa; font-size: 14px;"><<if $homeVisitor.type === 'romantic'>>Romantic visit<<else>>Hanging out<</if>> · <span style="color: <<= _visMoodDef.color>>;"><<= _visMoodDef.icon>> <<= _visMoodDef.label>></span></span> </div> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<if !$homeVisitor.homeTalkUsed>> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>💬 Chat</div>">> <<set $homeVisitor.homeTalkUsed = true>> <<set $dailyConversations[_visitorNPC.name] = 0>> <<set $homeTalkBonus = 1.5>> <<set $homeVisitReturn = true>> <<set $tradingWithNPC = _visitorNPC>> <<goto "NPCTalk">> <</link>> <<else>> <div style="display: inline-block; background: #333; color: #666; padding: 10px 20px; border-radius: 8px; font-weight: bold;">💬 Already Chatted</div> <</if>> <<if setup.homeVisit.canHomeIntimate()>> <<link "<div style='display: inline-block; background: #e91e63; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>❤️ Get Intimate</div>">> <<set $romanceTarget = _visitorNPC.name>> <<goto "HomeIntimateSelect">> <</link>> <<elseif $homeVisitor && !$homeVisitor.homeIntimateUsed>> <<set _intimateHint = setup.homeVisit.getIntimateHint()>> <<if _intimateHint>> <div style="display: inline-block; background: #2a1a2a; color: #c9a9ff; padding: 8px 16px; border-radius: 8px; font-size: 13px; font-style: italic; border: 1px dashed #6e4ea8;">💔 <<= _intimateHint>></div> <</if>> <</if>> <<link "<div style='display: inline-block; background: #666; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>👋 Say Goodbye</div>">> <<run setup.homeVisit.dismiss()>> <<goto _home>> <</link>> </div> </div> <</if>> <</if>> <h2 style="color: #51cf66;">Main Floor</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Master Bedroom --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🛏️ Master Bedroom</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A spacious bedroom with a king-size bed and walk-in closet.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bedroom</div>">> <<run advanceTime(1)>> <<goto "PlayerSuburbanBedroom">> <</link>> </div> <!-- Living Room --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🛋️ Living Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A comfortable living area with plush couches and entertainment space.</p> <<if $hasTV>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Watch TV</div>">> <<goto "WatchTV">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic; margin-top: 10px;'>No TV</div> <</if>> </div> <!-- Kitchen --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🍳 Kitchen</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A full-size kitchen with modern appliances, granite countertops, and plenty of cabinet space.</p> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Cook Something</div>">> <<run advanceTime(1)>> <<goto "HomeKitchen">> <</link>> </div> <!-- Laptop/Office Area --> <<if $hasLaptop>> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💻 Home Office</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A dedicated workspace with your laptop setup.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Laptop</div>">> <<set $laptopReturnLocation = "PlayerSuburbanHome">> <<goto "UseLaptop">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">💻 Home Office</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An empty desk awaits a laptop or computer.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic; margin-top: 10px;'>No Laptop</div> </div> <</if>> <!-- Milk Bottling (Hucow/Lactating only) --> <<if ($physicalTraits && ($physicalTraits.includes("Hucow") || $physicalTraits.includes("Lactating")))>> <div style="border: 3px solid #f8bbd0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f8bbd0; margin: 0 0 10px 0;">🥛 Milk Bottling</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Express and bottle milk for gifting.</p> <<link "<div style='background: #f8bbd0; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Bottle Milk</div>">> <<goto "MilkBottling">> <</link>> </div> <</if>> </div> <h2 style="color: #51cf66;">Other Rooms</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Master Bathroom --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Master Bathroom</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A luxurious bathroom with walk-in shower, bathtub, and double vanity.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bathroom</div>">> <<run advanceTime(1)>> <<goto "PlayerSuburbanBathroom">> <</link>> </div> <!-- Small Custom Room 1 --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _room1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[0]>> <<if _room1>> <<set _roomData = setup.roomRenovations.small.find(function(r) { return r.id === _room1; })>> <h3 style="color: <<print _roomData.color>>; margin: 0 0 10px 0;"><<print _roomData.icon>> <<print _roomData.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _roomData.description>></p> <<link "<div style='background: <<print _roomData.color>>; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter <<print _roomData.name>></div>">> <<set $renovateReturnPassage = "PlayerSuburbanHome">> <<goto _roomData.passage>> <</link>> <<else>> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Medium Custom Room 1 --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _medRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].medium && $homeRenovations[_home].medium[0]>> <<if _medRoom1>> <<set _medRoomData = setup.roomRenovations.medium.find(function(r) { return r.id === _medRoom1; })>> <h3 style="color: <<print _medRoomData.color>>; margin: 0 0 10px 0;"><<print _medRoomData.icon>> <<print _medRoomData.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _medRoomData.description>></p> <<link `"<div style='background: " + _medRoomData.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _medRoomData.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerSuburbanHome">> <<goto _medRoomData.passage>> <</link>> <<else>> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🚪 Medium Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A versatile room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Garage --> <div style="border: 3px solid #7f8c8d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #7f8c8d; margin: 0 0 10px 0;">🚗 Garage</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A two-car garage with storage space.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Backyard --> <div style="border: 3px solid #27ae60; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #27ae60; margin: 0 0 10px 0;">🌴 Backyard</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A fenced tropical backyard with palm trees and a patio.</p> <<link "<div style='background: #27ae60; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Outside</div>">> <<goto "PlayerBackyard">> <</link>> </div> </div> <h2 style="color: #51cf66;">Home Management</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Invite Someone Over --> <<if !$homeVisitor>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #444;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏠 Invite Someone Over</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Invite a friend or partner over</p> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>Choose Guest</div>">> <<goto "HomeInviteSelect">> <</link>> </div> <</if>> <!-- Decor Manager --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🎨 Decor Manager</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">View and manage your placed decorations.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Manage Decor</div>">> <<goto "HomeDecorManager">> <</link>> </div> <!-- Wall Color --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🖌️ Wall Paint</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Change your wall colors.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Paint Walls</div>">> <<goto "WallColorPicker">> <</link>> </div> <!-- Renovate Rooms --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🔧 Renovate Rooms</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Convert empty rooms into functional spaces.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Renovation Menu</div>">> <<set $renovateReturnPassage = "PlayerSuburbanHome">> <<goto "RoomRenovationManager">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Leave Home</div>">> <<goto "ResidentialDistrict">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("PlayerSuburbanBathroom")>> <<run $visitedLocations.push("PlayerSuburbanBathroom")>> <</if>> <<set $lastLocation = "PlayerSuburbanBathroom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">🚿 Master Bathroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0;"> A spacious master bathroom with marble countertops and modern fixtures. The walk-in shower has rainfall and handheld showerheads, while a deep soaking tub sits beneath a frosted window. Double vanities provide plenty of space for getting ready. </p> </div> <h2 style="color: #3498db;">Bathroom Features</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Walk-in Shower --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Walk-in Shower</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A luxurious glass-enclosed shower with dual showerheads.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Shower</div>">> <<set $bathroomMode = "shower">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Bathtub --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛁 Bathtub</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A deep freestanding bathtub perfect for relaxation.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Bathtub</div>">> <<set $bathroomMode = "bath">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Toilet --> <div style="border: 3px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #95a5a6; margin: 0 0 10px 0;">🚽 Toilet</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A modern toilet in a private water closet.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Mirror/Vanity --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🪞 Vanity Mirror</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A large backlit mirror above the double vanity.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Look in Mirror</div>">> <<set $mirrorReturnLocation = "PlayerSuburbanBathroom">> <<goto "MirrorView">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Main House</div>">> <<goto "PlayerSuburbanHome">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("PlayerExpensiveHome")>> <<run $visitedLocations.push("PlayerExpensiveHome")>> <</if>> <<set $lastLocation = "PlayerExpensiveHome">> <<set _home = "PlayerExpensiveHome">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(26, 26, 26, 0.9); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("PlayerExpensiveHome")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <!-- Home Visitor Card --> <<if $homeVisitor>> <<set _visitorNPC = setup.homeVisit.getVisitorNPC()>> <<if _visitorNPC>> <<set _visMood = setup.calculateNPCMood(_visitorNPC, false)>> <<set _visMoodDef = setup.moodDefinitions[_visMood.name] || setup.moodDefinitions.neutral>> <div style="background: linear-gradient(135deg, #2a1a2e 0%, #1a2a1e 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; box-shadow: 0 4px 12px rgba(0,0,0,0.4);"> <div style="display: flex; align-items: center; gap: 15px; margin-bottom: 15px;"> <span style="font-size: 32px;"><<if $homeVisitor.type === 'romantic'>>💕<<else>>👋<</if>></span> <div> <h3 style="color: <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; margin: 0;"><<= _visitorNPC.name>> is here</h3> <span style="color: #aaa; font-size: 14px;"><<if $homeVisitor.type === 'romantic'>>Romantic visit<<else>>Hanging out<</if>> · <span style="color: <<= _visMoodDef.color>>;"><<= _visMoodDef.icon>> <<= _visMoodDef.label>></span></span> </div> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<if !$homeVisitor.homeTalkUsed>> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>💬 Chat</div>">> <<set $homeVisitor.homeTalkUsed = true>> <<set $dailyConversations[_visitorNPC.name] = 0>> <<set $homeTalkBonus = 1.5>> <<set $homeVisitReturn = true>> <<set $tradingWithNPC = _visitorNPC>> <<goto "NPCTalk">> <</link>> <<else>> <div style="display: inline-block; background: #333; color: #666; padding: 10px 20px; border-radius: 8px; font-weight: bold;">💬 Already Chatted</div> <</if>> <<if setup.homeVisit.canHomeIntimate()>> <<link "<div style='display: inline-block; background: #e91e63; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>❤️ Get Intimate</div>">> <<set $romanceTarget = _visitorNPC.name>> <<goto "HomeIntimateSelect">> <</link>> <<elseif $homeVisitor && !$homeVisitor.homeIntimateUsed>> <<set _intimateHint = setup.homeVisit.getIntimateHint()>> <<if _intimateHint>> <div style="display: inline-block; background: #2a1a2a; color: #c9a9ff; padding: 8px 16px; border-radius: 8px; font-size: 13px; font-style: italic; border: 1px dashed #6e4ea8;">💔 <<= _intimateHint>></div> <</if>> <</if>> <<link "<div style='display: inline-block; background: #666; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>👋 Say Goodbye</div>">> <<run setup.homeVisit.dismiss()>> <<goto _home>> <</link>> </div> </div> <</if>> <</if>> <h2 style="color: #ffc107;">Main Floor</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Master Suite --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🛏️ Master Suite</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A stunning master suite with California king bed, walk-in closet, and private balcony.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bedroom</div>">> <<run advanceTime(1)>> <<goto "PlayerExpensiveBedroom">> <</link>> </div> <!-- Living Room --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🛋️ Living Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An expansive living room with vaulted ceilings, designer furniture, and a stunning entertainment center.</p> <<if $hasTV>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Watch TV</div>">> <<goto "WatchTV">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic; margin-top: 10px;'>No TV</div> <</if>> </div> <!-- Gourmet Kitchen --> <div style="border: 3px solid #e67e22; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e67e22; margin: 0 0 10px 0;">🍳 Gourmet Kitchen</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A chef's dream kitchen with professional-grade appliances, marble countertops, and a large island.</p> <<link "<div style='background: #e67e22; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Cook Something</div>">> <<run advanceTime(1)>> <<goto "HomeKitchen">> <</link>> </div> <!-- Home Office --> <<if $hasLaptop>> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💻 Home Office</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A private study with built-in bookshelves and panoramic windows.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Laptop</div>">> <<set $laptopReturnLocation = "PlayerExpensiveHome">> <<goto "UseLaptop">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">💻 Home Office</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A private study awaiting your equipment.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic; margin-top: 10px;'>No Laptop</div> </div> <</if>> <!-- Dining Room --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🍽️ Dining Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An elegant formal dining room with seating for twelve and a crystal chandelier.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Milk Bottling (Hucow/Lactating only) --> <<if ($physicalTraits && ($physicalTraits.includes("Hucow") || $physicalTraits.includes("Lactating")))>> <div style="border: 3px solid #f8bbd0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f8bbd0; margin: 0 0 10px 0;">🥛 Milk Bottling</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Express and bottle milk for gifting.</p> <<link "<div style='background: #f8bbd0; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Bottle Milk</div>">> <<goto "MilkBottling">> <</link>> </div> <</if>> </div> <h2 style="color: #ffc107;">Other Rooms</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Master Bathroom --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Master Bathroom</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A spa-like master bathroom with rainfall shower and jacuzzi tub.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bathroom</div>">> <<run advanceTime(1)>> <<goto "PlayerExpensiveBathroom">> <</link>> </div> <!-- Large Custom Room 1 --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _largeRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].large && $homeRenovations[_home].large[0]>> <<if _largeRoom1>> <<set _largeRoomData1 = setup.roomRenovations.large.find(function(r) { return r.id === _largeRoom1; })>> <h3 style="color: <<print _largeRoomData1.color>>; margin: 0 0 10px 0;"><<print _largeRoomData1.icon>> <<print _largeRoomData1.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _largeRoomData1.description>></p> <<link `"<div style='background: " + _largeRoomData1.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _largeRoomData1.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerExpensiveHome">> <<goto _largeRoomData1.passage>> <</link>> <<else>> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🪟 Large Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A spacious room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Pool & Spa --> <div style="border: 3px solid #00bcd4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #00bcd4; margin: 0 0 10px 0;">🏊 Pool & Spa</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A heated infinity pool with attached hot tub and waterfall feature.</p> <<link "<div style='background: #00bcd4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Pool</div>">> <<goto "PlayerBackyard">> <</link>> </div> <!-- Medium Custom Room 1 --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _medRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].medium && $homeRenovations[_home].medium[0]>> <<if _medRoom1>> <<set _medRoomData1 = setup.roomRenovations.medium.find(function(r) { return r.id === _medRoom1; })>> <h3 style="color: <<print _medRoomData1.color>>; margin: 0 0 10px 0;"><<print _medRoomData1.icon>> <<print _medRoomData1.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _medRoomData1.description>></p> <<link `"<div style='background: " + _medRoomData1.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _medRoomData1.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerExpensiveHome">> <<goto _medRoomData1.passage>> <</link>> <<else>> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🚪 Medium Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A versatile room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Medium Custom Room 2 --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _medRoom2 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].medium && $homeRenovations[_home].medium[1]>> <<if _medRoom2>> <<set _medRoomData2 = setup.roomRenovations.medium.find(function(r) { return r.id === _medRoom2; })>> <h3 style="color: <<print _medRoomData2.color>>; margin: 0 0 10px 0;"><<print _medRoomData2.icon>> <<print _medRoomData2.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _medRoomData2.description>></p> <<link `"<div style='background: " + _medRoomData2.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _medRoomData2.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerExpensiveHome">> <<goto _medRoomData2.passage>> <</link>> <<else>> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🚪 Medium Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A versatile room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Small Custom Room 1 --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _smallRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[0]>> <<if _smallRoom1>> <<set _smallRoomData1 = setup.roomRenovations.small.find(function(r) { return r.id === _smallRoom1; })>> <h3 style="color: <<print _smallRoomData1.color>>; margin: 0 0 10px 0;"><<print _smallRoomData1.icon>> <<print _smallRoomData1.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _smallRoomData1.description>></p> <<link `"<div style='background: " + _smallRoomData1.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _smallRoomData1.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerExpensiveHome">> <<goto _smallRoomData1.passage>> <</link>> <<else>> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Small Custom Room 2 --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _smallRoom2 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[1]>> <<if _smallRoom2>> <<set _smallRoomData2 = setup.roomRenovations.small.find(function(r) { return r.id === _smallRoom2; })>> <h3 style="color: <<print _smallRoomData2.color>>; margin: 0 0 10px 0;"><<print _smallRoomData2.icon>> <<print _smallRoomData2.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _smallRoomData2.description>></p> <<link `"<div style='background: " + _smallRoomData2.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _smallRoomData2.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerExpensiveHome">> <<goto _smallRoomData2.passage>> <</link>> <<else>> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- 3-Car Garage --> <div style="border: 3px solid #7f8c8d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #7f8c8d; margin: 0 0 10px 0;">🚗 3-Car Garage</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A spacious three-car garage with built-in storage and workshop area.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Backyard & Patio --> <div style="border: 3px solid #1abc9c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1abc9c; margin: 0 0 10px 0;">🌴 Backyard & Patio</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Lush tropical landscaping with outdoor kitchen, fire pit, and covered lanai.</p> <<link "<div style='background: #1abc9c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Outside</div>">> <<goto "PlayerBackyard">> <</link>> </div> </div> <h2 style="color: #ffc107;">Home Management</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Invite Someone Over --> <<if !$homeVisitor>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #444;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏠 Invite Someone Over</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Invite a friend or partner over</p> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>Choose Guest</div>">> <<goto "HomeInviteSelect">> <</link>> </div> <</if>> <!-- Decor Manager --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🎨 Decor Manager</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">View and manage your placed decorations.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Manage Decor</div>">> <<goto "HomeDecorManager">> <</link>> </div> <!-- Wall Color --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🖌️ Wall Paint</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Change your wall colors.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Paint Walls</div>">> <<goto "WallColorPicker">> <</link>> </div> <!-- Renovate Rooms --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🔧 Renovate Rooms</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Convert empty rooms into functional spaces.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Renovation Menu</div>">> <<set $renovateReturnPassage = "PlayerExpensiveHome">> <<goto "RoomRenovationManager">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Leave Home</div>">> <<goto "ResidentialDistrict">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("PlayerExpensiveBathroom")>> <<run $visitedLocations.push("PlayerExpensiveBathroom")>> <</if>> <<set $lastLocation = "PlayerExpensiveBathroom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">🚿 Master Bathroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0;"> A spa-worthy master bathroom with Italian marble floors, heated towel racks, and ambient lighting. The glass-enclosed rainfall shower and deep jacuzzi tub offer the ultimate in relaxation. Dual vanities with backlit mirrors complete this luxurious retreat. </p> </div> <h2 style="color: #3498db;">Bathroom Features</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Rainfall Shower --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Rainfall Shower</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A massive glass-enclosed shower with rainfall and body spray jets.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Shower</div>">> <<set $bathroomMode = "shower">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Jacuzzi Tub --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛁 Jacuzzi Tub</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A deep soaking tub with jets, perfect for unwinding after a long day.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Bathtub</div>">> <<set $bathroomMode = "bath">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Toilet --> <div style="border: 3px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #95a5a6; margin: 0 0 10px 0;">🚽 Toilet</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A smart toilet with heated seat and bidet in a private water closet.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Vanity Mirror --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🪞 Vanity Mirror</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Backlit dual vanity mirrors with built-in TV display.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Look in Mirror</div>">> <<set $mirrorReturnLocation = "PlayerExpensiveBathroom">> <<goto "MirrorView">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Main House</div>">> <<run advanceTime(1)>> <<goto "PlayerExpensiveHome">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PlayerModernMansion">> <<set _home = "PlayerModernMansion">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(26, 26, 26, 0.9); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("PlayerModernMansion")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <!-- Home Visitor Card --> <<if $homeVisitor>> <<set _visitorNPC = setup.homeVisit.getVisitorNPC()>> <<if _visitorNPC>> <<set _visMood = setup.calculateNPCMood(_visitorNPC, false)>> <<set _visMoodDef = setup.moodDefinitions[_visMood.name] || setup.moodDefinitions.neutral>> <div style="background: linear-gradient(135deg, #2a1a2e 0%, #1a2a1e 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; box-shadow: 0 4px 12px rgba(0,0,0,0.4);"> <div style="display: flex; align-items: center; gap: 15px; margin-bottom: 15px;"> <span style="font-size: 32px;"><<if $homeVisitor.type === 'romantic'>>💕<<else>>👋<</if>></span> <div> <h3 style="color: <<if $homeVisitor.type === 'romantic'>>#e91e63<<else>>#51cf66<</if>>; margin: 0;"><<= _visitorNPC.name>> is here</h3> <span style="color: #aaa; font-size: 14px;"><<if $homeVisitor.type === 'romantic'>>Romantic visit<<else>>Hanging out<</if>> · <span style="color: <<= _visMoodDef.color>>;"><<= _visMoodDef.icon>> <<= _visMoodDef.label>></span></span> </div> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<if !$homeVisitor.homeTalkUsed>> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>💬 Chat</div>">> <<set $homeVisitor.homeTalkUsed = true>> <<set $dailyConversations[_visitorNPC.name] = 0>> <<set $homeTalkBonus = 1.5>> <<set $homeVisitReturn = true>> <<set $tradingWithNPC = _visitorNPC>> <<goto "NPCTalk">> <</link>> <<else>> <div style="display: inline-block; background: #333; color: #666; padding: 10px 20px; border-radius: 8px; font-weight: bold;">💬 Already Chatted</div> <</if>> <<if setup.homeVisit.canHomeIntimate()>> <<link "<div style='display: inline-block; background: #e91e63; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>❤️ Get Intimate</div>">> <<set $romanceTarget = _visitorNPC.name>> <<goto "HomeIntimateSelect">> <</link>> <<elseif $homeVisitor && !$homeVisitor.homeIntimateUsed>> <<set _intimateHint = setup.homeVisit.getIntimateHint()>> <<if _intimateHint>> <div style="display: inline-block; background: #2a1a2a; color: #c9a9ff; padding: 8px 16px; border-radius: 8px; font-size: 13px; font-style: italic; border: 1px dashed #6e4ea8;">💔 <<= _intimateHint>></div> <</if>> <</if>> <<link "<div style='display: inline-block; background: #666; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer;'>👋 Say Goodbye</div>">> <<run setup.homeVisit.dismiss()>> <<goto _home>> <</link>> </div> </div> <</if>> <</if>> <h2 style="color: #fd7e14;">Main Floor</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Grand Master Suite --> <div style="border: 3px solid #9D00FF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9D00FF; margin: 0 0 10px 0;">🛏️ Grand Master Suite</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A palatial master bedroom with California king bed, walk-in closets the size of apartments, and panoramic city views.</p> <<link "<div style='background: #9D00FF; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bedroom</div>">> <<run advanceTime(1)>> <<goto "PlayerMansionBedroom">> <</link>> </div> <!-- Living Room --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🛋️ Great Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An expansive great room with 30-foot ceilings, designer furniture, and a massive entertainment system.</p> <<if $hasTV>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Watch TV</div>">> <<goto "WatchTV">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>No TV Installed</div> <</if>> </div> <!-- Gourmet Kitchen --> <div style="border: 3px solid #e67e22; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e67e22; margin: 0 0 10px 0;">👨🍳 Chef's Kitchen</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A professional-grade kitchen with two islands, imported marble, and restaurant-quality appliances.</p> <<link "<div style='background: #e67e22; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Cook Something</div>">> <<run advanceTime(1)>> <<goto "HomeKitchen">> <</link>> </div> <!-- Home Office --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">💼 Executive Office</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A corner office with floor-to-ceiling windows, built-in bookshelves, and smart glass technology.</p> <<if $hasLaptop>> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Laptop</div>">> <<set $laptopReturnLocation = "PlayerModernMansion">> <<goto "UseLaptop">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>No Laptop</div> <</if>> </div> <!-- Formal Dining --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🍽️ Formal Dining</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A grand dining room with seating for 16, crystal chandelier, and butler's pantry.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Library --> <div style="border: 3px solid #8e44ad; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8e44ad; margin: 0 0 10px 0;">📚 Library</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A two-story library with rolling ladder, rare first editions, and a cozy reading nook.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Milk Bottling (Hucow/Lactating only) --> <<if ($physicalTraits && ($physicalTraits.includes("Hucow") || $physicalTraits.includes("Lactating")))>> <div style="border: 3px solid #f8bbd0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f8bbd0; margin: 0 0 10px 0;">🥛 Milk Bottling</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Express and bottle milk for gifting.</p> <<link "<div style='background: #f8bbd0; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Bottle Milk</div>">> <<goto "MilkBottling">> <</link>> </div> <</if>> </div> <h2 style="color: #fd7e14;">Other Rooms</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Master Bathroom --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Spa Bathroom</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An opulent spa bathroom with steam shower, soaking tub, and heated floors.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bathroom</div>">> <<run advanceTime(1)>> <<goto "PlayerMansionBathroom">> <</link>> </div> <!-- Large Custom Room 1 --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _largeRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].large && $homeRenovations[_home].large[0]>> <<if _largeRoom1>> <<set _largeRoomData1 = setup.roomRenovations.large.find(function(r) { return r.id === _largeRoom1; })>> <h3 style="color: <<print _largeRoomData1.color>>; margin: 0 0 10px 0;"><<print _largeRoomData1.icon>> <<print _largeRoomData1.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _largeRoomData1.description>></p> <<link `"<div style='background: " + _largeRoomData1.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _largeRoomData1.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _largeRoomData1.passage>> <</link>> <<else>> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🪟 Large Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A spacious room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Indoor Pool --> <div style="border: 3px solid #1abc9c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1abc9c; margin: 0 0 10px 0;">🏊 Indoor Pool</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An Olympic-length indoor pool with retractable roof and adjacent hot tub.</p> <<link "<div style='background: #1abc9c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Pool</div>">> <<goto "PlayerBackyard">> <</link>> </div> <!-- Wine Cellar (always available with the Modern Mansion) --> <div style="border: 3px solid #722f37; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d4a5a5; margin: 0 0 10px 0;">🍷 Wine Cellar</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A stone walled cellar beneath the mansion lined with bottle racks. Cool, still, faintly drafty.</p> <<link "<div style='background: #722f37; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend to Cellar</div>">> <<run advanceTime(1)>> <<goto "MansionWineCellar">> <</link>> </div> <!-- Large Custom Room 2 --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _largeRoom2 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].large && $homeRenovations[_home].large[1]>> <<if _largeRoom2>> <<set _largeRoomData2 = setup.roomRenovations.large.find(function(r) { return r.id === _largeRoom2; })>> <h3 style="color: <<print _largeRoomData2.color>>; margin: 0 0 10px 0;"><<print _largeRoomData2.icon>> <<print _largeRoomData2.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _largeRoomData2.description>></p> <<link `"<div style='background: " + _largeRoomData2.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _largeRoomData2.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _largeRoomData2.passage>> <</link>> <<else>> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🪟 Large Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A spacious room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Medium Custom Room 1 --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _medRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].medium && $homeRenovations[_home].medium[0]>> <<if _medRoom1>> <<set _medRoomData1 = setup.roomRenovations.medium.find(function(r) { return r.id === _medRoom1; })>> <h3 style="color: <<print _medRoomData1.color>>; margin: 0 0 10px 0;"><<print _medRoomData1.icon>> <<print _medRoomData1.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _medRoomData1.description>></p> <<link `"<div style='background: " + _medRoomData1.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _medRoomData1.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _medRoomData1.passage>> <</link>> <<else>> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🚪 Medium Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A versatile room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Medium Custom Room 2 --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _medRoom2 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].medium && $homeRenovations[_home].medium[1]>> <<if _medRoom2>> <<set _medRoomData2 = setup.roomRenovations.medium.find(function(r) { return r.id === _medRoom2; })>> <h3 style="color: <<print _medRoomData2.color>>; margin: 0 0 10px 0;"><<print _medRoomData2.icon>> <<print _medRoomData2.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _medRoomData2.description>></p> <<link `"<div style='background: " + _medRoomData2.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _medRoomData2.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _medRoomData2.passage>> <</link>> <<else>> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🚪 Medium Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A versatile room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Medium Custom Room 3 --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _medRoom3 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].medium && $homeRenovations[_home].medium[2]>> <<if _medRoom3>> <<set _medRoomData3 = setup.roomRenovations.medium.find(function(r) { return r.id === _medRoom3; })>> <h3 style="color: <<print _medRoomData3.color>>; margin: 0 0 10px 0;"><<print _medRoomData3.icon>> <<print _medRoomData3.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _medRoomData3.description>></p> <<link `"<div style='background: " + _medRoomData3.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _medRoomData3.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _medRoomData3.passage>> <</link>> <<else>> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🚪 Medium Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A versatile room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Small Custom Room 1 --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _smallRoom1 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[0]>> <<if _smallRoom1>> <<set _smallRoomData1 = setup.roomRenovations.small.find(function(r) { return r.id === _smallRoom1; })>> <h3 style="color: <<print _smallRoomData1.color>>; margin: 0 0 10px 0;"><<print _smallRoomData1.icon>> <<print _smallRoomData1.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _smallRoomData1.description>></p> <<link `"<div style='background: " + _smallRoomData1.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _smallRoomData1.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _smallRoomData1.passage>> <</link>> <<else>> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Small Custom Room 2 --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _smallRoom2 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[1]>> <<if _smallRoom2>> <<set _smallRoomData2 = setup.roomRenovations.small.find(function(r) { return r.id === _smallRoom2; })>> <h3 style="color: <<print _smallRoomData2.color>>; margin: 0 0 10px 0;"><<print _smallRoomData2.icon>> <<print _smallRoomData2.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _smallRoomData2.description>></p> <<link `"<div style='background: " + _smallRoomData2.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _smallRoomData2.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _smallRoomData2.passage>> <</link>> <<else>> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Small Custom Room 3 --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _smallRoom3 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[2]>> <<if _smallRoom3>> <<set _smallRoomData3 = setup.roomRenovations.small.find(function(r) { return r.id === _smallRoom3; })>> <h3 style="color: <<print _smallRoomData3.color>>; margin: 0 0 10px 0;"><<print _smallRoomData3.icon>> <<print _smallRoomData3.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _smallRoomData3.description>></p> <<link `"<div style='background: " + _smallRoomData3.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _smallRoomData3.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _smallRoomData3.passage>> <</link>> <<else>> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- Small Custom Room 4 --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <<set _smallRoom4 = $homeRenovations && $homeRenovations[_home] && $homeRenovations[_home].small && $homeRenovations[_home].small[3]>> <<if _smallRoom4>> <<set _smallRoomData4 = setup.roomRenovations.small.find(function(r) { return r.id === _smallRoom4; })>> <h3 style="color: <<print _smallRoomData4.color>>; margin: 0 0 10px 0;"><<print _smallRoomData4.icon>> <<print _smallRoomData4.name>></h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"><<print _smallRoomData4.description>></p> <<link `"<div style='background: " + _smallRoomData4.color + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter " + _smallRoomData4.name + "</div>"`>> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto _smallRoomData4.passage>> <</link>> <<else>> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A cozy room ready for customization.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Not Renovated</div> <</if>> </div> <!-- 6-Car Garage --> <div style="border: 3px solid #34495e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #34495e; margin: 0 0 10px 0;">🚗 6-Car Garage</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Climate-controlled garage with car lift, workshop, and showroom lighting.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Grounds --> <div style="border: 3px solid #27ae60; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #27ae60; margin: 0 0 10px 0;">🌳 Estate Grounds</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">3 acres of manicured gardens, tennis court, outdoor kitchen, and helipad.</p> <<link "<div style='background: #27ae60; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Outside</div>">> <<goto "PlayerBackyard">> <</link>> </div> <!-- Private Aquarium --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🐠 Private Aquarium</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A magnificent floor-to-ceiling aquarium showcasing your prized fish collection.</p> <<link "<div style='background: #1e90ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>View Aquarium</div>">> <<run advanceTime(1)>> <<goto "PlayerMansionAquarium">> <</link>> </div> </div> <h2 style="color: #fd7e14;">Home Management</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Invite Someone Over --> <<if !$homeVisitor>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #444;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏠 Invite Someone Over</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Invite a friend or partner over</p> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>Choose Guest</div>">> <<goto "HomeInviteSelect">> <</link>> </div> <</if>> <!-- Decor Manager --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🎨 Decor Manager</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">View and manage your placed decorations.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Manage Decor</div>">> <<goto "HomeDecorManager">> <</link>> </div> <!-- Wall Color --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🖌️ Wall Paint</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Change your wall colors.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Paint Walls</div>">> <<goto "WallColorPicker">> <</link>> </div> <!-- Renovate Rooms --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🔧 Renovate Rooms</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Convert empty rooms into functional spaces.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Renovation Menu</div>">> <<set $renovateReturnPassage = "PlayerModernMansion">> <<goto "RoomRenovationManager">> <</link>> </div> </div> <h2 style="color: #fd7e14;">Leave</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">🚪 Leave Home</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Head out to the Residential District.</p> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave</div>">> <<goto "ResidentialDistrict">> <</link>> </div> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PlayerMansionBathroom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #fd7e14; text-align: center;">🚿 Spa Bathroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #fd7e14 0%, #e8590c 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #fd7e14;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A spa-like retreat with imported Italian marble, heated floors, and a stunning chandelier. </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Steam Shower --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🚿 Steam Shower</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A massive walk-in shower with multiple heads, body jets, and built-in steam system.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Shower</div>">> <<set $bathroomMode = "shower">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Soaking Tub --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🛁 Freestanding Tub</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A sculptural soaking tub carved from a single block of marble with city views.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Bathtub</div>">> <<set $bathroomMode = "bath">> <<goto "HomeBathroomActions">> <</link>> </div> <!-- Toilet --> <div style="border: 3px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #95a5a6; margin: 0 0 10px 0;">🚽 Private Water Closet</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A Japanese smart toilet with all the features in its own private room.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Vanity Mirror --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🪞 Lighted Vanity</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A custom vanity with Hollywood lighting, magnifying mirrors, and smart display.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Look in Mirror</div>">> <<set $mirrorReturnLocation = "PlayerMansionBathroom">> <<goto "MirrorView">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Main House</div>">> <<run advanceTime(1)>> <<goto "PlayerModernMansion">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SuburbanGuestBedroom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #9b59b6; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Suburban</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerSuburbanHome">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "SuburbanThirdBedroom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #e67e22; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Suburban</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerSuburbanHome">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "ExpensiveHomeTheater">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #e74c3c; text-align: center;">🪟 Large Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Large | Home: Expensive</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerExpensiveHome">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "ExpensiveWineCellar">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #8e44ad; text-align: center;">🚪 Medium Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Medium | Home: Expensive</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerExpensiveHome">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "ExpensiveGuestSuite1">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #27ae60; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Expensive</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerExpensiveHome">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "ExpensiveGuestSuite2">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #2ecc71; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Expensive</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerExpensiveHome">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionPrivateTheater">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #e74c3c; text-align: center;">🪟 Large Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Large | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionPrivateGym">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #e67e22; text-align: center;">🪟 Large Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Large | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionWineCellar">> <<run setup.tickOjouRefinement("wineCellar", 5)>> /* Cellar key discovery: fires once when refinement >= 60 and key not yet found */ <<set _discoverKey = false>> <<if !$ojou_hasCellarKey && $ojou_refinement >= 60>> <<set $ojou_hasCellarKey = true>> <<set _discoverKey = true>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #722f37; text-align: center;">🍷 Wine Cellar</h1> <div style="background: linear-gradient(135deg, #2a1a1a 0%, #1a0a0a 100%); padding: 20px; border-radius: 12px; border: 2px solid #722f37; margin-bottom: 20px;"> <p style="color: #d4a5a5; line-height: 1.6; margin: 0;">Rows of dark bottles line the racks. The air is cool and still. A faint draft moves through, the way it does in any underground room. Wine you bought, wine the previous owners left behind, all sleeping on their sides in the dim light.</p> </div> <<if _discoverKey>> <div style="background: #2a1a2a; padding: 25px; border-radius: 12px; border: 3px solid #c9a0dc; margin-bottom: 20px; box-shadow: 0 0 20px rgba(201,160,220,0.3);"> <h3 style="color: #c9a0dc; margin: 0 0 12px 0; text-align: center;">🗝️ A Loose Stone</h3> <p style="color: #d4a5d4; line-height: 1.7; margin: 0 0 15px 0;">Reaching behind one of the wine racks, your hand brushes a stone that gives under pressure. You work it loose. Behind it sits a small cavity, and inside the cavity rests a tarnished iron key on a length of chain. The metal is much older than the modern mansion. You pocket it without quite knowing why.</p> <p style="color: #aaa; font-style: italic; text-align: center; margin: 0;">You found a strange iron key.</p> </div> <</if>> <<if $ojou_hasCellarKey && !$ojou_descended>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 20px; background: #2a1a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🚪 A Hollow Wall</h3> <p style="color: #d4a5d4; line-height: 1.6; margin: 0 0 15px 0;">Now that you have the key, you notice a section of the back wall sounds hollow. An old iron sconce is mounted there. The key fits a tiny lock at its base.</p> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Use the key</div>">> <<run window.advanceTime(15)>> <<set $ojou_descended = true>> <<goto "BuriedWineVault">> <</link>> </div> <</if>> <<if $ojou_descended>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 15px; background: #1a0a2a; margin-bottom: 20px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>🚪 Descend to the lower floor</div>">> <<run window.advanceTime(5)>> <<goto "BuriedWineVault">> <</link>> </div> <</if>> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionGameRoom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #f1c40f; text-align: center;">🚪 Medium Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Medium | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionStaffQuarters">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #7f8c8d; text-align: center;">🚪 Medium Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Medium | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionCustomRoom1">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #95a5a6; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionCustomRoom2">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #95a5a6; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionCustomRoom3">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #95a5a6; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "MansionCustomRoom4">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #95a5a6; text-align: center;">🧱 Small Custom Room</h1> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Customizable Room</h2> <p style="color: #ccc;">This room can be customized in future updates!</p> <p style="color: #888; font-size: 14px;">Room Size: Small | Home: Mansion</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto "PlayerModernMansion">><</link>> </div> </div></div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("GroceryStore")>> <<run $visitedLocations.push("GroceryStore")>> <</if>> <<set $lastLocation = "GroceryStore">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">🛒 Fresh Catch Grocery</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/GroceryStore.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Grocery Store"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1e4a2d 0%, #143d1f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 18px; margin: 0;"> The main grocery store serving Sunfish City. Fluorescent lights illuminate aisles of fresh produce, packaged goods, and everyday essentials. Shopping carts rattle across the polished floors as customers browse the selections. </p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #28a745; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <!-- Category Cards --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Ingredients --> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: transform 0.2s;' onmouseover='this.style.transform="translateY(-5px)"' onmouseout='this.style.transform="translateY(0)"'><h2 style='color: #51cf66; margin: 0 0 10px 0; text-align: center;'>🥬 Ingredients</h2><p style='color: rgba(255,255,255,0.8); margin: 0; text-align: center; font-size: 14px;'>Fresh produce, meat, dairy, and pantry staples</p></div>">> <<goto "GroceryStoreIngredients">> <</link>> <!-- Garden Seeds (only for homeowners) --> <<if $ownsHouse>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: transform 0.2s;' onmouseover='this.style.transform="translateY(-5px)"' onmouseout='this.style.transform="translateY(0)"'><h2 style='color: #2ecc71; margin: 0 0 10px 0; text-align: center;'>🌱 Garden Seeds & Seedlings</h2><p style='color: rgba(255,255,255,0.8); margin: 0; text-align: center; font-size: 14px;'>Seeds, tropical crops, and fruit tree saplings</p></div>">> <<goto "GroceryStoreSeeds">> <</link>> <</if>> <!-- Cafe Supplies (only if player owns cafe) --> <<if $cafeOwnership and $cafeOwnership.owned>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: transform 0.2s;' onmouseover='this.style.transform="translateY(-5px)"' onmouseout='this.style.transform="translateY(0)"'><h2 style='color: #ffd700; margin: 0 0 10px 0; text-align: center;'>🫕 Cafe Supplies</h2><p style='color: rgba(255,255,255,0.8); margin: 0; text-align: center; font-size: 14px;'>Retail cafe ingredients for your shop</p></div>">> <<goto "GroceryStoreCafeSupplies">> <</link>> <</if>> <!-- Cleaning Supplies (Coming Soon) --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h2 style="color: #17a2b8; margin: 0 0 10px 0; text-align: center;">🧹 Cleaning Supplies</h2> <p style="color: #ffa500; margin: 0; text-align: center; font-size: 14px;">🚧 Coming Soon</p> </div> <!-- Personal Care (Coming Soon) --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6;"> <h2 style="color: #e91e63; margin: 0 0 10px 0; text-align: center;">🧴 Personal Care</h2> <p style="color: #ffa500; margin: 0; text-align: center; font-size: 14px;">🚧 Coming Soon</p> </div> <!-- Household Items --> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #9c27b0; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: transform 0.2s;' onmouseover='this.style.transform="translateY(-5px)"' onmouseout='this.style.transform="translateY(0)"'><h2 style='color: #9c27b0; margin: 0 0 10px 0; text-align: center;'>🏠 Household Items</h2><p style='color: rgba(255,255,255,0.8); margin: 0; text-align: center; font-size: 14px;'>Containers, storage, snacks, and supplies</p></div>">> <<goto "GroceryStoreHousehold">> <</link>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("GroceryStore")>> <h2 style="color: #28a745;">🛒 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 10px 0;"><<print _npc.name>></h3> <p style="font-size: 14px; color: #6fbf7f; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to <<print _npc.name>></div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one else is shopping right now. </p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #20c997; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Leave Store</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <<set $lastLocation = "HomeKitchen">> <div style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(26, 26, 26, 0.9); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("HomeKitchen")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h2 style="color: #ffc107;">🍳 Kitchen</h2> <!-- Pantry Contents --> <div style="border: 3px solid #51cf66; border-radius: 10px; background: #2a2a2a; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">📦 Pantry Contents</h3> <<set _hasIngredients = false>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _ingId, _qty range $kitchenInventory.ingredients>> <<if _qty > 0>> <<set _hasIngredients = true>> <<set _ingData = setup.ingredients[_ingId]>> <span style="display: inline-block; background: #1a1a1a; padding: 8px 12px; border-radius: 5px; color: #ccc;"> <<print _ingData.name>>: <<print _qty>> </span> <</if>> <</for>> </div> <<if !_hasIngredients>> <p style="color: #888; margin: 0;">Your pantry is empty. Visit the grocery store to stock up!</p> <</if>> <<if $physicalTraits && $physicalTraits.includes("Hucow")>> <div style="margin-top: 15px; padding: 10px; background: linear-gradient(135deg, #ff69b4 0%, #ff1493 100%); border-radius: 8px;"> <span style="color: white; font-weight: bold;">🐄 Hucow Bonus: Unlimited Milk for all recipes!</span> </div> <</if>> </div> <!-- Recipes --> <h3 style="color: #51cf66;">🍳 Recipes</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<set _hasCookingSkill = $skills && $skills.includes("Cooking")>> <<for _recipeId, _recipe range setup.recipes>> <<set _canCook = setup.canCookRecipe(_recipeId)>> <<set _needsCookingSkill = _recipe.requiresCooking && !_hasCookingSkill>> <<set _isAvailable = _canCook && !_needsCookingSkill>> <div style="border: 3px solid <<if _isAvailable>>#51cf66<<elseif _needsCookingSkill>>#ffc107<<else>>#666<</if>>; border-radius: 10px; background: #2a2a2a; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h4 style="color: <<if _isAvailable>>#51cf66<<elseif _needsCookingSkill>>#ffc107<<else>>#888<</if>>; margin: 0 0 10px 0;"> <<print _recipe.name>> <<if _recipe.requiresCooking>><span style="font-size: 12px; color: #ffc107;"> (Advanced)</span><</if>> </h4> <p style="color: #ccc; margin: 0 0 10px 0; font-weight: bold;">Ingredients:</p> <<set _hasHucow = $physicalTraits && $physicalTraits.includes("Hucow")>> <ul style="margin: 0 0 10px 0; padding-left: 20px;"> <<for _ingId, _needed range _recipe.ingredients>> <<set _ingData = setup.ingredients[_ingId]>> <<set _have = $kitchenInventory.ingredients[_ingId] || 0>> <<if _ingId === "milk" && _hasHucow>> <li style="color: #ff69b4;"> <<print _ingData.name>>: 🐄 Hucow (Unlimited) </li> <<else>> <li style="color: <<if _have >= _needed>>#51cf66<<else>>#ff6b6b<</if>>;"> <<print _ingData.name>>: <<print _have>> / <<print _needed>> </li> <</if>> <</for>> </ul> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">⏱️ Time: <<print _recipe.time>> minutes</p> <p style="color: #1e90ff; font-size: 14px; margin: 0 0 5px 0;">✨ Random buff for <<print Math.floor(_recipe.buffDuration / 60)>> hours</p> <p style="color: #888; font-size: 12px; margin: 0 0 15px 0;"> <<if _recipe.ingredientCost < 10>>Strength: +5-10% <<elseif _recipe.ingredientCost < 25>>Strength: +10-15% <<else>>Strength: +15-25% <</if>> </p> <<if _needsCookingSkill>> <div style="background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;">Requires Cooking Skill</div> <<elseif _canCook>> <<capture _recipeId, _recipe>> <<set _cookButtonText = "🍳 Cook " + _recipe.name>> <<link `"<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>" + _cookButtonText + "</div>"`>> <<run setup.consumeIngredients(_recipeId)>> <<set $lastCookedMeal = _recipe.name>> <<set $lastCookedRecipeId = _recipeId>> <<set $salamanderCooked = false>> <<run advanceTime(_recipe.time)>> <<goto "CookingComplete">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center;">Missing ingredients</div> <</if>> </div> <</for>> <!-- Brick Special Recipe --> <<set _hasShizu = false>> <<set _shizuIdx = -1>> <<if $fishInventory>> <<for _fi = 0; _fi < $fishInventory.length; _fi++>> <<if $fishInventory[_fi].id === "shizufish" && !_hasShizu>> <<set _hasShizu = true>> <<set _shizuIdx = _fi>> <</if>> <</for>> <</if>> <<if _hasShizu>> <div style="border: 3px solid #ffd700; border-radius: 10px; background: linear-gradient(135deg, #2a2a1a 0%, #3a3020 100%); padding: 20px; box-shadow: 0 4px 12px rgba(255,215,0,0.2);"> <h4 style="color: #ffd700; margin: 0 0 10px 0;">🧱 Brick <span style="font-size: 12px; color: #ff6b6b;">(Secret Recipe)</span></h4> <p style="color: #ccc; margin: 0 0 10px 0;">The legendary Shizufish is so dense it can be compressed into a solid brick. Somehow edible.</p> <p style="color: #ccc; margin: 0 0 5px 0; font-weight: bold;">Ingredients:</p> <ul style="margin: 0 0 10px 0; padding-left: 20px;"> <li style="color: #51cf66;">Shizufish: 1 / 1</li> </ul> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">⏱️ Time: 30 minutes</p> <p style="color: #ffd700; font-size: 14px; margin: 0 0 15px 0;">🧱 Grants Shizu for 12 hours</p> <<capture _shizuIdx>> <<link "<div style='background: linear-gradient(90deg, #ffd700, #ff8c00); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🧱 Cook Brick</div>">> <<run $fishInventory.splice(_shizuIdx, 1)>> <<if !$foodInventory>><<set $foodInventory = []>><</if>> <<run $foodInventory.push({name: "Brick", buffId: "shizu_brick", buffDuration: 720, cookedTime: $timeInMinutes || 0})>> <<run advanceTime(30)>> <<goto "HomeKitchen">> <</link>> <</capture>> </div> <</if>> </div> <!-- Quick Actions --> <div style="border: 3px solid #1e90ff; border-radius: 10px; background: #2a2a2a; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 15px 0;">Quick Actions</h3> <<link "<span style='color: #1e90ff; cursor: pointer;'>🥤 Get a glass of water</span>">> <<run advanceTime(2)>> <<run setup.addBuff("vending_refresh", 240)>> <<replace "#water-result">> <p style="color: #51cf66; margin: 10px 0;">You drink a refreshing glass of water. Feeling hydrated! 💧 Refreshed buff gained.</p> <</replace>> <</link>> <span id="water-result"></span> <<if setup.hasDecorItem("espresso_machine")>> <br><br> <<link "<span style='color: #8b4513; cursor: pointer;'>☕ Make an espresso</span>">> <<run advanceTime(5)>> <<run setup.addBuff("vending_focus", 360)>> <<replace "#coffee-result">> <p style="color: #8b4513; margin: 10px 0;">The rich aroma fills the kitchen as you enjoy your espresso. ☕ Focused buff gained.</p> <</replace>> <</link>> <span id="coffee-result"></span> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Return to Home</div>">> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "CookingComplete">> <<set _recipe = setup.recipes[$lastCookedRecipeId]>> <<set _buffDef = setup.foodBuffs[_recipe.buffId]>> <!-- Add food to inventory --> <<if !$foodInventory>><<set $foodInventory = []>><</if>> <<run $foodInventory.push({ recipeId: $lastCookedRecipeId, name: _recipe.name, buffId: _recipe.buffId, buffDuration: _recipe.buffDuration, cookedTime: $timeInMinutes })>> <!-- Achievement tracking --> <<if !$cookedRecipesList>><<set $cookedRecipesList = []>><</if>> <<if !$cookedRecipesList.includes($lastCookedRecipeId)>> <<run $cookedRecipesList.push($lastCookedRecipeId)>> <</if>> <<run setup.achievements.unlock("first_cook")>> <<if $cookedRecipesList.length >= Object.keys(setup.recipes).length>> <<run setup.achievements.unlock("master_chef")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="border: 3px solid #51cf66; border-radius: 15px; background: #2a2a2a; padding: 40px; max-width: 500px; text-align: center;"> <h2 style="color: #51cf66; margin: 0 0 20px 0;">🍽️ Meal Ready!</h2> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 20px 0;"> The delicious aroma of your <<print $lastCookedMeal>> fills the kitchen. Your meal has been added to your food inventory! </p> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="font-size: 28px; margin: 0 0 10px 0;"><<print _buffDef.icon>></p> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0 0 5px 0;"><<print _buffDef.name>></p> <p style="color: #888; font-size: 14px; margin: 0 0 10px 0;"><<print _buffDef.description>></p> <p style="color: #1e90ff; font-size: 16px; margin: 0;"> Duration: <<print Math.floor(_recipe.buffDuration / 60)>> hours </p> </div> <p style="color: #888; font-size: 14px; margin: 0 0 25px 0;"> Eat this meal from your inventory to gain its buff! </p> <<link "<div style='background: #51cf66; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>Continue</div>">> <<goto "HomeKitchen">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$foodInventory || $eatFoodIndex === undefined || $eatFoodIndex < 0 || $eatFoodIndex >= $foodInventory.length>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="border: 3px solid #ff6b6b; border-radius: 15px; background: #2a2a2a; padding: 40px; max-width: 400px; text-align: center;"> <h2 style="color: #ff6b6b;">Error</h2> <p style="color: #ccc;">No food selected.</p> <<link "<div style='background: #ff6b6b; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>Back</div>">> <<set $inventoryTab = "food">> <<goto "Inventory">> <</link>> </div> </div> <<elseif $physicalTraits.includes("Automaton")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="border: 3px solid #888; border-radius: 15px; background: #2a2a2a; padding: 40px; max-width: 400px; text-align: center;"> <h2 style="color: #888;">✗ Cannot Consume Food</h2> <p style="color: #ccc;">Your mechanical body has no digestive system. Food cannot be consumed.</p> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>Back</div>">> <<set $inventoryTab = "food">> <<goto "Inventory">> <</link>> </div> </div> <<else>> <<set _food = $foodInventory[$eatFoodIndex]>> <<set _buffDef = setup.foodBuffs[_food.buffId]>> <!-- Apply the food buff --> <<run setup.addBuff(_food.buffId, _food.buffDuration, 1)>> <!-- Eating restores some mining energy too --> <<run setup.mining && setup.mining.foodEnergyBoost && setup.mining.foodEnergyBoost(_food)>> <!-- Remove food from inventory --> <<run $foodInventory.splice($eatFoodIndex, 1)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="border: 3px solid #51cf66; border-radius: 15px; background: #2a2a2a; padding: 40px; max-width: 500px; text-align: center;"> <h2 style="color: #51cf66; margin: 0 0 20px 0;">🍴 Delicious!</h2> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 20px 0;"> You enjoyed your <<print _food.name>>. It was perfectly prepared! </p> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="font-size: 28px; margin: 0 0 10px 0;"><<print _buffDef ? _buffDef.icon : "🍽️">></p> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0 0 5px 0;"><<print _buffDef ? _buffDef.name : "Food Buff">></p> <p style="color: #888; font-size: 14px; margin: 0 0 10px 0;"><<print _buffDef ? _buffDef.description : "">></p> <p style="color: #1e90ff; font-size: 16px; margin: 0;"> Active for <<print Math.floor(_food.buffDuration / 60)>> hours </p> </div> <p style="color: #888; font-size: 14px; margin: 0 0 25px 0;"> Your buff is now active! </p> <<link "<div style='background: #51cf66; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>Continue</div>">> <<set $inventoryTab = "food">> <<goto "Inventory">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>><<set _prevBath = previous()>><<if ["StudioBathroom","PlayerSuburbanBathroom","PlayerExpensiveBathroom","PlayerMansionBathroom"].includes(_prevBath)>><<set $currentBathroom = _prevBath>><</if>> <<set _home = setup.getCurrentHome()>> <<set _bathHomeMap = {StudioBathroom:"StudioApartment",PlayerSuburbanBathroom:"PlayerSuburbanHome",PlayerExpensiveBathroom:"PlayerExpensiveHome",PlayerMansionBathroom:"PlayerModernMansion"}>> <<if $currentBathroom && _bathHomeMap[$currentBathroom]>><<set _home = _bathHomeMap[$currentBathroom]>><</if>> <<set _wallColor = ($homeDecor[_home] && $homeDecor[_home].wallColor) || "#2a2a2a">> <<set _hasLuxury = setup.hasLuxuryBathroom(_home)>> <<set _hasImprovedShower = $homeUpgrades.improvedShower>> <<set _hasWaterHeater = $homeUpgrades.waterHeater>> <<set _hasSpaKit = setup.hasDecorItem("spa_kit", _home)>> <<set $lastLocation = "HomeBathroomActions">> <div style="background: <<print _wallColor>>33; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #1e90ff; text-align: center;">🚿 Bathroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #0d6efd 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Time to freshen up... </p> </div> <<set _ageStr = ($appearance.age === "Mature Adult") ? "mature" : "adult">> <<set _imgGender = ($gender === "male") ? ($physicalTraits.includes("Cuntboy") ? "cuntboy" : "male") : ($physicalTraits.includes("Dickgirl") ? "futanari" : "female")>> <!-- Bathroom Image --> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<if $bathroomMode === "shower">> <div style="text-align: center; margin-bottom: 20px;"> <img src="Images/M/shower_m_<<print _imgGender>>_<<print _ageStr>>.webp" style="max-width: 100%; width: 400px; border-radius: 10px; border: 2px solid #1e90ff;" onerror="this.style.display='none'"> </div> <<elseif $bathroomMode === "bath">> <div style="text-align: center; margin-bottom: 20px;"> <img src="Images/M/bath_m_<<print _imgGender>>_<<print _ageStr>>.webp" style="max-width: 100%; width: 400px; border-radius: 10px; border: 2px solid #667eea;" onerror="this.style.display='none'"> </div> <</if>> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Shower Options --> <<if $bathroomMode === "shower">> <!-- Quick Shower --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🚿 Quick Shower</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 10px 0;">A refreshing shower to clean up.</p> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">⏱️ Time: 15 minutes</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 15px 0;">🚿 Fresh & Clean buff (+15% trading, 3 hours)</p> <<link "<div style='background: #1e90ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Take Quick Shower</div>">> <<run advanceTime(15)>> <<set $lastShowerType = "quick">> <<goto "ShowerComplete">> <</link>> </div> <!-- Long Shower --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🚿 Long Hot Shower</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 10px 0;">Take your time and relax under the hot water.</p> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">⏱️ Time: 30 minutes</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 15px 0;">🚿 Fresh & Clean buff (+15% trading, 3 hours)</p> <<link "<div style='background: #1e90ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Take Long Shower</div>">> <<run advanceTime(30)>> <<set $lastShowerType = "long">> <<goto "ShowerComplete">> <</link>> </div> <</if>> <!-- Bath Options --> <<if $bathroomMode === "bath">> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🛁 Relaxing Bath</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 10px 0;">Soak in the tub and let your worries melt away.</p> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">⏱️ Time: 45 minutes</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 15px 0;">🛁 Fresh & Clean buff (+15% trading, 3 hours)</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Take a Bath</div>">> <<run advanceTime(45)>> <<set $lastBathType = "regular">> <<goto "BathComplete">> <</link>> </div> <!-- Bubble Bath - Spa Kit --> <<if _hasSpaKit>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🛁 Luxury Bubble Bath</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 10px 0;">Use your spa kit for the ultimate relaxation.</p> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">⏱️ Time: 60 minutes</p> <p style="color: #51cf66; font-size: 14px; margin: 0 0 15px 0;">🛁 Fresh & Clean buff (+15% trading, 3 hours)</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Take Bubble Bath</div>">> <<run advanceTime(60)>> <<set $lastBathType = "bubble">> <<goto "BathComplete">> <</link>> </div> <</if>> <</if>> <!-- Masturbate --> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🔞 Masturbate</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">The bathroom offers privacy for personal activities...</p> <<if $bathroomMode === "shower">> <<link "<div style='background: #ff6b6b; color: white; padding: 8px 15px; border-radius: 6px; text-align: center; cursor: pointer;'>In the Shower...</div>">> <<set $masturbationStats.lastLocation = "shower">> <<goto "MasturbationShower">> <</link>> <</if>> <<if $bathroomMode === "bath">> <<link "<div style='background: #667eea; color: white; padding: 8px 15px; border-radius: 6px; text-align: center; cursor: pointer;'>In the Bathtub...</div>">> <<set $masturbationStats.lastLocation = "bathtub">> <<goto "MasturbationBathtub">> <</link>> <</if>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Return to Bathroom</div>">> <<goto `setup.getCurrentBathroom()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ShowerComplete">> <<run setup.addBuff("shower_fresh", 180)>> <<if $lastShowerType === "long">> <<run setup.addBuff("bath_relaxed", 180)>> <</if>> <<run setup.setHairMessy()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="border: 3px solid #1e90ff; border-radius: 15px; background: #2a2a2a; padding: 40px; max-width: 500px; text-align: center;"> <h2 style="color: #1e90ff; margin: 0 0 20px 0;">🚿 Refreshed!</h2> <<if $lastShowerType === "long">> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 20px 0;"> The warm water cascades over you, washing away all tension. Steam fills the bathroom as you take your time, enjoying every moment. You step out feeling completely refreshed and relaxed. </p> <<else>> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 20px 0;"> The water cascades over you, washing away the grime of the day. You step out feeling clean and refreshed. </p> <</if>> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">🚿 Fresh & Clean buff gained!</p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">+15% trading bonus for 3 hours</p> <<if $lastShowerType === "long">> <p style="color: #51cf66; font-size: 16px; margin: 10px 0 0 0;">✓ Feeling more relaxed</p> <</if>> </div> <<link "<div style='background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>Continue</div>">> <<goto `setup.getCurrentBathroom()`>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BathComplete">> <<if $lastBathType === "bubble">> <<run setup.addBuff("bath_luxury", 240)>> <<else>> <<run setup.addBuff("shower_fresh", 180)>> <<run setup.addBuff("bath_relaxed", 180)>> <</if>> <<run setup.setHairMessy()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="border: 3px solid <<if $lastBathType === 'bubble'>>#ffd700<<else>>#667eea<</if>>; border-radius: 15px; background: #2a2a2a; padding: 40px; max-width: 500px; text-align: center;"> <<if $lastBathType === "bubble">> <h2 style="color: #ffd700; margin: 0 0 20px 0;">✨ Spa Experience</h2> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 20px 0;"> Surrounded by fragrant bubbles and luxurious bath oils, you let yourself drift into a state of complete bliss. This is what the good life is all about. </p> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #ffd700; font-size: 16px; margin: 0;">✨ Spa Bliss buff gained!</p> <p style="color: #b8860b; font-size: 14px; margin: 5px 0 0 0;">+20% trading, +5% steal chance for 4 hours</p> <p style="color: #ffd700; font-size: 16px; margin: 10px 0 0 0;">★ Deep relaxation achieved</p> </div> <<else>> <h2 style="color: #667eea; margin: 0 0 20px 0;">🛁 Deeply Relaxed</h2> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 20px 0;"> You sink into the warm water, feeling the tension melt from your muscles. The quiet solitude of the bath brings a sense of peace. </p> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">🚿 Fresh & Clean buff gained!</p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">+15% trading bonus for 3 hours</p> <p style="color: #667eea; font-size: 16px; margin: 10px 0 0 0;">🛁 Deeply Relaxed buff gained!</p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">+10% steal chance for 3 hours</p> </div> <</if>> <<if $lastBathType === "bubble">> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>Continue</div>">> <<goto `setup.getCurrentBathroom()`>> <</link>> <<else>> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>Continue</div>">> <<goto `setup.getCurrentBathroom()`>> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <<set _hasBoth = $bodyParts.genitals === "both">> <<set _chestSize = $bodyParts.chest>> <<set _hasBreasts = _chestSize !== "flat" && _chestSize !== "flat masculine">> <<set _penisSize = $bodyParts.genitals>> <<set _isSmallPenis = _penisSize === "small penis">> <<set _isAveragePenis = _penisSize === "average penis">> <<set _isBigPenis = _penisSize === "big penis">> <<set _isHugePenis = _penisSize === "huge penis">> <<set _isGiantPenis = _penisSize === "giant penis">> <<set _isSmallBreasts = _chestSize === "small">> <<set _isMediumBreasts = _chestSize === "medium">> <<set _isLargeBreasts = _chestSize === "large">> <<set _isHugeBreasts = _chestSize === "huge">> <<set _isMassiveBreasts = _chestSize === "massive">> <<set $lastLocation = "MasturbationBedroom">> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #ff6b6b; text-align: center;">🛏️ Masturbate in Bed</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <<masturbationImage "bed">> <div style="color: #ccc; font-size: 16px; line-height: 1.8;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p>You retire to the bedchamber and close the door behind you. The dress comes off slowly, item by item, each piece set down on the chaise with the care of a private ritual. By the time you slip beneath the silk sheets your skin is humming, your composure thinning at the edges. The girl who lives in this dress has needs, and at this hour and behind this lock there is no one to be appalled by them. <em>Ohohoho. Just this once. Quietly.</em></p> <</if>> <p>You lock the door with a soft click, savoring the anticipation already building inside you. The bedroom is quiet, intimate - just you and the soft sheets waiting to embrace your body. You strip off your clothes, feeling the cool air kiss your bare skin, then sink onto the bed with a contented sigh. The mattress gives beneath you as you settle against the pillows, your body already tingling with need.</p> <<if _hasBreasts>> <<if _isSmallBreasts>> <p>Your hands drift up to your small, pert breasts, cupping their delicate weight. They fit perfectly in your palms, so sensitive that even the lightest touch sends shivers down your spine. You circle your thumbs around your hardening nipples, gasping softly as sparks of pleasure radiate through your chest. The sheets feel silky against your back as you arch into your own touch.</p> <<elseif _isMediumBreasts>> <p>Your hands slide up to cup your shapely breasts, feeling their soft weight fill your palms. You squeeze them gently, watching the flesh yield between your fingers. Your nipples stiffen as you roll them between thumb and forefinger, sending pulses of warmth straight to your core. A soft moan escapes your lips as you knead the supple mounds, losing yourself in the sensation.</p> <<elseif _isLargeBreasts>> <p>Your large, heavy breasts spill into your hands as you lift them, marveling at their generous weight. You squeeze them together, feeling the soft flesh bulge between your fingers. Your nipples are achingly hard now, and you pinch them with increasing pressure, gasping at the pleasure-pain that shoots through you. Each touch makes your core clench with need.</p> <<elseif _isHugeBreasts>> <p>Your huge breasts spread across your chest, so heavy and full that they need both hands just to lift. You grip them firmly, feeling the soft flesh overflow your grasp. Your swollen nipples beg for attention, and you bring one to your lips, sucking on the hardened bud while your free hand roughly massages the other. The sensation is overwhelming, making you writhe against the sheets.</p> <<elseif _isMassiveBreasts>> <p>Your massive breasts dominate your torso, their extraordinary weight pressing you into the mattress. You struggle to contain even one in both hands as you knead the impossibly soft flesh. Your thick nipples are so sensitive they ache, and every touch sends lightning bolts of pleasure through your body. You bury your face between them, losing yourself in their warmth while your hands continue their desperate exploration.</p> <</if>> <</if>> <<if _hasPenis>> <<if _isSmallPenis>> <p>Your cock stiffens eagerly, standing at attention despite its modest size. You wrap your fingers around it, your hand easily enclosing the entire length. What you lack in size, you make up for in sensitivity - every nerve ending fires as you begin to stroke with tight, focused motions. Your thumb swirls over the sensitive head, making you gasp and buck your hips.</p> <p>You build a steady rhythm, your tight grip working your shaft with practiced expertise. The pleasure mounts quickly, your balls drawing tight as tension coils in your core. With a sharp grunt, your cock pulses in your grip as you climax, your release spurting onto your stomach as waves of satisfaction wash through you.</p> <<elseif _isAveragePenis>> <p>Your cock swells to full hardness, throbbing with need. You grip your satisfying length, feeling the heat pulse against your palm. Slowly, you begin to stroke, savoring the sensation of your foreskin gliding over the swollen head. Your thumb teases the sensitive tip, spreading the bead of pre-cum that forms there.</p> <p>Your strokes grow faster, more urgent. The slick sounds of your hand working your shaft fill the quiet room. You imagine a lover's touch, their eager hands on your body. The pressure builds until you can't hold back - your cock throbs powerfully as ropes of cum paint your stomach, leaving you gasping and utterly satisfied.</p> <<elseif _isBigPenis>> <p>Your substantial cock rises thick and proud from your body, the impressive length demanding attention. You grip it with both hands, still leaving shaft exposed above and below your fists. The veins pulse visibly as you begin to stroke, the thick head swelling to an angry purple. Pre-cum leaks freely, providing natural lubrication.</p> <p>You pump your thick shaft with long, powerful strokes, one hand twisting around the head while the other works the base. The pleasure is intense, building like a storm. When you finally cum, your big cock erupts violently, thick streams of seed arcing through the air and splattering across your chest. Your whole body shakes from the force of your release.</p> <<elseif _isHugePenis>> <p>Your massive cock swells to its full, intimidating size, so long and thick it looks almost unreal. The weight of it is substantial as you grip the shaft with both hands - and there's still more exposed. Veins thick as cables throb along its length, pulsing with your heartbeat. Just holding something this big feels obscene.</p> <p>You stroke your huge member with determination, your arms working hard to pleasure its entire length. Pre-cum drools continuously from the fat head. When climax hits, it's volcanic - your enormous cock bucks and convulses as massive ropes of thick cum blast across your body, painting you from chest to chin. You cry out, overwhelmed by the intensity.</p> <<elseif _isGiantPenis>> <p>Your monster cock stirs to life, engorging with blood until it reaches its breathtaking full size. It's so large it borders on the inhuman - a magnificent pillar of flesh that demands worship. Both hands wrapped around it barely cover half the shaft. The head is swollen and angry, already weeping with need.</p> <p>Stroking something this massive is an athletic feat, but the sensations are worth every effort. Pre-cum pours from your cock in a steady stream. When you finally explode, it's like a force of nature - your giant cock convulses as an almost inhuman flood of cum erupts, jet after jet covering your entire torso. You roar with release, your body shaking uncontrollably.</p> <</if>> <</if>> <<if _hasVagina>> <p>Your hand slides down your stomach, fingers trailing through the heat between your thighs. You're already wet, your body eager and ready. You spread your legs against the cool sheets, giving yourself full access. One finger traces along your slick folds before finding your swollen clit.</p> <p>A moan escapes you as you begin to circle the sensitive nub with practiced expertise. Your hips rock against your hand as you work yourself, alternating between teasing your clit and plunging fingers deep inside. Two fingers curl forward, finding that perfect spot that makes your toes curl and back arch.</p> <p>The pressure builds with every stroke. You add a third finger, stretching yourself deliciously as your thumb maintains its relentless rhythm on your clit. When orgasm finally crashes through you, your inner walls clench hard around your fingers as waves of pleasure pulse through your core, leaving you trembling and breathless against the sheets.</p> <</if>> <<if _hasBoth>> <p>Having both sets of equipment gives you options most people can only dream of. One hand wraps around your stiffening cock while the other slides between your thighs to your slick pussy. The dual stimulation is electric, each touch amplifying the other until the pleasure bounces between them like lightning.</p> <p>You stroke yourself in rhythm while your fingers work your sensitive clit, then plunge inside. Your cock throbs in your grip while your inner walls clench around your fingers. When you cum, you cum HARD - your cock spurts across your stomach while your pussy clenches in powerful contractions. The dual orgasm leaves you seeing stars, completely overwhelmed by the intensity.</p> <</if>> <p>You lie back against the pillows, utterly spent and satisfied. The tension has melted from your body, replaced by a warm, pleasant glow. That was exactly what you needed.</p> </div> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Penis Options --> <<if _hasPenis>> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">Manual Stimulation</h3> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use your hand</div>">> <<set $masturbationStats.timesTotal++>> <<set $toyUsed = false>> <<goto "MasturbationPenisScene">> <</link>> </div> <<if $ownsFleshlight>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">Use Toy</h3> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use your fleshlight</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.fleshlight++>> <<set $toyUsed = "fleshlight">> <<goto "MasturbationPenisScene">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 20px; background: #1a1a1a; opacity: 0.7;"> <h3 style="color: #888; margin: 0 0 10px 0;">Fleshlight</h3> <p style="color: #666; font-size: 14px; margin: 0;">You don't own one. Visit the Adult Store ($50).</p> </div> <</if>> <</if>> <!-- Vagina Options --> <<if _hasVagina>> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">Manual Stimulation</h3> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use your fingers</div>">> <<set $masturbationStats.timesTotal++>> <<set $toyUsed = false>> <<goto "MasturbationVaginaScene">> <</link>> </div> <<if $ownsDildo>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">Use Toy</h3> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use your dildo</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.dildo++>> <<set $toyUsed = "dildo">> <<goto "MasturbationVaginaScene">> <</link>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 20px; background: #1a1a1a; opacity: 0.7;"> <h3 style="color: #888; margin: 0 0 10px 0;">Dildo</h3> <p style="color: #666; font-size: 14px; margin: 0;">You don't own one. Visit the Adult Store ($45).</p> </div> <</if>> <</if>> <!-- Chest Play Option --> <<if _hasBreasts>> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">Breast Play</h3> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Focus on your chest</div>">> <<set $masturbationStats.timesTotal++>> <<goto "MasturbationChestScene">> <</link>> </div> <</if>> <!-- Dual Stimulation Option (Futanari/Hermaphrodite only) --> <<if _hasBoth && $physicalTraits.includes("Futanari")>> <<set _futaVar = setup.getFutaVariant()>> <div style="border: 3px solid #e040fb; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #2a2a2a 0%, #1a1a2a 100%);"> <h3 style="color: #e040fb; margin: 0 0 10px 0;">Dual Stimulation</h3> <p style="color: #aaa; font-size: 13px; margin: 0 0 10px 0;"><<if _futaVar === "futanari">>Pleasure your cock and pussy together<<else>>Work both sets of equipment at once<</if>></p> <<link "<div style='background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use both hands</div>">> <<set $masturbationStats.timesTotal++>> <<set $toyUsed = false>> <<set $masturbationStats.dualStimulation = ($masturbationStats.dualStimulation || 0) + 1>> <<goto "MasturbationPenisScene">> <</link>> </div> <</if>> <<if $activeTransformation === "Cerberus">> <div style="border: 3px solid #c77dff; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a28 100%);"> <h3 style="margin: 0 0 15px 0;"><span style="color:#ffd700;">Three</span> <span style="color:#c93068;">Heads</span></h3> <<link "<div style='background: linear-gradient(135deg, #c93068 0%, #c77dff 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>💋 Make out with your other heads</div>">> <<set $masturbationStats.timesTotal++>> <<goto "CerberusSelfMakeout">> <</link>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Changed my mind</div>">> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _size = $bodyParts.genitals>> <<set _chestSize = $bodyParts.chest>> <<set _hasBreasts = _chestSize !== "flat" && _chestSize !== "flat masculine">> <<set _buttSize = $bodyParts.butt>> <<set $lastLocation = "MasturbationPenisScene">> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="border: 3px solid #ff6b6b; border-radius: 15px; background: #2a2a2a; padding: 30px; max-width: 700px; margin: 0 auto;"> <h2 style="color: #ff6b6b; text-align: center; margin: 0 0 20px 0;">🔞 Private Pleasure</h2> <<masturbationImage "bed">> <div style="color: #ccc; font-size: 16px; line-height: 1.8;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p>You retire to the bedchamber and close the door behind you. The dress comes off slowly, item by item, each piece set down on the chaise with the care of a private ritual. By the time you slip beneath the silk sheets your skin is humming, your composure thinning at the edges. The girl who lives in this dress has needs, and at this hour and behind this lock there is no one to be appalled by them. <em>Ohohoho. Just this once. Quietly.</em></p> <</if>> <!-- Opening varies by size and by tool (hand vs fleshlight). The fleshlight branch replaces the hand opening rather than being stacked on top of it, so the player only sees one set of stroking/thrusting prose per scene. --> <<if $toyUsed === "fleshlight">> <<if _size === "small penis">> <p>You reach for your fleshlight, squirting lube inside before sliding your modest cock all the way in on the first stroke. The textured sleeve closes around every inch of you, far more sensation than your fingers could ever offer. You begin to thrust into the toy with quiet, eager moans, your hips finding a rhythm almost on their own.</p> <<elseif _size === "big penis">> <p>You reach for your fleshlight, squirting a generous amount of lube inside before pressing your thick, impressive shaft against the entrance. The opening stretches to take you, the textured sleeve gripping and milking every inch of your considerable girth. You moan as you bottom out, then start thrusting, the toy clinging tight to your length on every pull back.</p> <<elseif _size === "huge penis" || _size === "giant penis">> <p>You reach for your fleshlight and squirt in a flood of lube. Even slicked, the entrance struggles to take you. You force your massive cock in slowly, gasping as the obscenely stretched sleeve clamps around your shaft. Each thrust is wet and almost too tight, the squelching sounds filling the room as the toy works your ridiculous length.</p> <<else>> <p>You reach for your fleshlight, squirting a generous amount of lube inside before pressing your swollen head against the entrance. You moan softly as you slide in, the textured interior gripping and massaging every inch of your shaft. You begin thrusting, fucking the toy with increasing urgency.</p> <</if>> <<else>> <<if _size === "small penis">> <p>You wrap your fingers around your modest cock, the familiar sensation sending a shiver up your spine. Your thumb traces the sensitive head, smearing the bead of precum that's already formed. You know exactly how to work your length, your grip tightening as you begin to stroke in earnest.</p> <<elseif _size === "big penis">> <p>You grip your thick, impressive shaft, both hands finding plenty to work with. The heavy weight of your cock feels incredible in your palms as you begin long, slow strokes from base to tip. Precum wells up, slicking your length and making your grip slide deliciously along your veiny shaft.</p> <<elseif _size === "huge penis" || _size === "giant penis">> <p>Your massive cock throbs demandingly, too thick for one hand to fully encircle. You grip it with both fists, pumping up and down the ridiculous length. Precum drools from the swollen head, running down over your knuckles. Every stroke sends bolts of pleasure through your body, your heavy balls tightening beneath.</p> <<else>> <p>You take hold of your hardening cock, wrapping your fingers around the shaft. A familiar warmth spreads through your groin as you begin to stroke, your hand sliding up and down in a practiced rhythm. Your cock stiffens fully under your touch, the head flushing a deeper color.</p> <</if>> <</if>> <!-- Chest involvement for those with breasts --> <<if _hasBreasts>> <<if _chestSize === "large" || _chestSize === "huge" || _chestSize === "giant" || _chestSize === "gigantic">> <p>Your free hand wanders up to your heavy breasts, cupping and squeezing the soft flesh. You pinch a stiffening nipple between your fingers, rolling it as pleasure shoots down to join the sensations in your groin. Your <<print _chestSize>> tits bounce gently as your stroking grows more urgent.</p> <<elseif _chestSize === "small" || _chestSize === "medium">> <p>Your fingers find your chest, circling a sensitive nipple before pinching it firmly. The sharp pleasure mixes perfectly with the heat building in your cock, making you moan.</p> <</if>> <</if>> <!-- Building intensity --> <p>Your breathing grows ragged as the pleasure mounts. Your hand moves faster, gripping tighter, chasing that building pressure. Your balls draw up tight, your cock throbbing and pulsing in your grip. You can feel it coming, that familiar tension coiling in your core...</p> <!-- Climax varies by size --> <<if _size === "huge penis" || _size === "giant penis">> <p>With a strangled cry, you explode. Your massive cock jerks violently, spurting thick ropes of cum that arc through the air. Load after load pumps from your throbbing shaft, coating your stomach and chest in hot, sticky release. The orgasm seems to go on forever, your cock continuing to twitch and dribble as the waves of pleasure slowly subside.</p> <<elseif _size === "big penis">> <p>You gasp as the orgasm hits, your cock pulsing hard in your grip. Thick cum spurts from the head, splashing across your stomach in long strings. Your hips buck involuntarily as you milk every last drop from your throbbing shaft, the pleasure washing through you in powerful waves.</p> <<else>> <p>The orgasm crashes through you, your cock twitching and spurting in your hand. Hot cum splashes across your skin as you stroke through the climax, riding out every pulse of pleasure until you're left panting and satisfied, your spent cock softening in your grip.</p> <</if>> /* Futanari/Hermaphrodite dual stimulation */ <<if setup.getFutaVariant()>> <<if setup.getFutaVariant() === "futanari">> <p>But your body isn't done yet. Even as your cock softens, you feel the wet heat between your thighs demanding attention. Your free hand slides down to your soaked pussy, fingers slipping easily between your swollen folds. You shudder as you circle your throbbing clit, your breasts heaving with each ragged breath while your spent cock twitches at the renewed stimulation. A second orgasm builds fast — your pussy clenches around your fingers as it crashes through you, your cock pulsing weakly in sympathy. <<print setup.getFutaFlavorText("masturbation_climax")>></p> <<else>> <p>Your cock may be spent, but the ache between your legs is only growing. You reach down past your softening shaft and press two fingers into your dripping pussy, groaning at the slick tightness. Your powerful thighs clench as you work yourself, cock pulsing against your wrist with each thrust of your fingers. The second climax rips through you without warning — your pussy contracts in rhythmic waves while your cock throbs and leaks a final dribble of cum. <<print setup.getFutaFlavorText("masturbation_climax")>></p> <</if>> <</if>> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">✓ Feeling satisfied</p> <<if $toyUsed>> <p style="color: #ffd700; font-size: 16px; margin: 5px 0 0 0;">★ Toy made it extra satisfying</p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e040fb; font-size: 16px; margin: 5px 0 0 0;">★ Double orgasm from dual anatomy</p> <</if>> </div> <<run advanceTime(20)>> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer; display: inline-block;'>Clean up and continue</div>">> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _chestSize = $bodyParts.chest>> <<set _hasBreasts = _chestSize !== "flat" && _chestSize !== "flat masculine">> <<set _buttSize = $bodyParts.butt>> <<set $lastLocation = "MasturbationVaginaScene">> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="border: 3px solid #ff6b6b; border-radius: 15px; background: #2a2a2a; padding: 30px; max-width: 700px; margin: 0 auto;"> <h2 style="color: #ff6b6b; text-align: center; margin: 0 0 20px 0;">🔞 Private Pleasure</h2> <<masturbationImage "bed">> <div style="color: #ccc; font-size: 16px; line-height: 1.8;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p>You retire to the bedchamber and close the door behind you. The dress comes off slowly, item by item, each piece set down on the chaise with the care of a private ritual. By the time you slip beneath the silk sheets your skin is humming, your composure thinning at the edges. The girl who lives in this dress has needs, and at this hour and behind this lock there is no one to be appalled by them. <em>Ohohoho. Just this once. Quietly.</em></p> <</if>> <p>You lie back on the bed, spreading your thighs as your hand trails down your body. Your fingers find their way between your legs, tracing along the soft folds of your pussy. Already you can feel the slick wetness gathering, your body responding to your touch. You tease yourself, running a fingertip along your slit, dipping just barely inside before circling your swelling clit.</p> <!-- Chest variation --> <<if _hasBreasts>> <<if _chestSize === "large" || _chestSize === "huge" || _chestSize === "giant" || _chestSize === "gigantic">> <p>Your other hand finds your heavy breasts, cupping and squeezing the abundant flesh. You roll a stiffening nipple between your fingers, pinching until you gasp. Your <<print _chestSize>> tits jiggle as your breathing quickens, their weight shifting as you arch into your own touch.</p> <<elseif _chestSize === "small" || _chestSize === "medium">> <p>Your free hand cups your breast, thumb circling a hardening nipple. You pinch and tug at the sensitive peak, sending sparks of pleasure down to join the heat building between your legs.</p> <</if>> <</if>> <!-- Toy variation --> <<if $toyUsed === "dildo">> <p>You reach for your dildo, running the thick head teasingly along your soaking slit. You press it against your entrance, feeling yourself stretch to accommodate it as you push it slowly inside. A moan escapes your lips as the toy fills you, inch by inch, until you're stuffed full. You begin pumping it in and out, the wet squelching sounds filling the room as you fuck yourself with increasing urgency.</p> <<else>> <p>You slide two fingers inside yourself, gasping at the slick heat that grips them. Your fingers curl forward, finding that spongy spot that makes your toes curl. Your palm grinds against your throbbing clit as you finger yourself, your inner walls clenching hungrily around the intrusion.</p> <</if>> <!-- Butt variation --> <<if _buttSize === "large" || _buttSize === "huge" || _buttSize === "giant" || _buttSize === "gigantic">> <p>Your hips rock desperately, your plump ass pressing into the mattress before lifting as you chase your pleasure. The bed creaks beneath your <<print _buttSize>> rear as you grind and thrust against your own hand.</p> <</if>> <!-- Building and climax --> <p>The pleasure builds relentlessly, each stroke and circle driving you higher. Your breath comes in desperate pants, your pussy clenching and dripping, your whole body tensing toward release. You can feel it coming, that tightening coil of pleasure ready to snap...</p> <p>The orgasm crashes through you like a wave, your inner walls spasming rhythmically as you cry out. Your hips buck uncontrollably, grinding against your hand as pulse after pulse of pleasure rolls through your core. You keep rubbing your clit through the aftershocks, milking every last tremor until you collapse back onto the bed, thoroughly satisfied and deliciously spent.</p> /* Futanari/Hermaphrodite dual stimulation */ <<if setup.getFutaVariant()>> <<if setup.getFutaVariant() === "futanari">> <p>As the aftershocks fade, you become acutely aware of your neglected cock, rock-hard and dripping pre-cum against your trembling stomach. You wrap your slick fingers around it — still wet from your pussy — and stroke with urgent, desperate pulls. Your breasts bounce with each frantic motion, nipples stiff and aching. It only takes a dozen strokes before your cock erupts, thick ropes of cum spattering across your heaving chest while your pussy still flutters with residual contractions. <<print setup.getFutaFlavorText("masturbation_climax")>></p> <<else>> <p>The vaginal orgasm has left your cock throbbing painfully hard, ignored until now. You grip your aching shaft with your soaked hand, pumping with rough, desperate strokes. Your powerful thighs flex as your hips drive upward, cock pulsing in your fist while your pussy still clenches in fading aftershocks. The second orgasm tears through you — your cock bucks and spurts across your abs as your pussy squeezes tight one final time. <<print setup.getFutaFlavorText("masturbation_climax")>></p> <</if>> <</if>> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">✓ Feeling satisfied</p> <<if $toyUsed>> <p style="color: #ffd700; font-size: 16px; margin: 5px 0 0 0;">★ Your dildo made it extra satisfying</p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e040fb; font-size: 16px; margin: 5px 0 0 0;">★ Double orgasm from dual anatomy</p> <</if>> </div> <<run advanceTime(25)>> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer; display: inline-block;'>Clean up and continue</div>">> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _chestSize = $bodyParts.chest>> <<set $lastLocation = "MasturbationChestScene">> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="border: 3px solid #ff6b6b; border-radius: 15px; background: #2a2a2a; padding: 30px; max-width: 700px; margin: 0 auto;"> <h2 style="color: #ff6b6b; text-align: center; margin: 0 0 20px 0;">🔞 Breast Play</h2> <<masturbationImage "bed">> <div style="color: #ccc; font-size: 16px; line-height: 1.8;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p>A lady tends to her own attentions in private. You sit at the edge of the bed and let the bodice down off your shoulders, the corset loosening with a long indulgent sigh. The fullness she gave you spills free into your own hands, heavier than you ever expected to be. <em>Goodness. These are quite a lot to be the proper owner of.</em></p> <</if>> <<if _chestSize === "gigantic">> <p>You lift your enormous, wobbling breasts, marveling at their impossible weight. The soft flesh spills through your fingers no matter how you try to contain them. You squeeze them together, watching them bulge and jiggle, the sensation alone enough to make you moan.</p> <p>Your nipples are swollen and aching for attention. You pinch them firmly, gasping as bolts of pleasure shoot through your chest. With breasts this massive, you can easily lift one to your mouth, swirling your tongue around the stiff peak before sucking hungrily. Your other hand kneads the neglected breast, squeezing and groping the pliant flesh.</p> <p>You lose yourself in the sensation, your gigantic tits bouncing and wobbling as you pleasure them. Heat spreads between your legs as the stimulation builds, each pinch and squeeze pushing you closer to a nipple-induced orgasm.</p> <<elseif _chestSize === "giant">> <p>Your massive breasts overflow your hands as you cup and squeeze them. The heavy, soft flesh molds under your fingers as you knead them eagerly. You press them together, creating deep cleavage before letting them bounce apart.</p> <p>Your nipples stiffen into hard peaks as you roll and pinch them. The sensation goes straight to your core, making your pussy clench with need. You alternate between squeezing and stroking, moaning as waves of pleasure radiate from your sensitive chest.</p> <<elseif _chestSize === "huge">> <p>You take your huge breasts in hand, savoring their heavy weight and softness. Your thumbs trace circles around your areolas, teasing closer and closer to the stiff peaks in the center. When you finally pinch your nipples, you gasp at the intensity.</p> <p>You squeeze and massage your tits, feeling them jiggle and bounce with every movement. The pleasure builds steadily as you continue, your nipples throbbing with sensitivity, your breathing growing ragged.</p> <<elseif _chestSize === "large">> <p>Your large breasts fill your palms nicely as you cup and squeeze them together. You trace circles around your puffy areolas, watching your nipples stiffen in anticipation. When you finally pinch them, a moan escapes your lips.</p> <p>You knead the soft flesh, tugging your nipples and rolling them between your fingers. Each touch sends sparks of pleasure down to join the growing warmth between your thighs.</p> <<elseif _chestSize === "medium">> <p>You caress your breasts, cupping them and squeezing gently. Your nipples respond immediately, stiffening under your fingers as you trace around them. You pinch and roll them, gasping at the sensitivity.</p> <p>The stimulation builds a delicious warmth that spreads through your body, making you squirm with arousal.</p> <<else>> <p>What you lack in size, you make up for in sensitivity. Your small breasts are incredibly responsive - even the lightest brush of your fingers across your nipples makes you gasp and shiver.</p> <p>You tease yourself mercilessly, circling and pinching your achingly hard nipples. Each touch sends electric pleasure coursing through your body, making your toes curl.</p> <</if>> <p>After a blissful session of teasing and pleasuring your sensitive breasts, you lie back with a satisfied sigh. Your nipples are still tingling, your body buzzing with the afterglow of purely chest-focused pleasure.</p> /* Futanari/Hermaphrodite arousal from breast play */ <<if setup.getFutaVariant()>> <<if setup.getFutaVariant() === "futanari">> <p>Between your legs, your cock is rock-hard and leaking pre-cum against your thigh, and your pussy is slick with arousal — both desperately worked up from the breast stimulation alone. You resist the urge to touch yourself further, savoring the ache of unsatisfied dual need.</p> <<else>> <p>Below, your cock strains upward, thick and dripping, while your pussy throbs with wet heat — your dual anatomy thoroughly aroused from nothing but chest play. You clench your thighs together, feeling both sets of genitals pulse in frustrated need.</p> <</if>> <</if>> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">✓ Feeling sensual and satisfied</p> <<if setup.getFutaVariant()>> <p style="color: #e040fb; font-size: 14px; margin: 5px 0 0 0;">Your dual anatomy is thoroughly worked up...</p> <</if>> </div> <<run advanceTime(15)>> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer; display: inline-block;'>Continue</div>">> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <<set _hasBoth = $bodyParts.genitals === "both">> <<set _chestSize = $bodyParts.chest>> <<set _hasBreasts = _chestSize !== "flat" && _chestSize !== "flat masculine">> <<set _penisSize = $bodyParts.genitals>> <<set _isSmallPenis = _penisSize === "small penis">> <<set _isAveragePenis = _penisSize === "average penis">> <<set _isBigPenis = _penisSize === "big penis">> <<set _isHugePenis = _penisSize === "huge penis">> <<set _isGiantPenis = _penisSize === "giant penis">> <<set _isSmallBreasts = _chestSize === "small">> <<set _isMediumBreasts = _chestSize === "medium">> <<set _isLargeBreasts = _chestSize === "large">> <<set _isHugeBreasts = _chestSize === "huge">> <<set _isMassiveBreasts = _chestSize === "massive">> <<set $lastLocation = "MasturbationShower">> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="border: 3px solid #1e90ff; border-radius: 15px; background: #2a2a2a; padding: 30px; max-width: 700px; margin: 0 auto;"> <h2 style="color: #1e90ff; text-align: center; margin: 0 0 20px 0;">🚿 Shower Fun</h2> <<masturbationImage "shower">> <div style="color: #ccc; font-size: 16px; line-height: 1.8;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p>You step out of the dress and into your private bath, the door latched behind you. Hot water sluices over pale skin in the way she would have wanted, prim and ritual and absolutely alone. The fan stays folded on the marble counter. You will need both hands. <em>Behind these walls, nobody minds.</em></p> <</if>> <p>Steam billows around you as scalding water cascades down your naked body. The bathroom fills with a thick, humid warmth that clings to your skin. Standing beneath the rainfall showerhead, you let the water pound against your shoulders and run in rivulets down every curve and contour. The heat seeps into your muscles, making you feel languid and aroused. With total privacy surrounding you, your thoughts drift to pleasure...</p> <<if _hasBreasts>> <<if _isSmallBreasts>> <p>The water flows over your small, pert breasts, the stream making your sensitive nipples harden instantly. You cup them gently, feeling how perfectly they fit in your palms. Your thumbs circle your nipples, sending little sparks of pleasure down your spine. Each drop of water that hits your chest feels magnified, a thousand tiny caresses against your delicate flesh.</p> <<elseif _isMediumBreasts>> <p>Hot water streams over your shapely breasts, running around and between them in tantalizing paths. You cup their soft weight in your hands, feeling them fill your palms beautifully. Your nipples stiffen under the water's assault as you roll them between your fingers, a soft moan escaping your lips. The sensation sends pulses of warmth straight to your core.</p> <<elseif _isLargeBreasts>> <p>The water cascades over your large, heavy breasts, streaming around their generous curves and dripping from your hardened nipples. You lift them with both hands, marveling at their substantial weight as the water flows between your fingers. When you squeeze them together, the sensation makes you gasp. Your nipples are achingly sensitive now, and you pinch them gently, then harder, feeling the pleasure-pain radiate through your chest.</p> <<elseif _isHugeBreasts>> <p>Hot water pours over your huge breasts, struggling to flow around their impressive mass. They hang heavy and full on your chest, the water streaming off in waterfalls from your swollen nipples. You grip them firmly, feeling the soft flesh spill between your fingers. Each squeeze sends waves of pleasure through you - they're so sensitive, so responsive. You lift one to your mouth, licking the water from your own nipple, sucking on the hardened bud while your free hand continues to massage the other.</p> <<elseif _isMassiveBreasts>> <p>The water cascades over your massive breasts like a river dividing around boulders. Their extraordinary weight pulls at your chest, the warm water doing little to lighten them. You struggle to lift them, both hands barely containing a single breast as water streams off in sheets. Your nipples are so thick and hard now they ache with need. Every touch sends lightning bolts of pleasure through your body. You press them together, bury your face between them, losing yourself in their incredible softness while the hot water pounds against your back.</p> <</if>> <</if>> <<if _hasPenis>> <<if _isSmallPenis>> <p>Despite the heat, you feel yourself stiffening with arousal. You look down at your compact member, fully erect now, bobbing slightly under the spray. You wrap your fingers around it, your hand easily enclosing its modest length. The soap provides perfect lubrication as you begin to stroke with a tight grip, working your entire shaft with quick, focused motions. What you lack in size, you make up for in sensitivity - every nerve ending fires with pleasure as your pace quickens.</p> <p>The water hammers against your back as you brace yourself against the tile with one hand. Your other hand works faster now, tight strokes from base to tip. The heat builds rapidly in your core, your balls tightening. With a grunt, you feel the pressure peak - your cock pulses in your grip as you climax, your release mixing with the water and swirling down the drain. Your legs tremble from the intensity.</p> <<elseif _isAveragePenis>> <p>The warm water teases your cock to attention, blood rushing south as you feel yourself growing harder. You wrap your soapy fist around your shaft, feeling its satisfying heft in your palm. You begin to stroke with long, deliberate movements, savoring the slick sensation of soap and water as your foreskin glides over the swollen head. Your thumb swirls over the tip each time you reach the top, sending shivers up your spine.</p> <p>Steam swirls around you as you pick up the pace, your hand making wet slapping sounds against your thighs. You imagine a lover on their knees before you, mouth open, eager. Your breathing grows ragged. The pressure builds until you can't hold back anymore - your cock throbs powerfully as ropes of cum spray against the shower wall, immediately washed away by the cascading water. You slump against the tile, spent and satisfied.</p> <<elseif _isBigPenis>> <p>Your substantial cock responds eagerly to the warm water, thickening and lengthening until it stands proud from your body, heavy with arousal. You grip it with both hands - the thick shaft fills your fingers completely. The veins pulse visibly beneath the skin as you begin to stroke, the soap creating obscene sounds that echo off the tile walls. Your impressive length requires full-arm movements to pleasure properly.</p> <p>The head swells until it's an angry purple, hypersensitive as water streams over it. You work your shaft with determined focus, one hand twisting around the head while the other pumps the thick base. Pre-cum leaks freely, mixing with water and soap. When your orgasm hits, it hits HARD - your cock erupts like a geyser, thick streams of cum painting the shower wall as wave after wave of pleasure crashes through you. Your knees nearly buckle as you ride out the intense release.</p> <<elseif _isHugePenis>> <p>Even soft, your cock is impressive, but as arousal floods through you, it swells to its full, intimidating size. The weight of it is substantial as it rises, pointing outward like a weapon. You grip it with both hands and there's still shaft visible above and below your fists. The thick veins throb visibly as blood engorges every inch. Stroking something this size is an athletic endeavor - your arms work hard as you pump your massive member with long, powerful strokes.</p> <p>The head is so swollen it looks almost angry, pre-cum drooling from the tip in long, sticky strands. Your balls churn heavy between your thighs. The pleasure builds inexorably, your huge cock throbbing in your grip. When you finally cum, it's like an explosion - your cock bucks violently as massive ropes of thick cum blast across the shower, hitting the far wall with audible splats. You cry out, overwhelmed by the intensity as your enormous member continues to pulse and spurt, emptying what feels like an ocean of seed down the drain.</p> <<elseif _isGiantPenis>> <p>Your monster cock stirs to life, engorging with blood until it reaches its breathtaking full size. It's so long and thick it borders on the inhuman - a magnificent pillar of flesh that juts from your body with almost aggressive power. Both hands wrapped around it only cover half the shaft. The veins crisscrossing its length are thick as cables, pulsing with your heartbeat. Just holding something this massive feels obscene.</p> <p>You have to lean back against the tile just to support the weight as you begin stroking your colossal member. The water runs down its incredible length in streams. Your arms burn from the effort of pleasuring something so large, but the sensations are overwhelming. Pre-cum pours from the fat head in a continuous stream. When climax finally arrives, it's volcanic - your giant cock convulses as you unleash an almost inhuman amount of cum, jet after jet splattering the shower like a fire hose. You roar with release, your entire body shaking as your enormous member continues pumping out seed for what feels like an eternity. You're left trembling, utterly drained.</p> <</if>> <</if>> <<if _hasVagina>> <p>The hot water flows between your thighs, teasing your most intimate places. You spread your legs slightly, letting the spray caress your sensitive folds. One hand braces against the slick tile wall while the other slides down your wet stomach. Your fingers find your lips, already slick with more than just water. You part them gently, exposing your swollen clit to the warm cascade.</p> <p>A gasp escapes you as your fingertips circle your sensitive nub. The water heightens every sensation, making you feel slippery and electric all at once. You work yourself with practiced expertise, alternating between teasing circles around your clit and dipping inside your eager entrance. Two fingers slide in easily - you're so wet, so ready. You curl them forward, finding that perfect spot that makes your legs shake.</p> <p>Your hips rock against your hand as you build toward release. Steam swirls around you as your moans echo off the tile. The pressure builds and builds until finally it crests - your inner walls clench hard around your fingers as waves of orgasm wash through you. Your knees buckle and you have to grip the safety bar to stay upright as pleasure pulses through your core, spreading outward until even your toes curl against the wet shower floor.</p> <</if>> <<if _hasBoth>> <p>The unique sensation of having both sets of equipment throbs with arousal. You have so many options for pleasure, and you intend to explore them all. One hand wraps around your stiff cock while the other slides between your thighs to your dripping pussy. The dual stimulation is almost overwhelming.</p> <p>You stroke yourself in rhythm while your fingers work your sensitive clit, then plunge inside your wet channel. The pleasure bounces between both sources, amplifying and echoing until you can't tell where one sensation ends and another begins. Your cock throbs in your grip while your inner walls squeeze your fingers. When you cum, you cum EVERYWHERE - your cock spurts against the wall while your pussy clenches in powerful contractions. The dual orgasm leaves you seeing stars, slumped against the tile, completely overwhelmed by the intensity.</p> <</if>> /* Futanari/Hermaphrodite shower-specific flavor */ <<if setup.getFutaVariant() && _hasBoth>> <<if setup.getFutaVariant() === "futanari">> <p>The hot water streams over your spent body, washing cum from your stomach and thighs. Your cock hangs heavy and satisfied against your thigh while your pussy still pulses with tiny aftershocks, each one making your breasts sway gently under the spray. The shower rinses away every trace, but the tingling between your legs — from both sides — lingers deliciously.</p> <<else>> <p>Water sluices the cum from your powerful body as you lean against the tile, catching your breath. Your cock drips the last of its release into the drain while your pussy still clenches in slow, fading contractions between your muscular thighs. The shower washes you clean, but the bone-deep satisfaction of a dual orgasm will stay with you for hours.</p> <</if>> <</if>> <p>The hot water continues to pour over you as you float in the blissful aftermath, all tension melted away. You feel completely relaxed, satisfied, and squeaky clean.</p> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">✓ Feeling satisfied</p> <p style="color: #1e90ff; font-size: 16px; margin: 5px 0 0 0;">✓ Also got clean!</p> <<if setup.getFutaVariant() && _hasBoth>> <p style="color: #e040fb; font-size: 16px; margin: 5px 0 0 0;">★ Dual anatomy made it twice as good</p> <</if>> </div> <<set $hygiene = Math.min(100, $hygiene + 40)>> <<set $masturbationStats.timesTotal++>> <<run advanceTime(30)>> <div style="text-align: center;"> <<link "<div style='background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer; display: inline-block;'>Finish showering</div>">> <<goto `setup.getCurrentBathroom()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <<set _hasBoth = $bodyParts.genitals === "both">> <<set _chestSize = $bodyParts.chest>> <<set _hasBreasts = _chestSize !== "flat" && _chestSize !== "flat masculine">> <<set _buttSize = $bodyParts.butt>> <<set _penisSize = $bodyParts.genitals>> <<set _isSmallPenis = _penisSize === "small penis">> <<set _isAveragePenis = _penisSize === "average penis">> <<set _isBigPenis = _penisSize === "big penis">> <<set _isHugePenis = _penisSize === "huge penis">> <<set _isGiantPenis = _penisSize === "giant penis">> <<set _isSmallBreasts = _chestSize === "small">> <<set _isMediumBreasts = _chestSize === "medium">> <<set _isLargeBreasts = _chestSize === "large">> <<set _isHugeBreasts = _chestSize === "huge">> <<set _isMassiveBreasts = _chestSize === "massive">> <<set _isLargeBass = _buttSize === "large" || _buttSize === "huge" || _buttSize === "giant" || _buttSize === "gigantic">> <<set $lastLocation = "MasturbationBathtub">> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="border: 3px solid #667eea; border-radius: 15px; background: #2a2a2a; padding: 30px; max-width: 700px; margin: 0 auto;"> <h2 style="color: #667eea; text-align: center; margin: 0 0 20px 0;">🛁 Bathtub Bliss</h2> <<masturbationImage "bathtub">> <div style="color: #ccc; font-size: 16px; line-height: 1.8;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p>You draw the bath yourself, lavender oils, rose petals, every refinement she would have insisted on. The corset comes off in slow stages. By the time you sink into the water you are already humming with something that is decidedly not refinement, and you let it have you. <em>A perfectly civilised indulgence. Behind a locked door.</em></p> <</if>> <p>You lower yourself into the steaming bath, sighing with pleasure as the hot water envelops your naked body inch by inch. The porcelain is smooth against your skin as you settle in, letting the warmth seep into your muscles and bones. Fragrant steam rises around you, and the soft glow of candles (or perhaps the bathroom light) casts everything in a flattering, intimate haze. This is your sanctuary, your private retreat - and you intend to make the most of it.</p> <<if _hasBreasts>> <<if _isSmallBreasts>> <p>Your small breasts bob gently at the water's surface, the tips of your hardened nipples breaking through like little pink islands. You cup them, feeling the warm water slosh between your fingers. They fit perfectly in your palms - delicate and sensitive. You pinch your nipples, rolling them between thumb and forefinger, gasping at the electric sensations that shoot straight to your core. The bathwater makes everything slippery, sensual.</p> <<elseif _isMediumBreasts>> <p>Your shapely breasts float beautifully in the bathwater, rising and falling with your breath. The warm water laps at them as you arch your back, making the soft flesh buoyant and tempting. You take one in each hand, squeezing gently, watching the water displaced by their fullness. Your thumbs find your hardened nipples and you circle them slowly, teasingly. The dual sensation of warm water and your own touch makes you moan softly.</p> <<elseif _isLargeBreasts>> <p>Your large breasts break the surface magnificently, their considerable mass creating gentle waves as you move. The water can barely contain them - they float heavily, nipples pointing toward the ceiling like beacons of arousal. You grip them firmly, feeling the soft, pillowy flesh yield to your fingers. Water streams between them as you push them together, creating a deep, tempting cleavage. You lean forward to flick your tongue against your own nipples, tasting the bathwater on your skin.</p> <<elseif _isHugeBreasts>> <p>Your huge breasts dominate the bathwater, their extraordinary buoyancy making them float like flesh-colored balloons. They spread across the surface of the water, barely contained by the tub. Your swollen nipples jut upward, achingly sensitive. You struggle to contain even one in both hands as you massage and squeeze. The water displacement is significant every time you move them. You lift one to your mouth, latching onto your own nipple with hungry lips, suckling while the other breast bobs heavily in the waves you're creating.</p> <<elseif _isMassiveBreasts>> <p>Your massive breasts take up half the bathtub, their unbelievable size making the water level rise visibly as they float. Each one is larger than your head, soft mountains of flesh that seem to have their own gravity. Your nipples are thick and long, impossibly sensitive. Even the water lapping against them makes you shiver. You can barely reach around them to massage their incredible mass. You press your face between them, lost in their warmth and softness while the bathwater swirls around their curves. Every movement of your body makes them shift and bounce, creating waves that splash against the tub's edges.</p> <</if>> <</if>> <<if _isLargeBass>> <p>Your <<print setup.getBodyDescription("butt", _buttSize)>> spreads against the smooth bottom of the tub, providing a plush cushion. You rock your hips experimentally, feeling your generous cheeks shift against the porcelain. The buoyancy of the water makes even your substantial rear feel lighter, almost playful as you squirm in search of pleasure.</p> <</if>> <<if _hasPenis>> <<if _isSmallPenis>> <p>Beneath the warm water, you feel yourself stirring. You look down through the slightly clouded bathwater to see your compact cock at full attention, standing straight up from your body. Your hand encircles it easily, the warm water providing a unique, slippery sensation. You stroke slowly, savoring how different it feels underwater - there's resistance, but also a silky smoothness. Your tight grip works your entire length with each stroke.</p> <p>The water sloshes gently as your arm moves rhythmically beneath the surface. Your head falls back against the tub's edge as pleasure builds. Your balls tighten, and with a deep groan, you erupt beneath the water. You watch through half-lidded eyes as milky clouds bloom in the bathwater, your cock pulsing as you empty yourself completely. The warm water seems to prolong your orgasm, each throb sending new ribbons of cum swirling through the bath.</p> <<elseif _isAveragePenis>> <p>Your cock rises through the warm water like a periscope, breaking the surface slightly as it reaches full hardness. The heat of the bath has made you achingly sensitive. You grip yourself beneath the water, marveling at the unique sensation - your strokes create small currents that swirl around your balls. The water's warmth feels like a lover's embrace as you pump steadily.</p> <p>Water slaps against the sides of the tub as your movements grow more urgent. You imagine being pleasured by invisible hands, the warmth surrounding every inch of your throbbing member. Your breath comes in ragged gasps. When you cum, the sensation is incredible - the warm water seems to milk every drop from you as your cock jerks and spurts. You watch your seed cloud the water, thick ropes dissolving into milky swirls. You float in the aftermath, utterly boneless.</p> <<elseif _isBigPenis>> <p>Your substantial cock displaces water as it rises to full mast, the thick shaft breaching the surface like a sea creature. You grip it with both hands beneath the bathwater - even in this position, your impressive length demands attention. The water resistance makes every stroke feel deliberate, purposeful. Your thick head breaks the surface repeatedly as you pump, creating small splashes.</p> <p>The bathwater sloshes violently now as you work your big cock with increasing urgency. Water splashes over the tub's edges but you don't care - you're lost in sensation. Your heavy balls churn in the warmth. When your climax hits, it's like a dam breaking. Your cock erupts with force, the first jet actually shooting above the water's surface before falling back with a splash. Again and again you pulse, turning the bath cloudy with your copious release. You groan deeply, completely spent.</p> <<elseif _isHugePenis>> <p>Your enormous cock rises from the water like a leviathan, its massive length and girth impossible to ignore. The thick shaft towers over the surface, dripping water, veins pulsing visibly. You grip it with both hands and still have room to spare. Stroking something this large underwater is an experience - the water resistance makes it feel even more substantial. Your arms work to pleasure your monstrous member.</p> <p>Water crashes against the sides of the tub like stormy waves as you pump your huge cock. Your balls are so heavy they sink to the bottom, churning with building pressure. Pre-cum leaks freely into the bath. When you finally explode, it's almost violent - massive jets of thick cum rocket from your engorged head, some shooting clear over the tub's edge. Your hips buck wildly, sending water everywhere. Pulse after powerful pulse empties what feels like a pint of cum into the thoroughly ruined bathwater. You collapse back, seeing stars.</p> <<elseif _isGiantPenis>> <p>Your gigantic cock rises from the bathwater like something out of a fantasy - a pillar of flesh so massive it seems almost impossible. It towers over the tub, water streaming down its incredible length. You can barely wrap your fingers around its breathtaking girth. Stroking it requires your entire arms to move, the muscles burning from the effort. The water churns chaotically around you.</p> <p>The bathroom looks like a storm hit it - water splashes everywhere as you vigorously pump your monster cock. Your inhuman endowment throbs with your heartbeat, thick as your arm and longer than your forearm. When you finally cum, it's apocalyptic. The first blast rockets across the entire bathroom, splattering against the far wall. Subsequent jets flood the tub with an obscene amount of thick seed. Your vision goes white as your entire body convulses with release. The orgasm seems to last forever, your gigantic cock pumping out what seems like gallons. When it finally subsides, you're utterly destroyed, floating in what is now more cum than bathwater.</p> <</if>> <</if>> <<if _hasVagina>> <p>The warm water laps between your thighs like a patient lover. You spread your legs, letting the heat caress your most intimate places. Your fingers drift downward through the water, finding your lips already swollen with arousal. You part them gently, gasping as the warm water rushes against your exposed clit. The sensation is uniquely delicious - wet touching wet, heat meeting heat.</p> <p>You slide two fingers inside yourself, marveling at how the water changes the sensation. You're so slick inside, so ready. Your fingers curl forward to find that perfect spot while your thumb circles your throbbing clit. The bathwater swirls with your movements as your hips begin to rock. One hand grips the tub's edge while the other works you with increasing urgency.</p> <p>Your moans echo off the tile walls as pleasure spirals higher. The water sloshes against the sides of the tub in rhythm with your grinding hips. You add a third finger, stretching yourself deliciously, pumping in and out while your palm grinds against your clit. The pressure builds and builds until you can't take anymore - your inner walls clench like a vise around your fingers as orgasm crashes through you in waves. You cry out, back arching, water splashing everywhere as your entire body quakes with release. The contractions seem to go on forever, milking your fingers as aftershocks ripple through your core.</p> <</if>> <<if _hasBoth>> <p>With both sets of equipment aching for attention, you have the unique pleasure of dual stimulation. One hand wraps around your stiff cock beneath the water while the other slips between your thighs to find your dripping pussy. The sensation of pleasuring both at once is almost too much to handle.</p> <p>You stroke your cock while fingering yourself, the dual sensations bouncing back and forth until you can't tell where one pleasure ends and another begins. The bathwater churns violently as your movements grow frantic. Your cock pulses in your grip while your inner walls squeeze your fingers desperately. When you cum, it's a full-body explosion - your cock spurts thick ropes of cum into the water while your pussy clenches in powerful waves. The dual orgasm is so intense you actually black out for a moment, coming back to yourself floating in the cooling, cum-clouded water, utterly wrecked and blissfully satisfied.</p> <</if>> /* Futanari/Hermaphrodite bathtub-specific flavor */ <<if setup.getFutaVariant() && _hasBoth>> <<if setup.getFutaVariant() === "futanari">> <p>Your cum clouds the warm bathwater as your cock softens beneath the surface, still twitching with aftershocks. Between your spread thighs, your pussy continues to pulse in slow, satisfied contractions, sending tiny ripples across the water. Your breasts float lazily at the surface, nipples still hard, the warmth of the bath soothing both sets of spent, tingling genitals at once. <<print setup.getFutaFlavorText("masturbation_climax")>></p> <<else>> <p>The bathwater is thoroughly ruined — milky with your release as your softening cock sinks below the surface. Your pussy still clenches in lazy aftershocks between your powerful thighs, each contraction sending a faint tremor through the clouded water. The warmth soaks into both sets of spent anatomy, the dual satisfaction leaving you utterly boneless. <<print setup.getFutaFlavorText("masturbation_climax")>></p> <</if>> <</if>> <p>You float in the now-cooling water, every muscle in your body completely relaxed. A satisfied smile plays across your lips as you soak in the afterglow. Eventually, you'll have to get out and drain this bath... but for now, you simply exist in a state of pure, post-orgasmic bliss.</p> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin: 20px 0;"> <p style="color: #ffd700; font-size: 16px; margin: 0;">★ Ultimate relaxation achieved</p> <p style="color: #51cf66; font-size: 16px; margin: 5px 0 0 0;">✓ Feeling blissfully satisfied</p> <p style="color: #667eea; font-size: 16px; margin: 5px 0 0 0;">✓ Squeaky clean</p> <<if setup.getFutaVariant() && _hasBoth>> <p style="color: #e040fb; font-size: 16px; margin: 5px 0 0 0;">★ Dual anatomy made it twice as good</p> <</if>> </div> <<set $hygiene = Math.min(100, $hygiene + 50)>> <<set $relaxation = Math.min(100, $relaxation + 30)>> <<set $masturbationStats.timesTotal++>> <<run advanceTime(45)>> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer; display: inline-block;'>Reluctantly get out</div>">> <<goto `setup.getCurrentBathroom()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set $lastLocation = "HomeDecorManager">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #667eea; text-align: center;">🏠 Home Decoration Manager</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #5a67d8 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Arrange your purchased decorations and customize your space. </p> </div> <!-- Room-by-Room Decor --> <h3 style="color: #51cf66;">📦 Placed Decorations by Room</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<for _roomName, _items range $homeDecor[_home]>> <<if _roomName !== "wallColor" && _roomName !== "roomColors" && Array.isArray(_items)>> <div style="border: 3px solid #51cf66; border-radius: 10px; background: #2a2a2a; padding: 20px;"> <h4 style="color: #51cf66; margin: 0 0 15px 0; text-transform: capitalize;"><<print _roomName.replace(/([A-Z])/g, " $1").trim()>></h4> <<if _items.length > 0>> <<for _i, _itemId range _items>> <<set _itemData = setup.getDecorItem(_itemId)>> <<if _itemData>> <div style="background: #1a1a1a; padding: 10px; border-radius: 5px; margin: 5px 0; display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ccc;"><<print _itemData.name>></span> <<capture _i, _roomName>> <<link "<span style='color: #ff6b6b; cursor: pointer;'>Remove</span>">> <<run $homeDecor[_home][_roomName].splice(_i, 1)>> <<goto "HomeDecorManager">> <</link>> <</capture>> </div> <</if>> <</for>> <<else>> <p style="color: #888; margin: 0;">No decorations placed</p> <</if>> </div> <</if>> <</for>> </div> <!-- Paintings Section --> <h3 style="color: #9b59b6; margin-top: 25px;">🖼️ Wall Paintings</h3> <<if $playerPaintings && $playerPaintings.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: #888; font-size: 12px; margin: 0 0 15px 0;">Click a painting to hang it in one of your rooms.</p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px;"> <<for _i, _painting range $playerPaintings>> <<set _hungRoom = setup.roomPaintings.isHung(_painting.id)>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid <<if _hungRoom>>#51cf66<<else>>#9b59b6<</if>>; text-align: center;"> <<if setup.paintingStorage.getImage(_painting)>> <img @src="setup.paintingStorage.getImage(_painting)" class="painting-thumbnail" alt="Painting"> <<else>> <div style="font-size: 48px; margin-bottom: 10px;">🎨</div> <</if>> <p style="color: #9b59b6; font-weight: bold; margin: 10px 0 5px 0;"><<print _painting.title>></p> <<if _painting.isPreset>> <p style="color: #ffd700; font-size: 10px; margin: 0;">⭐ Preset Artwork</p> <<else>> <p style="color: #666; font-size: 11px; margin: 0;">Day <<print _painting.createdDay>></p> <</if>> <<if _hungRoom>> <p class="painting-hung-badge">🖼️ Hung</p> <</if>> <<capture _painting>> <<link "<button class='painting-select-btn'><<if _hungRoom>>Move / Remove<<else>>Hang in Room<</if>></button>">> <<set $selectedPaintingForHanging = _painting>> <<goto "DecorHangPainting">> <</link>> <</capture>> </div> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: #888; margin: 0;">You don't have any paintings yet. Create some in your Art Studio!</p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Return to Home</div>">> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set _rooms = Object.keys($homeDecor[_home].roomColors)>> <<if !$tempSelectedRoom || _rooms.indexOf($tempSelectedRoom) === -1>> <<set $tempSelectedRoom = _rooms[0]>> <</if>> <<set _currentRoomColor = $homeDecor[_home].roomColors[$tempSelectedRoom] || "#2a2a2a">> <<if !$tempSelectedColor>> <<set $tempSelectedColor = _currentRoomColor>> <</if>> <<set $lastLocation = "WallColorPicker">> <<set _selectedRoomDisplay = $tempSelectedRoom.replace(/([A-Z])/g, " $1").trim()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button Top --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Return to Home</div>">> <<unset $tempSelectedRoom>> <<unset $tempSelectedColor>> <<goto `setup.getCurrentHome()`>> <</link>> </div> <!-- Header --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px; text-align: center;"> <h2 style="color: #667eea; margin: 0 0 10px 0;">🎨 Room Painter</h2> <p style="color: #51cf66; font-size: 18px; margin: 0;">💵 Balance: $<<print $money>></p> <p style="color: #ffd700; font-size: 14px; margin: 5px 0 0 0;">Cost: $50 per room</p> </div> <!-- Room Selector --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #4dabf7; margin: 0 0 15px 0;">Select Room to Paint</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _room range _rooms>> <<set _roomColor = $homeDecor[_home].roomColors[_room] || '#2a2a2a'>> <<set _isSelected = $tempSelectedRoom === _room>> <<set _roomDisplay = _room.replace(/([A-Z])/g, " $1").trim()>> <<set _borderColor = _isSelected ? '#667eea' : '#333'>> <<set _textColor = _isSelected ? '#667eea' : '#ccc'>> <<set _fontWeight = _isSelected ? 'bold' : 'normal'>> <<capture _room, _roomDisplay, _isSelected, _roomColor, _borderColor, _textColor, _fontWeight>> <div @style="'background-color: #1a1a1a; padding: 12px 16px; border-radius: 8px; border: 2px solid ' + _borderColor + '; cursor: pointer; display: flex; align-items: center; gap: 10px;'" @data-room-btn="_room"> <div @style="'width: 28px; height: 28px; border-radius: 6px; border: 2px solid #555; background-color: ' + _roomColor + ';'" @data-room-swatch="_room"></div> <span @style="'color: ' + _textColor + '; font-weight: ' + _fontWeight + '; text-transform: capitalize;'"><<print _roomDisplay>></span> </div> <</capture>> <</for>> </div> </div> <!-- Color Picker Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">Choose Color</h3> <div style="display: flex; align-items: flex-end; gap: 20px; flex-wrap: wrap; margin-bottom: 20px;"> <!-- HTML5 Color Picker --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <label style="color: #888; display: block; margin-bottom: 8px; font-size: 12px;">COLOR PICKER</label> <input type="color" id="wall-color-picker" @value="$tempSelectedColor || '#2a2a2a'" style="width: 80px; height: 50px; border: 2px solid #555; cursor: pointer; border-radius: 6px;"> </div> <!-- Hex Input --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <label style="color: #888; display: block; margin-bottom: 8px; font-size: 12px;">HEX CODE</label> <input type="text" id="hex-input" @value="$tempSelectedColor || '#2a2a2a'" maxlength="7" style="width: 100px; padding: 12px; font-size: 16px; background: #2a2a2a; color: #fff; border: 2px solid #555; border-radius: 6px; font-family: monospace;"> </div> <!-- Preview --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <label style="color: #888; display: block; margin-bottom: 8px; font-size: 12px;">PREVIEW</label> <<set _previewColor = $tempSelectedColor || '#2a2a2a'>> <div id="color-preview" @style="'width: 80px; height: 50px; border-radius: 6px; border: 2px solid #555; background-color: ' + _previewColor + ';'"></div> </div> </div> <!-- Apply Button --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <p style="color: #ccc; margin: 0 0 10px 0;">Painting: <span style="color: #667eea; font-weight: bold; text-transform: capitalize;"><<print _selectedRoomDisplay>></span></p> <<if $money >= 50>> <<link "Paint Room - $50">> <<set $money -= 50>> <<set $homeDecor[_home].roomColors[$tempSelectedRoom] = $tempSelectedColor>> <<goto "WallColorPicker">> <</link>> <<else>> <span style="color: #ff6b6b;">Cannot Afford ($50 needed)</span> <</if>> </div> </div> <!-- Saved Colors Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #ffd43b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #ffd43b; margin: 0 0 15px 0;">Saved Colors</h3> <<if $savedWallColors.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 15px;"> <<for _i, _savedColor range $savedWallColors>> <<capture _i, _savedColor>> <div style="background-color: #1a1a1a; padding: 10px; border-radius: 8px; border: 1px solid #333; display: flex; flex-direction: column; align-items: center; gap: 8px;"> <div @style="'width: 50px; height: 50px; border-radius: 8px; border: 2px solid #555; cursor: pointer; background-color: ' + _savedColor + ';'" @data-saved-color="_savedColor"></div> <span style="color: #888; font-size: 10px; font-family: monospace;"><<print _savedColor>></span> <<link "Remove">> <<set $savedWallColors.splice(_i, 1)>> <<goto "WallColorPicker">> <</link>> </div> <</capture>> <</for>> </div> <<else>> <p style="color: #888; margin: 0 0 15px 0;">No saved colors yet. Save colors you like for quick access!</p> <</if>> <!-- Save Current Color Button --> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; display: inline-block;"> <<if $savedWallColors.indexOf($tempSelectedColor) === -1>> <<link "Save Current Color">> <<set $savedWallColors.push($tempSelectedColor)>> <<goto "WallColorPicker">> <</link>> <<else>> <span style="color: #888;">Color already saved</span> <</if>> </div> </div> <!-- Quick Preset Colors --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">Quick Presets</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _colorName, _colorHex range setup.wallColors>> <<capture _colorName, _colorHex>> <div style="background-color: #1a1a1a; padding: 10px 14px; border-radius: 8px; border: 1px solid #333; cursor: pointer; display: flex; align-items: center; gap: 10px;" @data-preset-btn="_colorHex"> <div @style="'width: 24px; height: 24px; border-radius: 6px; border: 2px solid #555; background-color: ' + _colorHex + ';'" @data-preset-color="_colorHex"></div> <span style="color: #ccc; font-size: 13px;"><<print _colorName>></span> </div> <</capture>> <</for>> </div> </div> <!-- Back Button Bottom --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Return to Home</div>">> <<unset $tempSelectedRoom>> <<unset $tempSelectedColor>> <<goto `setup.getCurrentHome()`>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set $lastLocation = "MallCoralFurnishings">> <div style="background: linear-gradient(135deg, #2a2a2a 0%, #1a3a2a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center;">🪴 Coral Furnishings</h1> <div style="padding: 10px; background: #1a1a1a; border-radius: 8px; margin-bottom: 15px; text-align: center;"> <p style="color: #90caf9; font-size: 14px; margin: 0;">Mall Floor 2 - Basic Home Goods</p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #51cf66; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<for _item range setup.decorItems.basic>> <<set _owned = setup.hasDecorItem(_item.id)>> <<set _canAfford = $money >= _item.price>> <<set _hasCompatibleRoom = _item.room.some(function(r) { return $homeDecor[_home][r] !== undefined; })>> <div style="border: 3px solid <<if _owned>>#ffd700<<elseif _canAfford && _hasCompatibleRoom>>#51cf66<<else>>#666<</if>>; border-radius: 10px; background: #2a2a2a; padding: 20px;"> <h4 style="color: <<if _owned>>#ffd700<<else>>#51cf66<</if>>; margin: 0 0 10px 0;"><<print _item.name>></h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;"><<print _item.desc>></p> <p style="color: <<if _canAfford>>#51cf66<<else>>#ff6b6b<</if>>; font-weight: bold; margin: 0 0 5px 0;">$<<print _item.price>></p> <p style="color: #888; font-size: 12px; margin: 0 0 15px 0;">Fits: <<print _item.room.join(", ")>></p> <<if _owned>> <span style="color: #ffd700;">✓ Owned</span> <<elseif !_hasCompatibleRoom>> <span style="color: #888;">No compatible room</span> <<elseif _canAfford>> <<capture _item>> <<link "<div style='background: #51cf66; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase</div>">> <<set $money -= _item.price>> <<set _targetRoom = _item.room.find(function(r) { return $homeDecor[_home][r] !== undefined; })>> <<run setup.addDecorToRoom(_item.id, _targetRoom)>> <<goto "MallCoralFurnishings">> <</link>> <</capture>> <<else>> <span style="color: #666;">Cannot afford</span> <</if>> </div> <</for>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Mall Floor 2</div>">> <<goto "MallFloor2">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set $lastLocation = "GoldenSeahorseDecor">> <div style="background: linear-gradient(135deg, #2a2a2a 0%, #3a2a1a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">✨ The Golden Seahorse</h1> <div style="padding: 10px; background: #1a1a1a; border-radius: 8px; margin-bottom: 15px; text-align: center;"> <p style="color: #90caf9; font-size: 14px; margin: 0;">Commercial District - Premium Furniture</p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #51cf66; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <<if _home === "StudioApartment">> <div style="background: #4a3000; border: 2px solid #ffd700; border-radius: 8px; padding: 15px; margin-bottom: 20px;"> <p style="color: #ffd700; margin: 0;">⚠️ Many premium items require a larger home. Consider upgrading from your studio apartment!</p> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<for _item range setup.decorItems.premium>> <<set _owned = setup.hasDecorItem(_item.id)>> <<set _canAfford = $money >= _item.price>> <<set _hasCompatibleRoom = _item.room.some(function(r) { return $homeDecor[_home][r] !== undefined; })>> <div style="border: 3px solid <<if _owned>>#ffd700<<elseif _canAfford && _hasCompatibleRoom>>#51cf66<<else>>#666<</if>>; border-radius: 10px; background: #2a2a2a; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h4 style="color: #ffd700; margin: 0 0 10px 0;"><<print _item.name>></h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;"><<print _item.desc>></p> <p style="color: <<if _canAfford>>#51cf66<<else>>#ff6b6b<</if>>; font-weight: bold; margin: 0 0 5px 0;">$<<print _item.price>></p> <p style="color: #888; font-size: 12px; margin: 0 0 15px 0;">Fits: <<print _item.room.join(", ")>></p> <<if _owned>> <span style="color: #ffd700;">✓ Owned</span> <<elseif !_hasCompatibleRoom>> <span style="color: #ff6b6b;">Requires larger home</span> <<elseif _canAfford>> <<capture _item>> <<set _purchaseLabel = "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase ($" + _item.price + ")</div>">> <<link _purchaseLabel>> <<set $money -= _item.price>> <<set _targetRoom = _item.room.find(function(r) { return $homeDecor[_home][r] !== undefined; })>> <<run setup.addDecorToRoom(_item.id, _targetRoom)>> <<goto "GoldenSeahorseDecor">> <</link>> <</capture>> <<else>> <span style="color: #666;">Cannot afford</span> <</if>> </div> <</for>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Leave Store</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set $lastLocation = "AquariumGiftShopDecor">> <div style="background: linear-gradient(135deg, #0a1628 0%, #1a3a5c 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🐠 Aquarium Gift Shop - Home Decor</h1> <div style="padding: 10px; background: #1a1a1a; border-radius: 8px; margin-bottom: 15px; text-align: center;"> <p style="color: #90caf9; font-size: 14px; margin: 0;">Ocean-themed decor and souvenirs</p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #51cf66; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<for _item range setup.decorItems.aquarium>> <<set _owned = setup.hasDecorItem(_item.id)>> <<set _canAfford = $money >= _item.price>> <<set _hasCompatibleRoom = _item.room.some(function(r) { return $homeDecor[_home][r] !== undefined; })>> <div style="border: 3px solid <<if _owned>>#ffd700<<elseif _canAfford>>#1e90ff<<else>>#666<</if>>; border-radius: 10px; background: #2a2a2a; padding: 20px;"> <h4 style="color: #1e90ff; margin: 0 0 10px 0;"><<print _item.name>></h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;"><<print _item.desc>></p> <p style="color: <<if _canAfford>>#51cf66<<else>>#ff6b6b<</if>>; font-weight: bold; margin: 0 0 5px 0;">$<<print _item.price>></p> <p style="color: #888; font-size: 12px; margin: 0 0 10px 0;">Fits: <<print _item.room.join(", ")>></p> <<if _item.room.includes("aquariumRoom") && _home !== "PlayerModernMansion">> <p style="color: #ffd700; font-size: 12px; margin: 0 0 15px 0;">★ Perfect for mansion aquarium room!</p> <</if>> <<if _owned>> <span style="color: #ffd700;">✓ Owned</span> <<elseif !_hasCompatibleRoom>> <span style="color: #888;">No compatible room in current home</span> <<elseif _canAfford>> <<capture _item>> <<link "<div style='background: #1e90ff; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase</div>">> <<set $money -= _item.price>> <<set _targetRoom = _item.room.find(function(r) { return $homeDecor[_home][r] !== undefined; })>> <<run setup.addDecorToRoom(_item.id, _targetRoom)>> <<goto "AquariumGiftShopDecor">> <</link>> <</capture>> <<else>> <span style="color: #666;">Cannot afford</span> <</if>> </div> <</for>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if $houseLocation !== "ResidentialMansions">> <p style="color: #ff6b6b;">You don't have access to this location.</p> <<link "Go back">><<goto "previousPassage">><</link>> <<else>> <<set _decor = setup.getDecorForRoom("aquariumRoom")>> <<set _currentLevel = $mansionAquarium.capacityLevel || 1>> <<set _capacityData = setup.aquariumCapacityUpgrades.find(function(u) { return u.level === _currentLevel; })>> <<set _capacity = _capacityData ? _capacityData.capacity : 10>> <<set $lastLocation = "PlayerMansionAquarium">> <div style="background: linear-gradient(180deg, #0a1628 0%, #1a3a5c 50%, #0a1628 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🐠 Mansion Aquarium</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #0d6efd 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Your personal aquarium stretches across the wall, a mesmerizing window into an underwater world. </p> </div> <!-- Aquarium Stats --> <div style="display: flex; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center;"> <div style="background: #1a1a1a; padding: 15px 25px; border-radius: 8px;"> <span style="color: #1e90ff;">🐟 Fish:</span> <span style="color: #51cf66;"><<print $mansionAquarium.fish.length>> / <<print _capacity>></span> </div> <div style="background: #1a1a1a; padding: 15px 25px; border-radius: 8px;"> <span style="color: #1e90ff;">🏷️ Tank Level:</span> <span style="color: #ffd700;"><<print _currentLevel>></span> </div> </div> <!-- Fish Tank Display --> <style> .swimming-fish { position: absolute; transition: left 3s ease-in-out, top 2.5s ease-in-out, transform 0.3s ease; cursor: pointer; } .swimming-fish:hover { transform: scale(1.1); } .swimming-fish:hover .fish-tooltip { opacity: 1; visibility: visible; } .fish-tooltip { position: absolute; bottom: 100%; left: 50%; transform: translateX(-50%); background: rgba(0,0,0,0.9); padding: 8px 12px; border-radius: 6px; white-space: nowrap; opacity: 0; visibility: hidden; transition: opacity 0.2s; z-index: 10; pointer-events: none; } .pellet { position: absolute; width: 12px; height: 12px; background: radial-gradient(circle, #8B4513 0%, #654321 100%); border-radius: 50%; z-index: 5; transition: top 2s ease-in; box-shadow: 0 2px 4px rgba(0,0,0,0.4); } </style> <div id="aquarium-tank" style="background: linear-gradient(180deg, #0d47a1 0%, #1565c0 30%, #0d47a1 100%); border-radius: 15px; padding: 30px; min-height: 300px; position: relative; overflow: hidden; margin-bottom: 25px; border: 3px solid #1e90ff;"> <<if $mansionAquarium.fish.length === 0>> <p style="text-align: center; color: #90caf9; padding-top: 100px; font-size: 18px;">The tank is empty. Transfer some fish from your inventory!</p> <<else>> <<set _fishIndex = 0>> <<for _fish range $mansionAquarium.fish>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <<set _startLeft = Math.random() * 75>> <<set _startTop = Math.random() * 60 + 10>> <div class="swimming-fish" style="left: <<print _startLeft>>%; top: <<print _startTop>>%;"> <div class="fish-tooltip"> <span style="color: <<print _rarityColor>>; font-weight: bold;"><<print _fish.name>></span> <br><span style="color: #90caf9; font-size: 11px; text-transform: capitalize;"><<print _fish.rarity>></span> </div> <<if _fish.icon>><img @src="_fish.icon" style="width: 64px; height: 64px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 48px;">🐟</span><<else>><span style="font-size: 48px;">🐟</span><</if>> </div> <<set _fishIndex++>> <</for>> <</if>> </div> <<if $mansionAquarium.fish.length > 0>> <<run setTimeout(function() { var fish = document.querySelectorAll('.swimming-fish'); function moveFish() { fish.forEach(function(f) { f.style.left = (Math.random() * 75) + '%'; f.style.top = (Math.random() * 60 + 10) + '%'; }); } moveFish(); setInterval(moveFish, 3500); }, 100)>> <</if>> <!-- Actions --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Transfer Fish --> <div style="border: 3px solid #51cf66; border-radius: 10px; background: #2a2a2a; padding: 20px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🐟 Manage Fish</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">Add or remove fish from your aquarium.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Manage Fish</div>">> <<goto "AquariumFishTransfer">> <</link>> </div> <!-- Upgrade Capacity --> <div style="border: 3px solid #667eea; border-radius: 10px; background: #2a2a2a; padding: 20px;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">📈 Upgrade Tank</h3> <<set _nextUpgrade = setup.aquariumCapacityUpgrades.find(function(u) { return u.level === _currentLevel + 1; })>> <<if _nextUpgrade>> <p style="color: #ccc; font-size: 14px; margin: 0 0 10px 0;">Expand to <<print _nextUpgrade.capacity>> fish capacity.</p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 15px 0;">Cost: $<<print _nextUpgrade.cost>></p> <<if $money >= _nextUpgrade.cost>> <<capture _nextUpgrade>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Upgrade ($<<print _nextUpgrade.cost>>)</div>">> <<set $money -= _nextUpgrade.cost>> <<set $mansionAquarium.capacityLevel = _nextUpgrade.level>> <<goto "PlayerMansionAquarium">> <</link>> <</capture>> <<else>> <p style="color: #ff6b6b;">Cannot afford</p> <</if>> <<else>> <p style="color: #ffd700;">Maximum capacity reached!</p> <</if>> </div> </div> <!-- Room Decorations --> <<if _decor.length > 0>> <div style="border: 3px solid #1e90ff; border-radius: 10px; background: #2a2a2a; padding: 20px; margin-bottom: 20px;"> <h4 style="color: #1e90ff; margin: 0 0 10px 0;">Room Decorations:</h4> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _itemId range _decor>> <<set _itemData = setup.getDecorItem(_itemId)>> <<if _itemData>> <span style="background: #1a1a1a; padding: 8px 12px; border-radius: 5px; color: #ccc;"><<print _itemData.name>></span> <</if>> <</for>> </div> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Return to Mansion</div>">> <<goto "PlayerModernMansion">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set _currentLevel = $mansionAquarium.capacityLevel || 1>> <<set _capacityData = setup.aquariumCapacityUpgrades.find(function(u) { return u.level === _currentLevel; })>> <<set _capacity = _capacityData ? _capacityData.capacity : 10>> <<set _spotsLeft = _capacity - $mansionAquarium.fish.length>> <<set $lastLocation = "AquariumFishTransfer">> <div style="background: linear-gradient(180deg, #0a1628 0%, #1a3a5c 50%, #0a1628 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🐟 Fish Transfer</h1> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #51cf66; font-size: 18px; margin: 0;">Select fish to transfer. <span style="color: #ffd700;"><<print _spotsLeft>> spots remaining.</span></p> </div> <!-- Fish Inventory --> <h3 style="color: #51cf66;">Your Inventory (<<print $fishInventory ? $fishInventory.length : 0>> fish)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 30px;"> <<if $fishInventory && $fishInventory.length > 0>> <<for _i, _fish range $fishInventory>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <div style="border: 3px solid <<print _rarityColor>>; border-radius: 10px; background: #2a2a2a; padding: 15px; text-align: center;"> <div style="font-size: 2em;"><<if _fish.icon>><img @src="_fish.icon" style="width: 64px; height: 64px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none;">🐟</span><<else>>🐟<</if>></div> <p style="color: <<print _rarityColor>>; margin: 5px 0; font-weight: bold;"><<print _fish.name>></p> <p style="font-size: 12px; color: #888; text-transform: capitalize; margin: 0 0 10px 0;"><<print _fish.rarity>></p> <p style="font-size: 12px; color: #51cf66; margin: 0 0 10px 0;">Value: $<<print _fish.basePrice>></p> <<if _spotsLeft > 0>> <<capture _i, _fish>> <<link "<div style='background: #51cf66; color: white; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 12px;'>Add to Tank</div>">> <<run $mansionAquarium.fish.push(clone(_fish))>> <<run $fishInventory.splice(_i, 1)>> <<goto "AquariumFishTransfer">> <</link>> <</capture>> <<else>> <span style="color: #ff6b6b; font-size: 12px;">Tank full</span> <</if>> </div> <</for>> <<else>> <p style="color: #888;">No fish in your inventory.</p> <</if>> </div> <!-- Fish in Tank --> <h3 style="color: #1e90ff;">Fish in Aquarium (<<print $mansionAquarium.fish.length>>/<<print _capacity>>)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 30px;"> <<if $mansionAquarium.fish.length > 0>> <<for _i, _fish range $mansionAquarium.fish>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <div style="border: 3px solid <<print _rarityColor>>; border-radius: 10px; background: #1a3a5c; padding: 15px; text-align: center;"> <div style="font-size: 2em;"><<if _fish.icon>><img @src="_fish.icon" style="width: 64px; height: 64px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none;">🐟</span><<else>>🐟<</if>></div> <p style="color: <<print _rarityColor>>; margin: 5px 0; font-weight: bold;"><<print _fish.name>></p> <p style="font-size: 12px; color: #90caf9; text-transform: capitalize; margin: 0 0 10px 0;"><<print _fish.rarity>></p> <<capture _i, _fish>> <<link "<div style='background: #ff6b6b; color: white; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 12px;'>Remove</div>">> <<run $fishInventory.push(clone(_fish))>> <<run $mansionAquarium.fish.splice(_i, 1)>> <<goto "AquariumFishTransfer">> <</link>> <</capture>> </div> <</for>> <<else>> <p style="color: #888;">No fish in aquarium yet.</p> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>Done</div>">> <<goto "PlayerMansionAquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StudioBedroom">> <<set _home = "StudioApartment">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("StudioBedroom")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #667eea; text-align: center;">🛏️ Your Bedroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #5a6fd6 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Your cozy studio bedroom. The fold-out bed takes up most of the space, but it's home. </p> </div> <!-- Decor Display --> <<if $homeDecor[_home].bedroom && $homeDecor[_home].bedroom.length > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">Room Decorations</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _decor range $homeDecor[_home].bedroom>> <span style="background: #3a3a3a; padding: 5px 10px; border-radius: 5px; font-size: 14px;"><<print _decor.icon>> <<print _decor.name>></span> <</for>> </div> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Bun Bun Sleep Arrangement Card --> <<if setup.bunBunSleep && setup.bunBunSleep.canShowArrangement()>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #2a1a4a 0%, #1a0a28 100%); box-shadow: 0 0 15px rgba(201,169,255,0.3);"> <h3 style="color: #ff8fc8; margin: 0 0 15px 0;">🐰 <<= ($bunBunChosenName || "Bun Bun")>></h3> <<if !$bunBunSleepsHere>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">She has not started staying over yet. Ask her to.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask her to start staying over</div>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> <<else>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">Your room. Hers too, lately.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Spend the night with her</div>">> <<goto "BunBunSleepRoot">> <</link>> <div style="text-align: center; margin-top: 10px;"> <<link "<span style='color: #888; font-size: 11px; cursor: pointer;'>End the arrangement</span>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> </div> <</if>> </div> <</if>> <!-- Sleep Option --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">😴 Sleep</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Rest and recover your energy.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Go to Sleep</div>">> <<popover "rest-popover">> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; max-width: 350px;"> <h3 style="color: #51cf66; margin: 0 0 15px 0; text-align: center;">How long do you want to sleep?</h3> <div style="text-align: center; margin-bottom: 15px;"> <input type="number" id="rest-time-input" min="1" max="12" value="8" style="width: 80px; padding: 10px; font-size: 18px; text-align: center; border-radius: 5px; border: 2px solid #51cf66; background: #1a1a1a; color: white;"> <span style="color: #ccc; margin-left: 10px;">hours</span> </div> <<if $witchFormActive && $clairFirstMeetingDone>> <<if $dreamwalkEnabled>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check" checked> 💤 Dreamwalk tonight</label></p> <<else>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check"> 💤 Dreamwalk tonight</label></p> <</if>> <</if>> <p style="color: #888; font-size: 12px; text-align: center; margin-bottom: 15px;">Any amount of sleep removes exhaustion. Sleep 8+ hours for the Well Rested buff.</p> <div style="margin-top: 20px; text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; margin-right: 10px;'>Confirm</div>">> <<set _restHours = Number(jQuery("#rest-time-input").val())>> <<if _restHours < 1 || _restHours > 12 || Number.isNaN(_restHours)>> <<set _restHours = 8>> <</if>> <<if _restHours >= 8>> <<run setup.achievements.unlock("full_rest")>> <</if>> <<if !$lucidRestActive>><<run advanceTime(_restHours * 60)>><</if>> <<run setup.setHairMessy()>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.removeDebuff("exhaustion")>> <<if $witchFormActive && $clairFirstMeetingDone>><<set $dreamwalkEnabled = jQuery("#dreamwalk-check").prop("checked")>><</if>> <<set _dreamRoute = setup.witchSpells.onSleep(_restHours, "StudioBedroom")>> <<if _restHours >= 8 && setup.canEarnWellRestedBySleeping()>> <<run setup.addBuff("well_rested", 480)>><<run setup.mining && setup.mining.refillEnergy && setup.mining.refillEnergy()>> <</if>> <<run Dialog.close()>> <<if _dreamRoute>><<goto _dreamRoute>><<else>><<goto "StudioBedroom">><</if>> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Masturbate Option --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #e83e8c; margin: 0 0 15px 0;">💋 Masturbate</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Enjoy some personal relaxation.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Masturbate</div>">> <<goto "MasturbationBedroom">> <</link>> </div> <!-- Sex Toys Section --> <<if $ownsDildo || $ownsFleshlight>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">🎁 Sex Toys</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Use your toys for enhanced pleasure.</p> <<if $ownsDildo && _hasVagina>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Use Dildo</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.dildo++>> <<set $toyUsed = "dildo">> <<goto "MasturbationVaginaScene">> <</link>> <</if>> <<if $ownsFleshlight && _hasPenis>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use Fleshlight</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.fleshlight++>> <<set $toyUsed = "fleshlight">> <<goto "MasturbationPenisScene">> <</link>> <</if>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Apartment</div>">> <<goto "StudioApartment">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PlayerSuburbanBedroom">> <<set _home = "PlayerSuburbanHome">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("PlayerSuburbanBedroom")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #667eea; text-align: center;">🛏️ Master Bedroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #5a6fd6 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A comfortable suburban bedroom with a queen-sized bed and plenty of natural light from the window. </p> </div> <!-- Decor Display --> <<if $homeDecor[_home].bedroom && $homeDecor[_home].bedroom.length > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">Room Decorations</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _decor range $homeDecor[_home].bedroom>> <span style="background: #3a3a3a; padding: 5px 10px; border-radius: 5px; font-size: 14px;"><<print _decor.icon>> <<print _decor.name>></span> <</for>> </div> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Bun Bun Sleep Arrangement Card --> <<if setup.bunBunSleep && setup.bunBunSleep.canShowArrangement()>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #2a1a4a 0%, #1a0a28 100%); box-shadow: 0 0 15px rgba(201,169,255,0.3);"> <h3 style="color: #ff8fc8; margin: 0 0 15px 0;">🐰 <<= ($bunBunChosenName || "Bun Bun")>></h3> <<if !$bunBunSleepsHere>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">She has not started staying over yet. Ask her to.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask her to start staying over</div>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> <<else>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">Your room. Hers too, lately.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Spend the night with her</div>">> <<goto "BunBunSleepRoot">> <</link>> <div style="text-align: center; margin-top: 10px;"> <<link "<span style='color: #888; font-size: 11px; cursor: pointer;'>End the arrangement</span>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> </div> <</if>> </div> <</if>> <!-- Sleep Option --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">😴 Sleep</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Rest in your comfortable bed.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Go to Sleep</div>">> <<popover "rest-popover">> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; max-width: 350px;"> <h3 style="color: #51cf66; margin: 0 0 15px 0; text-align: center;">How long do you want to sleep?</h3> <div style="text-align: center; margin-bottom: 15px;"> <input type="number" id="rest-time-input" min="1" max="12" value="8" style="width: 80px; padding: 10px; font-size: 18px; text-align: center; border-radius: 5px; border: 2px solid #51cf66; background: #1a1a1a; color: white;"> <span style="color: #ccc; margin-left: 10px;">hours</span> </div> <<if $witchFormActive && $clairFirstMeetingDone>> <<if $dreamwalkEnabled>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check" checked> 💤 Dreamwalk tonight</label></p> <<else>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check"> 💤 Dreamwalk tonight</label></p> <</if>> <</if>> <p style="color: #888; font-size: 12px; text-align: center; margin-bottom: 15px;">Any amount of sleep removes exhaustion. Sleep 8+ hours for the Well Rested buff.</p> <div style="margin-top: 20px; text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; margin-right: 10px;'>Confirm</div>">> <<set _restHours = Number(jQuery("#rest-time-input").val())>> <<if _restHours < 1 || _restHours > 12 || Number.isNaN(_restHours)>> <<set _restHours = 8>> <</if>> <<if _restHours >= 8>> <<run setup.achievements.unlock("full_rest")>> <</if>> <<if !$lucidRestActive>><<run advanceTime(_restHours * 60)>><</if>> <<run setup.setHairMessy()>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.removeDebuff("exhaustion")>> <<if $witchFormActive && $clairFirstMeetingDone>><<set $dreamwalkEnabled = jQuery("#dreamwalk-check").prop("checked")>><</if>> <<set _dreamRoute = setup.witchSpells.onSleep(_restHours, "PlayerSuburbanBedroom")>> <<if _restHours >= 8 && setup.canEarnWellRestedBySleeping()>> <<run setup.addBuff("well_rested", 480)>><<run setup.mining && setup.mining.refillEnergy && setup.mining.refillEnergy()>> <</if>> <<run Dialog.close()>> <<if _dreamRoute>><<goto _dreamRoute>><<else>><<goto "PlayerSuburbanBedroom">><</if>> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Masturbate Option --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #e83e8c; margin: 0 0 15px 0;">💋 Masturbate</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Enjoy some personal relaxation.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Masturbate</div>">> <<goto "MasturbationBedroom">> <</link>> </div> <!-- Sex Toys Section --> <<if $ownsDildo || $ownsFleshlight>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">🎁 Sex Toys</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Use your toys for enhanced pleasure.</p> <<if $ownsDildo && _hasVagina>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Use Dildo</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.dildo++>> <<set $toyUsed = "dildo">> <<goto "MasturbationVaginaScene">> <</link>> <</if>> <<if $ownsFleshlight && _hasPenis>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use Fleshlight</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.fleshlight++>> <<set $toyUsed = "fleshlight">> <<goto "MasturbationPenisScene">> <</link>> <</if>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Living Room</div>">> <<goto "PlayerSuburbanHome">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PlayerExpensiveBedroom">> <<set _home = "PlayerExpensiveHome">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("PlayerExpensiveBedroom")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #ffd700; text-align: center;">🛏️ Luxury Master Suite</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700;"> <p style="color: #1a1a1a; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> An elegant master suite with a king-sized bed, walk-in closet, and stunning city views. </p> </div> <!-- Decor Display --> <<if $homeDecor[_home].bedroom && $homeDecor[_home].bedroom.length > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">Room Decorations</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _decor range $homeDecor[_home].bedroom>> <span style="background: #3a3a3a; padding: 5px 10px; border-radius: 5px; font-size: 14px;"><<print _decor.icon>> <<print _decor.name>></span> <</for>> </div> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Bun Bun Sleep Arrangement Card --> <<if setup.bunBunSleep && setup.bunBunSleep.canShowArrangement()>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #2a1a4a 0%, #1a0a28 100%); box-shadow: 0 0 15px rgba(201,169,255,0.3);"> <h3 style="color: #ff8fc8; margin: 0 0 15px 0;">🐰 <<= ($bunBunChosenName || "Bun Bun")>></h3> <<if !$bunBunSleepsHere>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">She has not started staying over yet. Ask her to.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask her to start staying over</div>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> <<else>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">Your room. Hers too, lately.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Spend the night with her</div>">> <<goto "BunBunSleepRoot">> <</link>> <div style="text-align: center; margin-top: 10px;"> <<link "<span style='color: #888; font-size: 11px; cursor: pointer;'>End the arrangement</span>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> </div> <</if>> </div> <</if>> <!-- Sleep Option --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">😴 Sleep</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Rest in your luxurious king bed.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Go to Sleep</div>">> <<popover "rest-popover">> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; max-width: 350px;"> <h3 style="color: #51cf66; margin: 0 0 15px 0; text-align: center;">How long do you want to sleep?</h3> <div style="text-align: center; margin-bottom: 15px;"> <input type="number" id="rest-time-input" min="1" max="12" value="8" style="width: 80px; padding: 10px; font-size: 18px; text-align: center; border-radius: 5px; border: 2px solid #51cf66; background: #1a1a1a; color: white;"> <span style="color: #ccc; margin-left: 10px;">hours</span> </div> <<if $witchFormActive && $clairFirstMeetingDone>> <<if $dreamwalkEnabled>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check" checked> 💤 Dreamwalk tonight</label></p> <<else>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check"> 💤 Dreamwalk tonight</label></p> <</if>> <</if>> <p style="color: #888; font-size: 12px; text-align: center; margin-bottom: 15px;">Any amount of sleep removes exhaustion. Sleep 8+ hours for the Well Rested buff.</p> <div style="margin-top: 20px; text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; margin-right: 10px;'>Confirm</div>">> <<set _restHours = Number(jQuery("#rest-time-input").val())>> <<if _restHours < 1 || _restHours > 12 || Number.isNaN(_restHours)>> <<set _restHours = 8>> <</if>> <<if _restHours >= 8>> <<run setup.achievements.unlock("full_rest")>> <</if>> <<if !$lucidRestActive>><<run advanceTime(_restHours * 60)>><</if>> <<run setup.setHairMessy()>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.removeDebuff("exhaustion")>> <<if $witchFormActive && $clairFirstMeetingDone>><<set $dreamwalkEnabled = jQuery("#dreamwalk-check").prop("checked")>><</if>> <<set _dreamRoute = setup.witchSpells.onSleep(_restHours, "PlayerExpensiveBedroom")>> <<if _restHours >= 8 && setup.canEarnWellRestedBySleeping()>> <<run setup.addBuff("well_rested", 480)>><<run setup.mining && setup.mining.refillEnergy && setup.mining.refillEnergy()>> <</if>> <<run Dialog.close()>> <<if _dreamRoute>><<goto _dreamRoute>><<else>><<goto "PlayerExpensiveBedroom">><</if>> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Masturbate Option --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #e83e8c; margin: 0 0 15px 0;">💋 Masturbate</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Enjoy some personal relaxation.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Masturbate</div>">> <<goto "MasturbationBedroom">> <</link>> </div> <!-- Sex Toys Section --> <<if $ownsDildo || $ownsFleshlight>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">🎁 Sex Toys</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Use your toys for enhanced pleasure.</p> <<if $ownsDildo && _hasVagina>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Use Dildo</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.dildo++>> <<set $toyUsed = "dildo">> <<goto "MasturbationVaginaScene">> <</link>> <</if>> <<if $ownsFleshlight && _hasPenis>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use Fleshlight</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.fleshlight++>> <<set $toyUsed = "fleshlight">> <<goto "MasturbationPenisScene">> <</link>> <</if>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Living Room</div>">> <<run advanceTime(1)>> <<goto "PlayerExpensiveHome">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PlayerMansionBedroom">> <<set _home = "PlayerModernMansion">> <<set _wallColor = $homeDecor[_home].wallColor || "#2a2a2a">> <<set _hasPenis = $bodyParts.genitals && $bodyParts.genitals.includes("penis")>> <<set _hasVagina = $bodyParts.genitals && ($bodyParts.genitals.includes("vagina") || $bodyParts.genitals === "both")>> <div id="home-wall-color" style="background: <<print _wallColor>>; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42, 42, 42, 0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("PlayerMansionBedroom")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #9D00FF; text-align: center;">🛏️ Grand Master Suite</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9D00FF 0%, #7B00CC 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9D00FF;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> The palatial master suite features a California king bed, automated blinds, and a private balcony overlooking the estate. </p> </div> <!-- Decor Display --> <<if $homeDecor[_home].masterBedroom && $homeDecor[_home].masterBedroom.length > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">Room Decorations</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _decor range $homeDecor[_home].masterBedroom>> <span style="background: #3a3a3a; padding: 5px 10px; border-radius: 5px; font-size: 14px;"><<print _decor.icon>> <<print _decor.name>></span> <</for>> </div> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Bun Bun Sleep Arrangement Card --> <<if setup.bunBunSleep && setup.bunBunSleep.canShowArrangement()>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 20px; background: linear-gradient(135deg, #2a1a4a 0%, #1a0a28 100%); box-shadow: 0 0 15px rgba(201,169,255,0.3);"> <h3 style="color: #ff8fc8; margin: 0 0 15px 0;">🐰 <<= ($bunBunChosenName || "Bun Bun")>></h3> <<if !$bunBunSleepsHere>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">She has not started staying over yet. Ask her to.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask her to start staying over</div>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> <<else>> <p style="color: #d4c4f0; font-size: 14px; margin-bottom: 15px;">Your room. Hers too, lately.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Spend the night with her</div>">> <<goto "BunBunSleepRoot">> <</link>> <div style="text-align: center; margin-top: 10px;"> <<link "<span style='color: #888; font-size: 11px; cursor: pointer;'>End the arrangement</span>">> <<run setup.bunBunSleep.toggleArrangement()>> <<set _bbReturn = passage()>><<goto _bbReturn>> <</link>> </div> <</if>> </div> <</if>> <!-- Sleep Option --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">😴 Sleep</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Rest in absolute luxury.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Go to Sleep</div>">> <<popover "rest-popover">> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; max-width: 350px;"> <h3 style="color: #51cf66; margin: 0 0 15px 0; text-align: center;">How long do you want to sleep?</h3> <div style="text-align: center; margin-bottom: 15px;"> <input type="number" id="rest-time-input" min="1" max="12" value="8" style="width: 80px; padding: 10px; font-size: 18px; text-align: center; border-radius: 5px; border: 2px solid #51cf66; background: #1a1a1a; color: white;"> <span style="color: #ccc; margin-left: 10px;">hours</span> </div> <<if $witchFormActive && $clairFirstMeetingDone>> <<if $dreamwalkEnabled>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check" checked> 💤 Dreamwalk tonight</label></p> <<else>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check"> 💤 Dreamwalk tonight</label></p> <</if>> <</if>> <p style="color: #888; font-size: 12px; text-align: center; margin-bottom: 15px;">Any amount of sleep removes exhaustion. Sleep 8+ hours for the Well Rested buff.</p> <div style="margin-top: 20px; text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; margin-right: 10px;'>Confirm</div>">> <<set _restHours = Number(jQuery("#rest-time-input").val())>> <<if _restHours < 1 || _restHours > 12 || Number.isNaN(_restHours)>> <<set _restHours = 8>> <</if>> <<if _restHours >= 8>> <<run setup.achievements.unlock("full_rest")>> <</if>> <<if !$lucidRestActive>><<run advanceTime(_restHours * 60)>><</if>> <<run setup.setHairMessy()>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.removeDebuff("exhaustion")>> <<if $witchFormActive && $clairFirstMeetingDone>><<set $dreamwalkEnabled = jQuery("#dreamwalk-check").prop("checked")>><</if>> <<set _dreamRoute = setup.witchSpells.onSleep(_restHours, "PlayerMansionBedroom")>> <<if _restHours >= 8 && setup.canEarnWellRestedBySleeping()>> <<run setup.addBuff("well_rested", 480)>><<run setup.mining && setup.mining.refillEnergy && setup.mining.refillEnergy()>> <</if>> <<run Dialog.close()>> <<if _dreamRoute>><<goto _dreamRoute>><<else>><<goto "PlayerMansionBedroom">><</if>> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Masturbate Option --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #e83e8c; margin: 0 0 15px 0;">💋 Masturbate</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Enjoy some personal relaxation.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Masturbate</div>">> <<goto "MasturbationBedroom">> <</link>> </div> <!-- Sex Toys Section --> <<if $ownsDildo || $ownsFleshlight>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">🎁 Sex Toys</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Use your toys for enhanced pleasure.</p> <<if $ownsDildo && _hasVagina>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px;'>Use Dildo</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.dildo++>> <<set $toyUsed = "dildo">> <<goto "MasturbationVaginaScene">> <</link>> <</if>> <<if $ownsFleshlight && _hasPenis>> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #f0c000 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use Fleshlight</div>">> <<set $masturbationStats.timesTotal++>> <<set $masturbationStats.toysUsed.fleshlight++>> <<set $toyUsed = "fleshlight">> <<goto "MasturbationPenisScene">> <</link>> <</if>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Great Hall</div>">> <<run advanceTime(1)>> <<goto "PlayerModernMansion">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MirrorView">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <<if $possessionActive>> <h1 style="color: #c9a9ff; text-align: center;">🪞 Roisin in the Mirror</h1> <div style="padding: 20px; background: linear-gradient(135deg, #c9a9ff 0%, #6e4ea8 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #c9a9ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> You catch Roisin's reflection in the glass... </p> </div> <div style="background: linear-gradient(135deg, #1a0a28 0%, #2a1a3e 100%); padding: 22px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #6e4ea8; box-shadow: 0 0 22px rgba(201,169,255,0.25);"> <p style="color: #ddd; font-size: 16px; line-height: 1.8; margin: 0 0 14px 0;">Roisin Sullivan is staring back at you from the glass. Ginger ponytail high on her crown. Police cap shading her brow. Tape wrap straining over her chest. The carved line of her abs above the open button of her shorts. The fingerless gloves still cinched at her knuckles. The artifact glints once at her wrist and her reflection winks back at you on its own.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; font-size: 16px; margin: 14px 0;">"Christ. Hello, gorgeous."</p> <p style="color: #ddd; font-size: 16px; line-height: 1.8; margin: 14px 0;">You roll her shoulders. Her tits roll with them. You turn her hips and the denim pulls tight across the swell of her ass. You tilt her chin and her smirk arrives without you asking, easy and crooked and made for a fight.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; font-size: 16px; margin: 14px 0;">"Look at the work she has put into you. All those mornings on the heavy bag. All those squats. All for me to live in for an afternoon."</p> <p style="color: #ddd; font-size: 16px; line-height: 1.8; margin: 14px 0;">Heat slides down her stomach as you watch yourself. The reflection's nipples push at the wrap. The reflection's thighs press together once, slow and deliberate. The reflection's eyes drag up the line of her own body and meet yours and the look in them is unmistakable. She wants her.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; font-size: 16px; margin: 14px 0;">"Aye, Roisin. You and me are going to have a very good day."</p> </div> <<else>> <h1 style="color: #f39c12; text-align: center;">🪞 Looking in the Mirror</h1> <div style="padding: 20px; background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f39c12;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> You gaze at your reflection... </p> </div> <</if>> <!-- Description Box --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f39c12; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<set _genderWord = "">> <<set _pronounNoun = "">> <<if $bodyParts.gender === "female">> <<set _genderWord = "feminine">> <<set _pronounNoun = "woman">> <<elseif $bodyParts.gender === "male">> <<set _genderWord = "masculine">> <<set _pronounNoun = "man">> <<else>> <<set _genderWord = "androgynous">> <<set _pronounNoun = "person">> <</if>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You look and see a <<print _genderWord>> <<print _pronounNoun>> staring back at you in the mirror. <<if $appearance.age === "Mature Adult">> Your face shows the marks of experience, mature and distinguished. <<else>> Your youthful features are still unburdened by the weight of years. <</if>> Your <<print $appearance.skinTone>> skin <<if $appearance.skinTone === "pale">>has a porcelain quality<<elseif $appearance.skinTone === "tan">>has a warm, sun-kissed glow<<elseif $appearance.skinTone === "dark">>has a rich, deep tone<<else>>looks healthy<</if>>, and your <<print $appearance.hairLength>> <<print $appearance.hairColor.toLowerCase()>> hair <<if $physicalTraits && $physicalTraits.includes("Ojou")>>is wound into the long golden drill curls her family knew her by<<elseif $appearance.hairStyle === "messy">>falls in an untamed cascade<<else>>is neatly styled<</if>>. </p> <<set _chestDescription = "">> <<if $bodyParts.chest === "flat masculine">> <<set _chestDescription = "Your chest is flat and masculine, with defined pectorals.">> <<elseif $bodyParts.chest === "flat">> <<set _chestDescription = "Your chest is flat, with only the slightest hint of femininity.">> <<elseif $bodyParts.chest === "small">> <<set _chestDescription = "You have small, perky breasts that sit high on your chest.">> <<elseif $bodyParts.chest === "medium">> <<set _chestDescription = "You have medium-sized breasts with a pleasant, natural shape.">> <<elseif $bodyParts.chest === "large">> <<set _chestDescription = "Your large breasts are impossible to ignore, straining against any top you wear.">> <<elseif $bodyParts.chest === "huge">> <<set _chestDescription = "Your huge breasts are gravity-defying, drawing eyes wherever you go.">> <<elseif $bodyParts.chest === "giant">> <<set _chestDescription = "Your giant breasts are almost absurdly large, dominating your silhouette.">> <<elseif $bodyParts.chest === "gigantic">> <<set _chestDescription = "Your gigantic breasts are beyond belief, each one larger than your head.">> <<else>> <<set _chestDescription = "You examine your chest in the mirror.">> <</if>> <<set _buttDescription = "">> <<if $bodyParts.butt === "flat">> <<set _buttDescription = "Your backside is flat and unremarkable.">> <<elseif $bodyParts.butt === "small">> <<set _buttDescription = "You have a small, tight rear.">> <<elseif $bodyParts.butt === "medium">> <<set _buttDescription = "Your butt has a nice, rounded shape.">> <<elseif $bodyParts.butt === "large">> <<set _buttDescription = "Your large butt curves outward noticeably, filling out any pants you wear.">> <<elseif $bodyParts.butt === "huge">> <<set _buttDescription = "Your huge butt jiggles with every step, impossible to hide.">> <<elseif $bodyParts.butt === "giant">> <<set _buttDescription = "Your giant butt is almost comically large, a shelf you could balance things on.">> <<elseif $bodyParts.butt === "gigantic">> <<set _buttDescription = "Your gigantic butt is truly massive, each cheek bigger than a watermelon.">> <<else>> <<set _buttDescription = "You turn to examine your backside.">> <</if>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<print _chestDescription>> <<print _buttDescription>> </p> <<set _genitalsDescription = "">> <<if $bodyParts.genitals === "vagina">> <<set _genitalsDescription = "Between your legs, you have female anatomy.">> <<elseif $bodyParts.genitals === "penis">> <<set _genitalsDescription = "Between your legs, you have male anatomy.">> <<elseif $bodyParts.genitals === "both">> <<set _genitalsDescription = "Between your legs, you have both male and female anatomy.">> <</if>> <<if _genitalsDescription !== "">> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<print _genitalsDescription>> </p> <</if>> <!-- Physical Traits Summary --> <<if $physicalTraits && $physicalTraits.length > 0>> <<set _physTraitDisplay = $physicalTraits.filter(function(t) { return t !== "Short Hair" && t !== "Long Hair"; })>> <<if _physTraitDisplay.length > 0>> <p style="color: #aaa; font-size: 14px; line-height: 1.6; margin: 0; font-style: italic;"> Your body could be described as: <<print _physTraitDisplay.join(", ").toLowerCase()>>. </p> <</if>> <</if>> <!-- Refinement hint: vague reflection-based clue about the player's hidden refinement progress. Only shows before the Ojou trait is gained. --> <<if !($physicalTraits && $physicalTraits.includes("Ojou")) && ($ojou_refinementLifetime || 0) > 0>> <<set _refLife = $ojou_refinementLifetime || 0>> <p style="color: #c9a0dc; font-size: 14px; line-height: 1.6; margin: 12px 0 0 0; font-style: italic; border-top: 1px dashed #6a0dad; padding-top: 12px;"> <<if _refLife >= 16>>You look every inch a person of breeding now. Your reflection meets your own gaze with the still composure of someone who has been admired in better rooms than this one.<<elseif _refLife >= 11>>There is a distinct refinement to the way you carry yourself in the glass. Your chin sits a little higher than it used to, your shoulders set themselves without you asking.<<elseif _refLife >= 6>>Your posture has shifted. The set of your shoulders feels more deliberate, the line of your throat more poised than the last time you looked.<<else>>You catch a hint of poise in your reflection that was not there before. Whatever you have been doing with your afternoons is leaving a mark.<</if>> </p> <</if>> </div> <!-- Image Display Section --> <<if $possessionActive>> <h2 style="color: #c9a9ff; text-align: center;">Her Reflection</h2> <div style="display: flex; justify-content: center; margin-bottom: 25px;"> <div style="border: 3px solid #c9a9ff; border-radius: 12px; padding: 18px; background: #1a0a28; box-shadow: 0 0 24px rgba(201,169,255,0.35); max-width: 480px;"> <h3 style="color: #c9a9ff; margin: 0 0 12px 0; text-align: center;">Roisin Sullivan</h3> <div style="text-align: center;"> <img src="Images/Transformation/Roisin.webp" style="max-width: 100%; height: auto; border-radius: 8px;" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; padding: 40px; background: #1a1a1a; border-radius: 8px; color: #999; font-style: italic;"> Image not found </div> </div> </div> </div> <<else>> <h2 style="color: #f39c12; text-align: center;">Your Reflection</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Face Image --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #667eea; margin: 0 0 10px 0; text-align: center;">Your Face</h3> <<set _faceImage = setup.getPlayerFaceImage()>> <div style="text-align: center;"> <img @src="_faceImage" style="max-width: 100%; height: auto; border-radius: 8px;" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; padding: 40px; background: #1a1a1a; border-radius: 8px; color: #999; font-style: italic;"> Image not found </div> </div> </div> <!-- Chest Image --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0; text-align: center;">Your Chest</h3> <<set _chestImage = setup.getPlayerChestImage()>> <div style="text-align: center;"> <img @src="_chestImage" style="max-width: 100%; height: auto; border-radius: 8px;" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; padding: 40px; background: #1a1a1a; border-radius: 8px; color: #999; font-style: italic;"> Image not found </div> </div> </div> </div> <</if>> <!-- Additional Info Box --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #3498db; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #3498db; margin: 0 0 15px 0;">Additional Details</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Skin Tone:</p> <p style="color: #fff; margin: 0; font-size: 16px; text-transform: capitalize;"><<print $appearance.skinTone>></p> </div> <div> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Hair Color:</p> <p style="color: #fff; margin: 0; font-size: 16px;"><<print $appearance.hairColor>></p> </div> <div> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Hair Style:</p> <p style="color: #fff; margin: 0; font-size: 16px; text-transform: capitalize;"><<if $physicalTraits && $physicalTraits.includes("Ojou")>>Drill Curls<<else>><<print $appearance.hairStyle>><</if>></p> </div> <div> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Hair Length:</p> <p style="color: #fff; margin: 0; font-size: 16px; text-transform: capitalize;"><<print $appearance.hairLength>></p> </div> </div> </div> <!-- Internal Monologue Section - Varies by Personality Traits --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">Inner Thoughts</h3> <div style="color: #ccc; font-size: 15px; line-height: 1.8; font-style: italic;"> <<if $mentalTraits && $mentalTraits.length > 0>> <!-- Confident thoughts --> <<if $mentalTraits.includes("Confident") || $mentalTraits.includes("Arrogant")>> <p style="margin: 0 0 10px 0;">"Looking good, as always. I know exactly who I am and what I'm worth."</p> <</if>> <!-- Shy/Insecure thoughts --> <<if $mentalTraits.includes("Shy") || $mentalTraits.includes("Insecure")>> <p style="margin: 0 0 10px 0;">"I wonder what people think when they look at me... Do they notice me at all?"</p> <</if>> <!-- Dominant thoughts --> <<if $mentalTraits.includes("Dominant")>> <p style="margin: 0 0 10px 0;">"This is the face of someone in control. People follow my lead, and they should."</p> <</if>> <!-- Submissive thoughts --> <<if $mentalTraits.includes("Submissive")>> <p style="margin: 0 0 10px 0;">"I hope I can make someone happy today... I just want to be useful."</p> <</if>> <!-- Intelligent/Analytical thoughts --> <<if $mentalTraits.includes("Intelligent") || $mentalTraits.includes("Analytical")>> <p style="margin: 0 0 10px 0;">"Fascinating how light reflects off my features at this angle. The physics of perception..."</p> <</if>> <!-- Optimistic thoughts --> <<if $mentalTraits.includes("Optimistic")>> <p style="margin: 0 0 10px 0;">"Today is going to be amazing! I can feel it. So many possibilities ahead!"</p> <</if>> <!-- Pessimistic thoughts --> <<if $mentalTraits.includes("Pessimistic") || $mentalTraits.includes("Cynical")>> <p style="margin: 0 0 10px 0;">"Another day, another disappointment waiting to happen. Let's see what goes wrong this time."</p> <</if>> <!-- Flirty/Seductive thoughts --> <<if $mentalTraits.includes("Flirty") || $mentalTraits.includes("Seductive") || $mentalTraits.includes("Alluring")>> <p style="margin: 0 0 10px 0;">"Mmm, looking delicious today. I wonder who I'll catch staring at me..."</p> <</if>> <!-- Kind/Empathetic thoughts --> <<if $mentalTraits.includes("Kind") || $mentalTraits.includes("Empathetic") || $mentalTraits.includes("Warm")>> <p style="margin: 0 0 10px 0;">"I hope everyone I meet today is doing okay. Maybe I can brighten someone's day."</p> <</if>> <!-- Bitchy/Cruel thoughts --> <<if $mentalTraits.includes("Bitchy") || $mentalTraits.includes("Cruel")>> <p style="margin: 0 0 10px 0;">"Better than most of the trash walking around this city. Not that that's saying much."</p> <</if>> <!-- Lazy thoughts --> <<if $mentalTraits.includes("Lazy")>> <p style="margin: 0 0 10px 0;">"Ugh, do I really have to do anything today? Looking at myself is exhausting enough."</p> <</if>> <!-- Hardworking/Ambitious thoughts --> <<if $mentalTraits.includes("Hardworking") || $mentalTraits.includes("Ambitious")>> <p style="margin: 0 0 10px 0;">"No time to waste. I've got goals to achieve and nobody's going to hand them to me."</p> <</if>> <!-- Paranoid thoughts --> <<if $mentalTraits.includes("Paranoid")>> <p style="margin: 0 0 10px 0;">"Is someone watching me? I swear I heard something... Stay alert."</p> <</if>> <!-- Creative/Artistic thoughts --> <<if $mentalTraits.includes("Creative") || $mentalTraits.includes("Artistic")>> <p style="margin: 0 0 10px 0;">"The interplay of shadow and light... I could make something beautiful of this moment."</p> <</if>> <!-- Brave thoughts --> <<if $mentalTraits.includes("Brave")>> <p style="margin: 0 0 10px 0;">"Whatever comes my way today, I'll face it head-on. Nothing can stop me."</p> <</if>> <!-- Cowardly thoughts --> <<if $mentalTraits.includes("Cowardly")>> <p style="margin: 0 0 10px 0;">"I hope nothing scary happens today... Maybe I should just stay inside."</p> <</if>> <!-- Awkward thoughts --> <<if $mentalTraits.includes("Awkward")>> <p style="margin: 0 0 10px 0;">"Why did I make that face? What do I do with my hands? Being me is so weird sometimes."</p> <</if>> <!-- Nerd thoughts --> <<if $mentalTraits.includes("Nerd") || $mentalTraits.includes("Bookworm")>> <p style="margin: 0 0 10px 0;">"I wonder if I have time to read another chapter today... or maybe finish that research."</p> <</if>> <!-- Energetic thoughts --> <<if $mentalTraits.includes("Energetic") || $mentalTraits.includes("High Energy")>> <p style="margin: 0 0 10px 0;">"Let's GO! I'm ready to take on the world! Where's my first adventure?!"</p> <</if>> <!-- Calm/Chill thoughts --> <<if $mentalTraits.includes("Calm") || $mentalTraits.includes("Chill") || $mentalTraits.includes("Relaxed")>> <p style="margin: 0 0 10px 0;">"...Yeah. This is fine. Everything's fine. No rush."</p> <</if>> <!-- Impulsive/Reckless thoughts --> <<if $mentalTraits.includes("Impulsive") || $mentalTraits.includes("Reckless")>> <p style="margin: 0 0 10px 0;">"Screw planning! Let's just do something crazy and see what happens!"</p> <</if>> <!-- Deep Thinker thoughts --> <<if $mentalTraits.includes("Deep Thinker") || $mentalTraits.includes("Overthinker")>> <p style="margin: 0 0 10px 0;">"Who am I really? Is this reflection the true me, or just what I show the world?"</p> <</if>> <!-- Sarcastic thoughts --> <<if $mentalTraits.includes("Sarcastic")>> <p style="margin: 0 0 10px 0;">"Oh great, it's me. What a thrilling discovery. Never saw that coming."</p> <</if>> <!-- Moody thoughts --> <<if $mentalTraits.includes("Moody")>> <p style="margin: 0 0 10px 0;">"I don't know how I feel right now. Happy? Sad? Angry? All of them? None?"</p> <</if>> <!-- Lucky thoughts --> <<if $mentalTraits.includes("Lucky")>> <p style="margin: 0 0 10px 0;">"I've got a good feeling about today. Things always seem to work out for me."</p> <</if>> <!-- Unlucky thoughts --> <<if $mentalTraits.includes("Unlucky") || $mentalTraits.includes("Bad Luck")>> <p style="margin: 0 0 10px 0;">"Knowing my luck, something terrible is about to happen. It always does."</p> <</if>> <!-- Default if no specific trait matched but has mental traits --> <<set _hasShownThought = $mentalTraits.includes("Confident") || $mentalTraits.includes("Arrogant") || $mentalTraits.includes("Shy") || $mentalTraits.includes("Insecure") || $mentalTraits.includes("Dominant") || $mentalTraits.includes("Submissive") || $mentalTraits.includes("Intelligent") || $mentalTraits.includes("Analytical") || $mentalTraits.includes("Optimistic") || $mentalTraits.includes("Pessimistic") || $mentalTraits.includes("Cynical") || $mentalTraits.includes("Flirty") || $mentalTraits.includes("Seductive") || $mentalTraits.includes("Alluring") || $mentalTraits.includes("Kind") || $mentalTraits.includes("Empathetic") || $mentalTraits.includes("Warm") || $mentalTraits.includes("Bitchy") || $mentalTraits.includes("Cruel") || $mentalTraits.includes("Lazy") || $mentalTraits.includes("Hardworking") || $mentalTraits.includes("Ambitious") || $mentalTraits.includes("Paranoid") || $mentalTraits.includes("Creative") || $mentalTraits.includes("Artistic") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Cowardly") || $mentalTraits.includes("Awkward") || $mentalTraits.includes("Nerd") || $mentalTraits.includes("Bookworm") || $mentalTraits.includes("Energetic") || $mentalTraits.includes("High Energy") || $mentalTraits.includes("Calm") || $mentalTraits.includes("Chill") || $mentalTraits.includes("Relaxed") || $mentalTraits.includes("Impulsive") || $mentalTraits.includes("Reckless") || $mentalTraits.includes("Deep Thinker") || $mentalTraits.includes("Overthinker") || $mentalTraits.includes("Sarcastic") || $mentalTraits.includes("Moody") || $mentalTraits.includes("Lucky") || $mentalTraits.includes("Unlucky")>> <<if !_hasShownThought>> <p style="margin: 0 0 10px 0;">"Hmm, that's me alright. Just... me."</p> <</if>> <<else>> <p style="margin: 0;">"Hmm, that's me alright. Just... me."</p> <</if>> </div> </div> <!-- Hair Styling Option (if player has Hair Styling skill) --> <<if $skills && $skills.includes("Hair Styling")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-top: 25px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 15px 0;">💇 Style Your Hair</h3> <<if $appearance.hairStyle === "messy">> <p style="color: #aaa; margin-bottom: 15px;">Your hair is currently messy. With your Hair Styling skill, you can style it yourself!</p> <<link "<div style='background: #e91e63; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>💇 Style Your Hair (10 min)</div>">> <<run advanceTime(10)>> <<set $appearance.hairStyle = "styled">> <<goto "MirrorView">> <</link>> <<else>> <p style="color: #51cf66; margin: 0;">✓ Your hair is already styled and looks great!</p> <</if>> </div> <<elseif $appearance.hairStyle === "messy">> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-top: 25px; border: 2px solid #666;"> <p style="color: #888; margin: 0; font-style: italic;">Your hair is messy. Learn the Hair Styling skill or visit a salon to style it.</p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<set _mirrorBack = $mirrorReturnLocation || "StudioBathroom">> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Bathroom</div>">> <<goto _mirrorBack>> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center;">😴 Restless Sleep</h1> <div style="padding: 20px; background: linear-gradient(135deg, #434343 0%, #000000 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: white; font-size: 18px; margin: 0;"> You manage to get some fitful sleep behind the trash bags. The smell is unbearable and every sound makes you jolt awake, but at least you got some rest. Your body aches from the hard ground, but you're safe... for now. </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Wake Up</div>">> <<goto "Alleyway">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">😱 Robbed!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b6b 0%, #c92a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0;"> You wake up suddenly to find someone rifling through your pockets! Before you can react, they sprint off into the darkness with half your money! </p> <p style="color: white; font-size: 16px; margin: 0; font-weight: bold;"> You lost half your money! </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; font-size: 15px; margin: 0; text-align: center;"> You curse yourself for sleeping in such a dangerous place. The streets are ruthless to those who let their guard down. </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Get Up</div>">> <<goto "Alleyway">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Aquarium")>> <<run $visitedLocations.push("Aquarium")>> <</if>> <<set $lastLocation = "Aquarium">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🐠 Sunfish City Aquarium</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0;"> The aquarium's grand entrance hall opens into a world of blue. Massive glass tanks stretch from floor to ceiling, filled with... sunfish. Only sunfish. Exclusively sunfish. Every single tank contains ocean sunfish (Mola mola) in various sizes, all drifting lazily and rotating in that vacant way they do. You expected dolphins, sharks, tropical fish, coral reefs... but no. Just hundreds upon hundreds of sunfish. The plaques on each tank read things like "Sunfish Exhibit A", "Sunfish Exhibit B", and "Really Big Sunfish Exhibit". Why would anyone build an entire aquarium dedicated solely to sunfish? It doesn't make any sense. The gentle sound of bubbling water and the blank stares of countless sunfish create an unsettling atmosphere. </p> </div> <h2 style="color: #1e90ff;">What do you want to do?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Explore Exhibits --> <div style="border: 3px solid #00ced1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #00ced1; margin-top: 0;">🌊 Explore Exhibits</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Wander through the various sunfish exhibits. There are baby sunfish, adult sunfish, and really big sunfish. That's it. That's all there is.</p> <<link "<div style='background: #00ced1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Explore</div>">> <<set $timeInMinutes += 60>> <<set _sunfishRoll = Math.random()>> <<set _gotSunfishTrait = false>> <<if _sunfishRoll < (1/32768) && !$physicalTraits.includes("Sunfish")>> <<run $physicalTraits.push("Sunfish")>> <<set _gotSunfishTrait = true>> <</if>> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px; max-width: 500px;"> <h2 style="color: #00ced1; margin-top: 0;">🌊 Exploring the Exhibits</h2> <p style="color: #ccc; line-height: 1.6; margin: 15px 0;"> You wander through the dimly lit corridors, passing tank after tank of slowly rotating sunfish. Their vacant eyes follow you—or maybe they don't, it's hard to tell. </p> <div style="margin: 20px 0;"> <img src="Images/Other/Sunfish.jpg" style="max-width: 100%; border-radius: 8px; border: 2px solid #00ced1;"> </div> <p style="color: #ccc; line-height: 1.6; margin: 15px 0;"> The sunfish drift peacefully, their enormous disc-shaped bodies rotating slowly in the water. It's actually quite mesmerizing. </p> <<if _gotSunfishTrait>> <div style="background: #ffd700; padding: 15px; border-radius: 8px; margin: 15px 0; border: 3px solid #ffaa00;"> <p style="color: #000; font-weight: bold; font-size: 18px; margin: 0 0 10px 0;">✨ ULTRA RARE! ✨</p> <p style="color: #000; font-weight: bold; margin: 0;">You feel a strange connection to the sunfish... You have become one with the Mola mola!</p> <p style="color: #ff6b00; font-weight: bold; margin: 10px 0 0 0;">Gained trait: Sunfish</p> </div> <</if>> <p style="color: #ccc; line-height: 1.6; margin: 15px 0;"> As you continue walking, you swear someone is following you from the corner of your eye. Every time you turn to look, there's no one there... except for a suspicious puddle on the floor and a trail of water leading around the corner. </p> <p style="color: #ffc107; line-height: 1.6; margin: 15px 0; font-style: italic;"> The wet footprints look oddly disc-shaped. </p> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #00ced1; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Continue</div>">> <<run Dialog.close()>> <<goto "Aquarium">> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Touch Tank --> <div style="border: 3px solid #20b2aa; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20b2aa; margin-top: 0;">✋ Touch Tank</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Interactive touch pool with small sunfish. They feel slimy and confused. Why is this the only interactive exhibit?</p> <<link "<div style='background: #20b2aa; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Touch Tank</div>">> <<set $timeInMinutes += 30>> <<set _sunfishRoll = Math.random()>> <<set _gotSunfishTrait = false>> <<if _sunfishRoll < (1/32768) && !$physicalTraits.includes("Sunfish")>> <<run $physicalTraits.push("Sunfish")>> <<set _gotSunfishTrait = true>> <</if>> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px; max-width: 500px;"> <h2 style="color: #20b2aa; margin-top: 0;">✋ Touch Tank Experience</h2> <p style="color: #ccc; line-height: 1.6; margin: 15px 0;"> You approach the shallow touch pool, eager to feel the texture of a sunfish. Several small sunfish drift lazily near the surface. </p> <p style="color: #ccc; line-height: 1.6; margin: 15px 0;"> You reach your hand into the water toward one... and it instantly disappears. Not swims away—<em>disappears</em>. You blink and try again with another sunfish. The same thing happens. </p> <<if _gotSunfishTrait>> <div style="background: #ffd700; padding: 15px; border-radius: 8px; margin: 15px 0; border: 3px solid #ffaa00;"> <p style="color: #000; font-weight: bold; font-size: 18px; margin: 0 0 10px 0;">✨ ULTRA RARE! ✨</p> <p style="color: #000; font-weight: bold; margin: 0;">As your hand touches the water, you feel a profound transformation... You have become one with the Mola mola!</p> <p style="color: #ff6b00; font-weight: bold; margin: 10px 0 0 0;">Gained trait: Sunfish</p> </div> <</if>> <p style="color: #ff6b6b; line-height: 1.6; margin: 15px 0; font-weight: bold;"> Every single sunfish you try to touch vanishes the moment your hand gets close. </p> <p style="color: #aaa; line-height: 1.6; margin: 15px 0; font-style: italic;"> You have no idea what's going on. This place is deeply unsettling. </p> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #20b2aa; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Back Away Slowly</div>">> <<run Dialog.close()>> <<goto "Aquarium">> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Gift Shop --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🎁 Gift Shop</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Browse sunfish-themed souvenirs. Plush sunfish, sunfish keychains, sunfish t-shirts, sunfish mugs, sunfish everything...</p> <<link "<div style='background: #ffd700; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Browse Shop</div>">> <<goto "AquariumGiftShop">> <</link>> </div> <!-- Cafe --> <div style="border: 3px solid #32cd32; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #32cd32; margin-top: 0;">☕ Ocean View Cafe</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Grab a bite with a view of the main tank. Watch sunfish slowly rotate while you eat. It's hypnotic and deeply weird.</p> <<link "<div style='background: #32cd32; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Cafe</div>">> <<goto "AquariumCafe">> <</link>> </div> </div> <!-- NPCs Section --> <h2 style="color: #1e90ff;">People Here</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #1e90ff; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">Normal Man</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;">Normal Employee</p> <<link "<div style='background: #1e90ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to Normal Man</div>">> <<goto "SunfishFakeInterface">> <</link>> </div> </div> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "IllegalServices">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("IllegalServices")>> <<run $visitedLocations.push("IllegalServices")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff4444; text-align: center;">🔓 Illegal Services</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff4444;"> <p style="color: #ccc; font-size: 18px; margin: 0;"> The old man leans in close, his breath reeking of cheap whiskey. "Looking for some... personality adjustments? Criminal record problems? I know people. They can make problems disappear, or give you new... perspectives. For the right price, of course. Hehehehe..." </p> </div> <div style="background: #2a2a2a; border: 2px solid #ffc107; padding: 15px; border-radius: 10px; margin-bottom: 25px;"> <p style="color: #ffc107; margin: 0; font-weight: bold; font-size: 16px;">💰 Your Money: $<<print $money.toLocaleString()>></p> </div> <!-- ERASE CRIMINAL RECORD --> <<if $jobs && $jobs.includes("Criminal")>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e74c3c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #e74c3c; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #e74c3c; padding-bottom: 10px;">🚔 Erase Criminal Record</h2> <p style="color: #aaa; font-size: 14px; margin-bottom: 15px;">Completely wipe your criminal history clean. All records destroyed, heat cleared, warrant removed. It's like you were never a criminal...</p> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #ffc107; margin: 0 0 10px 0; font-size: 18px;">What This Includes:</h3> <ul style="color: #ccc; font-size: 14px; margin: 5px 0; padding-left: 20px;"> <<if $jailSystem && $jailSystem.previousJob && $jailSystem.previousJob !== "Unemployed">> <li>Restore your previous job: <span style="color: #51cf66;">$jailSystem.previousJob</span></li> <<else>> <li>Remove Criminal status (become Unemployed)</li> <</if>> <li>Clear all arrest records and crime statistics</li> <li>Remove heat level and active warrants</li> <li>Erase all evidence of criminal activity</li> <li><span style="color: #51cf66;">Keep all traits you've acquired</span></li> </ul> <p style="color: #888; font-size: 13px; margin: 10px 0 0 0; font-style: italic;">Note: Any traits you've stolen remain yours. This only clears your record.</p> </div> <<if $money >= 50000>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Erase Record for $50,000</div>">> <<set $money -= 50000>> /* Restore previous job or make unemployed */ <<if $jailSystem && $jailSystem.previousJob && $jailSystem.previousJob !== "Unemployed" && $jailSystem.previousJob !== "Criminal">> <<set $jobs = [$jailSystem.previousJob]>> <<else>> <<set $jobs = ["Unemployed"]>> <</if>> /* Clear all crime system data */ <<set $crimeSystem.warnings = 0>> <<set $crimeSystem.witnessedCrimes = 0>> <<set $crimeSystem.totalThefts = 0>> <<set $crimeSystem.successfulThefts = 0>> <<set $crimeSystem.failedThefts = 0>> <<set $crimeSystem.arrestCount = 0>> <<set $crimeSystem.resistedArrestCount = 0>> <<set $crimeSystem.surrenderCount = 0>> <<set $crimeSystem.heatLevel = 0>> <<set $crimeSystem.activeWarrant = false>> <<set $crimeSystem.crimesCommitted = 0>> /* Clear jail system */ <<if $jailSystem>> <<set $jailSystem.previousJob = "">> <</if>> /* Achievement for erasing criminal record */ <<run setup.achievements.unlock("erase_criminal_record")>> <<goto "IllegalServices">> <</link>> </div> <<else>> <div style="text-align: center;"> <div style='display: inline-block; background: #666; color: #999; padding: 15px 30px; border-radius: 8px; font-weight: bold; font-size: 18px; opacity: 0.5;'> Can't Afford ($50,000 required) </div> </div> <</if>> </div> <</if>> <!-- CURE GAMBLING ADDICTION --> <<if $mentalTraits && $mentalTraits.includes("Gambling Addiction")>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 215, 0, 0.3);"> <h2 style="color: #ffd700; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ffd700; padding-bottom: 10px;">🎰 Cure Gambling Addiction</h2> <p style="color: #aaa; font-size: 14px; margin-bottom: 15px;">The old man grins wickedly. "Gambling problem, eh? I know a... specialist. Hypnotherapy, they call it. He'll rewire your brain, make you forget you ever liked the slots. Won't be cheap though..."</p> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #ffc107; margin: 0 0 10px 0; font-size: 18px;">Treatment Includes:</h3> <ul style="color: #ccc; font-size: 14px; margin: 5px 0; padding-left: 20px;"> <li>Permanent removal of Gambling Addiction trait</li> <li>No more forced gambling when entering casino</li> <li>Complete freedom from compulsive urges</li> <li>Ability to walk away from games anytime</li> </ul> <div style="background: #2d2020; padding: 10px; border-radius: 6px; margin-top: 10px; border-left: 4px solid #c62828;"> <p style="color: #ff6b6b; font-size: 13px; margin: 0; font-weight: bold;">⚠️ Warning: Extremely expensive procedure - $100,000</p> <p style="color: #888; font-size: 12px; margin: 5px 0 0 0; font-style: italic;">Ironically, you'll need to win big at gambling to afford the cure for gambling addiction...</p> </div> </div> <<if $money >= 100000>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px rgba(255, 215, 0, 0.5);'>Get Treatment for $100,000</div>">> <<set $money -= 100000>> <<run $mentalTraits.delete("Gambling Addiction")>> /* Achievement for curing gambling addiction */ <<run setup.achievements.unlock("remove_gambling_addiction")>> /* Also counts as removing a negative trait */ <<run setup.achievements.unlock("remove_negative_trait")>> <<goto "IllegalServices">> <</link>> </div> <<else>> <div style="text-align: center;"> <div style='display: inline-block; background: #666; color: #999; padding: 15px 30px; border-radius: 8px; font-weight: bold; font-size: 18px; opacity: 0.5;'> Can't Afford ($100,000 required) </div> <p style="color: #888; font-size: 13px; margin: 10px 0 0 0; font-style: italic;">You need $<<print (100000 - $money).toLocaleString()>> more...</p> </div> <</if>> </div> <</if>> <!-- REMOVE NEGATIVE TRAITS --> <<set _negativeTraits = []>> <<set _purelyNegativeTraits = [ "Blemished", "Clumsy", "Overweight", "Plain", "Slow", "Stiff", "Ugly", "Underweight", "Weak", "Arrogant", "Bitchy", "Cold", "Complacent", "Cowardly", "Cruel", "Deceitful", "Disorganized", "Dull", "Erratic", "Foolish", "Forgetful", "Impatient", "Insecure", "Insensitive", "Jealous", "Lazy", "Obsessive", "Reckless", "Rude", "Selfish", "Short Tempered", "Slow Learner", "Unreliable" ]>> <<for _trait range $mentalTraits>> <<if _purelyNegativeTraits.includes(_trait)>> <<run _negativeTraits.push(_trait)>> <</if>> <</for>> <<for _trait range $physicalTraits>> <<if _purelyNegativeTraits.includes(_trait)>> <<run _negativeTraits.push(_trait)>> <</if>> <</for>> <<if _negativeTraits.length > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #ff6b6b; padding-bottom: 10px;">❌ Remove Negative Traits</h2> <p style="color: #aaa; font-size: 14px; margin-bottom: 15px;">Get rid of your worst qualities... for a price. Each trait removal costs $5,000.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px;"> <<for _trait range _negativeTraits>> <<capture _trait>> <<if $money >= 5000>> <div style="border: 2px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; font-size: 18px;">_trait</h3> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Remove for $5,000</div>">> <<set $money -= 5000>> <<if $physicalTraits.includes(_trait)>> <<run $physicalTraits.delete(_trait)>> <<else>> <<run $mentalTraits.delete(_trait)>> <</if>> /* Achievement for removing a negative trait */ <<run setup.achievements.unlock("remove_negative_trait")>> <<goto "IllegalServices">> <</link>> </div> <<else>> <div style="border: 2px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0; font-size: 18px;">_trait</h3> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Can't Afford ($5,000 required)</div> </div> <</if>> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #666; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #666; padding-bottom: 10px;">❌ Remove Negative Traits</h2> <p style="color: #666; font-size: 14px; margin: 0; text-align: center; font-style: italic;">You have no negative traits to remove.</p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #434343; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Shady Shop</div>">> <<goto "ShadyShop">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("AquariumCafe")>> <<run $visitedLocations.push("AquariumCafe")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">☕ Aquarium Café</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The café is eerily quiet. A few empty tables sit scattered around the room. The lighting is dim, casting strange shadows on the walls. </p> </div> <!-- If player just ate the food --> <<if $justAteSunfishFood>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dabf7; box-shadow: 0 8px 16px rgba(77, 171, 247, 0.4);"> <h3 style="color: #4dabf7; margin: 0 0 15px 0; text-align: center;">Something Changes...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You consume the mysterious substance. The taste is indescribable - neither pleasant nor unpleasant, existing somehow outside normal sensory experience. It slides down your throat with an odd, gelatinous texture. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> For a moment, everything goes silent. Then you feel it - a fundamental shift deep within you. Your connection to sunfish becomes... profound. Innate. As if you've always been part of their world. </p> <p style="color: #4caf50; margin: 0; text-align: center; font-weight: bold; font-size: 18px;"> ✓ You have gained the Sunfish skill! </p> </div> <<set $justAteSunfishFood = false>> <</if>> <!-- The Wall Sign --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0; text-align: center;">On the Wall</h3> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #ff6b6b; text-align: center;"> <p style="color: #4caf50; font-size: 24px; margin: 0 0 15px 0; font-weight: bold;"> SAFE TO EAT </p> <div style="margin: 15px 0;"> <p style="color: #1e90ff; font-size: 60px; margin: 0; line-height: 1;"> 🐟 </p> </div> <p style="color: #ccc; margin: 0; font-style: italic; font-size: 14px;"> The sunfish image seems to watch you. No matter where you stand, its eyes follow your movement. It makes your skin crawl. </p> </div> </div> <!-- The Counter/Menu --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">The Counter</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Normal Man stands behind the counter. Again. The same damp trench coat. The same mismatched, unblinking eyes. Water drips steadily onto the floor beneath him, forming a small puddle. You hear those wet slapping sounds from inside the coat once more. </p> <p style="color: #ccc; margin: 0 0 20px 0; line-height: 1.6; font-style: italic;"> How does he keep appearing everywhere? You're starting to feel very uncomfortable. </p> </div> <!-- If player has the food but hasn't eaten it yet --> <<if $hasSunfishFood && !$skills.includes("Sunfish")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; text-align: center;">You Have Sunfish Food?</h3> <p style="color: #ccc; margin: 0 0 20px 0; text-align: center; line-height: 1.6;"> The mysterious dish sits before you. Do you dare consume it? </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #ffc107; color: #1a1a1a; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Eat the Sunfish Food?</div>">> <<if !$skills>><<set $skills = []>><</if>> <<set $skills.push("Sunfish")>> <<set $hasSunfishFood = false>> <<set $justAteSunfishFood = true>> <<goto "AquariumCafe">> <</link>> </div> </div> <<else>> <!-- The Menu (only shows if you don't have the food or already ate it) --> <h2 style="color: #1e90ff; text-align: center;">Menu</h2> <div style="display: grid; grid-template-columns: 1fr; gap: 15px; margin-bottom: 25px; max-width: 600px; margin-left: auto; margin-right: auto;"> <!-- Sunfish Food --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 8px 16px rgba(255, 193, 7, 0.3);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; text-align: center; font-size: 24px;">🍽️ Sunfish Food?</h3> <<if $skills.includes("Sunfish")>> <p style="font-size: 14px; color: #4caf50; margin: 0; text-align: center; font-style: italic;"> You've already consumed this mysterious dish. Its effects course through you. </p> <<else>> <p style="font-size: 14px; color: #aaa; margin: 0 0 15px 0; text-align: center; line-height: 1.6;"> A mysterious dish. You can't quite tell what it is. It sits under a glass dome on the counter, looking... odd. The texture is strange. The color is stranger. </p> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 15px 0; text-align: center; font-style: italic;"> Is it food FOR sunfish? Or food MADE FROM sunfish? Or something else entirely? You're not sure you want to know. </p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 20px 0; text-align: center; font-size: 28px;"> $1,000,000 </p> <p style="color: #ff6b6b; margin: 0 0 20px 0; text-align: center; font-size: 14px; font-style: italic;"> Who in the world would pay this much for... whatever this is? </p> <<if $money >= 1000000>> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Purchase Sunfish Food?</div>">> <<set $money -= 1000000>> <<set $hasSunfishFood = true>> <<run setup.achievements.unlock("buy_sunfish_food")>> <<goto "AquariumCafe">> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 12px 25px; border-radius: 6px; text-align: center; font-weight: bold;'>Cannot Afford (Thank goodness?)</div> <</if>> <</if>> </div> </div> <</if>> <!-- Normal Man's Stare --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #1e90ff; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0; text-align: center; line-height: 1.6;"> Normal Man continues to stare at you with those bulging, unblinking eyes. One looking at you. One looking... elsewhere. The silence is deafening except for the drip, drip, drip of water and those occasional wet slapping sounds. </p> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">❓ Information Desk</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: white; font-size: 18px; margin: 0;"> You approach the information desk. The figure standing behind it is... wrong. They're impossibly tall and disc-shaped, wearing a soaking wet trench coat that's clearly too small. Their "face" is just two bulging eyes staring in slightly different directions. They're not moving like a human should - instead, they're sort of... wobbling? Rotating? There's a constant stream of water dripping from the coat onto the floor, forming a substantial puddle. You can hear a faint "bloop bloop" sound coming from somewhere within the coat. This absolutely doesn't make sense. It's as if multiple mola mola sunfish somehow stacked themselves inside a trench coat and are pretending to be a person, which is impossible because fish can't do that. </p> </div> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> The "person" slowly rotates to face you, making a sloshing sound. Their mouth opens slightly. </p> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #1e90ff; margin-bottom: 20px;"> <p style="color: #1e90ff; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> "Bloop bloop. Nothing to see here. Bloop bloop." </p> </div> <p style="color: #ccc; font-size: 16px; margin-top: 20px;"> They continue staring at you with those vacant, fishy eyes. A small fin briefly pokes out from under the trench coat before quickly retracting. You're not sure what you expected. </p> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🐠 Trade with Normal Man</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> "Bloop bloop. Nothing to see here. Bloop bloop." </p> </div> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #1e90ff;"> <p style="color: #ccc; font-size: 16px;"> Normal Man stares at you with vacant, unblinking eyes. Water drips from somewhere within the trench coat. You hear a faint sloshing sound. A fin briefly pokes out before disappearing again. This is deeply uncomfortable. </p> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">💬 Talk to Normal Man</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0;"> You attempt to strike up a conversation with Normal Man. </p> </div> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #1e90ff;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> Normal Man who is Normal stares at you. His bulging eyes don't blink. They don't move. One eye seems to be looking at you. The other is looking at something behind you. Or maybe at nothing. The silence stretches on. Water continues to drip. You hear a wet slapping sound from inside the coat. The stare continues. It's making you very uncomfortable. </p> <p style="color: #ccc; font-size: 16px; margin-top: 20px;"> You give up at any attempt to talk to the... Normal Man... </p> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #667eea;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Normal Man</h1> <p style="color: white; margin: 0; font-size: 18px; text-align: center;"> Normal Employee </p> </div> <!-- NPC Stats --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #17a2b8; padding-bottom: 10px;">📊 Stats</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; font-size: 16px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Charisma:</strong> <span style="color: #17a2b8; font-weight: bold;">Bloop</span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Dexterity:</strong> <span style="color: #17a2b8; font-weight: bold;">Bloop</span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Strength:</strong> <span style="color: #17a2b8; font-weight: bold;">Bloop</span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #17a2b8;"> <strong style="color: #aaa;">Intelligence:</strong> <span style="color: #17a2b8; font-weight: bold;">Bloop</span> </div> </div> </div> <!-- NPC Appearance --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #9b59b6; padding-bottom: 10px;">👤 Appearance</h3> <div style="font-size: 16px; color: #ccc; line-height: 1.8;"> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Hair:</strong> None</p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Skin Tone:</strong> Wet and Slimy</p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Physique:</strong> Disc-Shaped</p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Chest:</strong> ????</p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Butt:</strong> ????</p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Gender:</strong> Bloop</p> <p style="margin: 8px 0;"><strong style="color: #9b59b6;">Age:</strong> ????</p> </div> </div> <!-- NPC Traits --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #51cf66; padding-bottom: 10px;">💪 Physical Traits</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <span style="background: #1a1a1a; color: #51cf66; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #51cf66; font-weight: 500;">Disc-Shaped</span> <span style="background: #1a1a1a; color: #51cf66; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #51cf66; font-weight: 500;">Wet</span> <span style="background: #1a1a1a; color: #51cf66; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #51cf66; font-weight: 500;">Wobbling</span> <span style="background: #1a1a1a; color: #51cf66; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #51cf66; font-weight: 500;">Has Fins (??)</span> <span style="background: #1a1a1a; color: #51cf66; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #51cf66; font-weight: 500;">Multiple Eyes</span> </div> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #9b59b6; padding-bottom: 10px;">🧠 Mental Traits</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <span style="background: #1a1a1a; color: #9b59b6; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #9b59b6; font-weight: 500;">Vacant</span> <span style="background: #1a1a1a; color: #9b59b6; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #9b59b6; font-weight: 500;">Fishy</span> <span style="background: #1a1a1a; color: #9b59b6; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #9b59b6; font-weight: 500;">Suspicious</span> <span style="background: #1a1a1a; color: #9b59b6; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #9b59b6; font-weight: 500;">Definitely Not Multiple Sunfish</span> </div> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #ffc107; padding-bottom: 10px;">🎯 Skills</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <span style="background: #1a1a1a; color: #ffc107; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #ffc107; font-weight: 500;">Blooping</span> <span style="background: #1a1a1a; color: #ffc107; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #ffc107; font-weight: 500;">Standing Still</span> <span style="background: #1a1a1a; color: #ffc107; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #ffc107; font-weight: 500;">Avoiding Questions</span> <span style="background: #1a1a1a; color: #ffc107; padding: 8px 15px; border-radius: 20px; font-size: 15px; border: 2px solid #ffc107; font-weight: 500;">Rotating Slowly</span> </div> </div> <!-- Action Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 25px;"> <<link "<div style='background: #667eea; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💱 Initiate Trade</div>">> <<goto "NormalManTrade">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>💬 Talk</div>">> <<goto "NormalManTalk">> <</link>> </div> <br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #2a2a2a; color: #667eea; padding: 12px 30px; border-radius: 8px; border: 2px solid #667eea; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Go Back</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("AquariumGiftShop")>> <<run $visitedLocations.push("AquariumGiftShop")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🎁 Aquarium Gift Shop</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #00bfff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The gift shop is packed wall-to-wall with sunfish merchandise. Plush sunfish in every size. Sunfish keychains. Sunfish t-shirts. Sunfish coffee mugs. Sunfish everything. It's almost overwhelming. </p> </div> <!-- Special Display Case --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 8px 16px rgba(255, 215, 0, 0.3);"> <h3 style="color: #ffd700; margin: 0 0 15px 0; text-align: center;">✨ Premium Display ✨</h3> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #ffd700;"> <p style="color: #ffd700; font-size: 18px; margin: 0 0 10px 0; font-weight: bold; text-align: center;">Jeweled Sunfish Statue</p> <p style="color: #ccc; margin: 0 0 15px 0; text-align: center; line-height: 1.6;"> A magnificent sunfish carved from rare blue stone and encrusted with precious gems. Its eyes seem to follow you around the room. The craftsmanship is extraordinary - almost unnatural in its detail. </p> <p style="color: #4caf50; font-size: 20px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Price: $500,000 </p> <div style='background: #ff9800; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Coming Soon</div> </div> </div> <!-- Regular Merchandise --> <h2 style="color: #1e90ff;">Sunfish Merchandise</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Plush Sunfish --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🧸 Plush Sunfish</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">A soft, huggable sunfish plushie.</p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 10px 0;">$25</p> <div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Coming Soon</div> </div> <!-- Sunfish T-Shirt --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">👕 Sunfish T-Shirt</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">"I ♥ SUNFISH" printed on front.</p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 10px 0;">$20</p> <div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Coming Soon</div> </div> <!-- Sunfish Keychain --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🔑 Sunfish Keychain</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">A metal sunfish charm for your keys.</p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 10px 0;">$8</p> <div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Coming Soon</div> </div> <!-- Sunfish Coffee Mug --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">☕ Sunfish Mug</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Ceramic mug with sunfish design.</p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 10px 0;">$15</p> <div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Coming Soon</div> </div> <!-- Sunfish Poster --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">🖼️ Sunfish Poster</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Educational poster about sunfish.</p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 10px 0;">$12</p> <div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Coming Soon</div> </div> <!-- Sunfish Stickers --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1e90ff; margin: 0 0 10px 0;">✨ Sunfish Sticker Pack</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Set of 10 holographic stickers.</p> <p style="color: #4caf50; font-weight: bold; margin: 0 0 10px 0;">$5</p> <div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Coming Soon</div> </div> </div> <!-- Home Decor Section --> <h2 style="color: #1e90ff;">Home Decor</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #1abc9c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #1abc9c; margin: 0 0 15px 0;">🐚 Ocean-Themed Home Decor</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Bring the beauty of the ocean into your home with our collection of nautical and marine-themed decorations. Perfect for any room! </p> <<link "<div style='background: #1abc9c; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>Browse Ocean Decor</div>">> <<goto "AquariumGiftShopDecor">> <</link>> </div> <!-- The Cashier --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">The Counter</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Behind the counter stands... Normal Man. The same one from the entrance. You're sure of it. Same damp trench coat. Same unblinking, bulging eyes pointing in different directions. Same wet slapping sounds coming from inside the coat. </p> <p style="color: #ccc; margin: 0; line-height: 1.6; font-style: italic;"> How did he get here so fast? You just saw him at the entrance... This is deeply unsettling. </p> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Aquarium</div>">> <<goto "Aquarium">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("FenRisTraining")>> <<run $visitedLocations.push("FenRisTraining")>> <</if>> /* Initialize relationship if this is first meeting */ <<if !$npcRelationships["Fen Ris"]>> <<set $npcRelationships["Fen Ris"] = { level: 0, points: 0, xp: 0, maxXp: 20, levelName: "Stranger", bestFriendUnlocked: false }>> <</if>> <<if $npcRelationships["Fen Ris"].points === undefined || $npcRelationships["Fen Ris"].points === null || isNaN($npcRelationships["Fen Ris"].points)>> <<set $npcRelationships["Fen Ris"].points = 0>> <</if>> /* Add Fen Ris to met NPCs if not already there */ <<if !$metNPCs.includes("Fen Ris")>> <<run $metNPCs.push("Fen Ris")>> <</if>> <<silently>> /* Get all trainers by job */ <<set _trainers = setup.getNPCsAtLocation("FenRisTraining").filter(function(n) { return n.jobs && n.jobs.includes("Fitness Trainer"); })>> <<set _canTrainToday = true>> /* Check if player already trained today (track by job, not name) */ <<if $lastFenRisTrainingDay === $dayNumber>> <<set _canTrainToday = false>> <</if>> <</silently>> <div style="background: linear-gradient(135deg, #ff6b6b 0%, #c92a2a 100%); padding: 20px; border-radius: 10px; margin-bottom: 20px;"> <h2 style="margin: 0; color: white; text-align: center;">Personal Training</h2> </div> <<if $physicalTraits.includes("Automaton")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 2px solid #555; margin-bottom: 20px;"> <p style="color: #e74c3c; font-size: 16px; text-align: center; margin: 0;">Your mechanical body cannot benefit from physical training. Personal training is unavailable.</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold;'>← Return to Gym</div>" "OpahFitness">><</link>> </div> <<elseif _trainers && _trainers.length > 0>> <<for _trainerIndex = 0; _trainerIndex < _trainers.length; _trainerIndex++>> <<set _trainer = _trainers[_trainerIndex]>> <<silently>> /* Calculate trainer effectiveness */ <<set _effectiveness = 100>> /* Base effectiveness */ /* Check if this is the original Fen Ris by checking for Were-Creature trait */ <<set _isOriginalFenRis = _trainer.physicalTraits.includes("Were-Creature")>> <<if !_isOriginalFenRis>> /* Calculate trainer's total stats (base + trait/skill bonuses) */ <<set _trainerStrength = _trainer.stats.strength>> <<set _trainerDex = _trainer.stats.dexterity>> /* Add bonuses from physical traits */ <<for _i = 0; _i < _trainer.physicalTraits.length; _i++>> <<set _trait = _trainer.physicalTraits[_i]>> <<if setup.traitBonuses[_trait]>> <<if setup.traitBonuses[_trait].strength>> <<set _trainerStrength += setup.traitBonuses[_trait].strength>> <</if>> <<if setup.traitBonuses[_trait].dexterity>> <<set _trainerDex += setup.traitBonuses[_trait].dexterity>> <</if>> <</if>> <</for>> /* Add bonuses from mental traits */ <<for _i = 0; _i < _trainer.mentalTraits.length; _i++>> <<set _trait = _trainer.mentalTraits[_i]>> <<if setup.traitBonuses[_trait]>> <<if setup.traitBonuses[_trait].strength>> <<set _trainerStrength += setup.traitBonuses[_trait].strength>> <</if>> <<if setup.traitBonuses[_trait].dexterity>> <<set _trainerDex += setup.traitBonuses[_trait].dexterity>> <</if>> <</if>> <</for>> /* Add bonuses from skills */ <<for _i = 0; _i < _trainer.skills.length; _i++>> <<set _skill = _trainer.skills[_i]>> <<if setup.skillBonuses[_skill]>> <<if setup.skillBonuses[_skill].strength>> <<set _trainerStrength += setup.skillBonuses[_skill].strength>> <</if>> <<if setup.skillBonuses[_skill].dexterity>> <<set _trainerDex += setup.skillBonuses[_skill].dexterity>> <</if>> <</if>> <</for>> /* Check if both stats meet the threshold */ <<if _trainerStrength >= 80 && _trainerDex >= 80>> <<set _effectiveness = 100>> <<else>> /* Start at 50% base effectiveness */ <<set _effectiveness = 50>> /* Compare physical traits (excluding body parts) */ <<set _fenRisPhysical = ["Tall", "Muscular", "Athletic Build", "Sharp Features", "Were-Creature"]>> <<set _matchingPhysical = 0>> <<for _i = 0; _i < _fenRisPhysical.length; _i++>> <<if _trainer.physicalTraits.includes(_fenRisPhysical[_i])>> <<set _matchingPhysical++>> <</if>> <</for>> <<set _effectiveness += (_matchingPhysical / _fenRisPhysical.length) * 15>> /* Compare mental traits */ <<set _fenRisMental = ["Confident", "Calm", "Honest", "Patient"]>> <<set _matchingMental = 0>> <<for _i = 0; _i < _fenRisMental.length; _i++>> <<if _trainer.mentalTraits.includes(_fenRisMental[_i])>> <<set _matchingMental++>> <</if>> <</for>> <<set _effectiveness += (_matchingMental / _fenRisMental.length) * 10>> /* Compare skills */ <<set _fenRisSkills = ["Athletics", "Heavy Lifting", "Combat", "Yoga", "Teaching"]>> <<set _matchingSkills = 0>> <<for _i = 0; _i < _fenRisSkills.length; _i++>> <<if _trainer.skills.includes(_fenRisSkills[_i])>> <<set _matchingSkills++>> <</if>> <</for>> <<set _effectiveness += (_matchingSkills / _fenRisSkills.length) * 15>> /* Compare appearance (hair color, skin tone, age) */ <<set _appearanceMatches = 0>> <<if _trainer.appearance.hairColor === "Black">><<set _appearanceMatches++>><</if>> <<if _trainer.appearance.skinTone === "tan">><<set _appearanceMatches++>><</if>> <<if _trainer.appearance.age === "Adult">><<set _appearanceMatches++>><</if>> <<set _effectiveness += (_appearanceMatches / 3) * 10>> /* Round to whole number */ <<set _effectiveness = Math.round(_effectiveness)>> <</if>> <</if>> /* Calculate actual stat gains based on effectiveness */ /* Cerberus/Gym Bunny 4x / Himbo 2x gym bonus */ <<set _cerberusBonus = $physicalTraits.includes("Cerberus") ? 4 : ($physicalTraits.includes("Gym Bunny") ? 4 : ($physicalTraits.includes("Himbo") ? 2 : 1))>> <<set _strengthGain = Math.round(5 * (_effectiveness / 100) * _cerberusBonus)>> <<set _dexGain = Math.round(4 * (_effectiveness / 100) * _cerberusBonus)>> <<set _charismaGain = Math.round(3 * (_effectiveness / 100) * _cerberusBonus)>> <<set _intGain = Math.round(2 * (_effectiveness / 100) * _cerberusBonus)>> <</silently>> <!-- Transformation Gym Multiplier Display --> <<if _cerberusBonus > 1>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #ff6b6b; margin-bottom: 20px; box-shadow: 0 0 15px rgba(255,107,107,0.4);"> <p style="color: #ff6b6b; margin: 0; text-align: center; font-size: 14px; font-weight: bold; text-shadow: 0 0 8px rgba(255,107,107,0.5);"> ✓ <<if $physicalTraits.includes("Cerberus")>>Cerberus<<elseif $physicalTraits.includes("Gym Bunny")>>Gym Bunny<<else>>Himbo<</if>>: <<print _cerberusBonus>>x Training Gains </p> </div> <</if>> <div style="background-color: #2d2d2d; padding: 20px; border-radius: 8px; border: 2px solid #ff6b6b; margin-bottom: 20px;"> <h3 style="color: #ff6b6b; margin-top: 0;">About Your Trainer</h3> <!-- NPC Image --> <<set _trainerImage = setup.getNPCImage(_trainer.name)>> <<if _trainerImage>> <div style="text-align: center; margin-bottom: 20px;"> <img @src="_trainerImage" style="max-width: 300px; max-height: 400px; border-radius: 10px; border: 3px solid #ff6b6b; box-shadow: 0 0 20px rgba(255,107,107,0.6);" onerror="this.style.display='none';"> </div> <</if>> <<if _isOriginalFenRis>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> <<= _trainer.name>> stands before you, her imposing figure radiating strength and confidence. Her olive-brown skin glistens with a light sheen of sweat, and her wild black mane of wavy hair reaches her upper back, slightly unkempt in that effortlessly cool way. </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> Her deep yellow eyes with black sclera meet yours with an intensity that's both captivating and slightly intimidating. Black wolf ears perk up from her hair, twitching as she sizes you up, while a matching tail sways lazily behind her. Her upper arms and legs are covered in dark fur, ending in sharp claws that she's clearly mastered handling around gym equipment. When she grins, revealing sharp canines, you feel both welcomed and challenged. </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> "Ready to push your limits?" she asks in a laid-back but direct tone. Despite her nonchalant demeanor, there's a forceful charisma about her that makes you want to prove yourself. Her high moral standards are evident in how she carries herself - no shortcuts, no excuses, just honest hard work. </p> <</if>> <<if !_isOriginalFenRis>> <div style="margin-top: 15px; padding: 12px; background-color: #1a1a1a; border-left: 4px solid #ffd43b; border-radius: 4px;"> <p style="color: #ffd43b; margin: 0; font-weight: bold;">Training Effectiveness: <<= _effectiveness>>%</p> <<if _effectiveness < 100>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-size: 14px;"> This trainer is less effective than the original Fen Ris. <<if _trainerStrength < 80 || _trainerDex < 80>> They need at least 80 Strength and 80 Dexterity for full effectiveness. <</if>> </p> <</if>> </div> <</if>> </div> <div style="background-color: #2d2d2d; padding: 20px; border-radius: 8px; border: 2px solid #51cf66; margin-bottom: 20px;"> <h3 style="color: #51cf66; margin-top: 0;">Training Session Details</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 15px;"> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 6px;"> <div style="color: #999; font-size: 14px;">Cost</div> <div style="color: #51cf66; font-size: 20px; font-weight: bold;">$100</div> </div> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 6px;"> <div style="color: #999; font-size: 14px;">Duration</div> <div style="color: #51cf66; font-size: 20px; font-weight: bold;">4 Hours</div> </div> </div> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 15px;"> <h4 style="color: #51cf66; margin: 0 0 10px 0;">Stat Gains (at <<= _effectiveness>>% effectiveness):</h4> <div style="color: #e0e0e0; line-height: 1.8;"> • Strength: <span style="color: #ff6b6b; font-weight: bold;">+<<= _strengthGain>></span><br> • Dexterity: <span style="color: #51cf66; font-weight: bold;">+<<= _dexGain>></span><br> • Charisma: <span style="color: #ffd43b; font-weight: bold;">+<<= _charismaGain>></span><br> • Intelligence: <span style="color: #4dabf7; font-weight: bold;">+<<= _intGain>></span> </div> </div> <<set _canAffordTraining = setup.canAffordTotal(100)>> <<if !_canTrainToday>> <div style="background-color: #c92a2a; padding: 12px; border-radius: 6px; margin-bottom: 15px;"> <p style="color: white; margin: 0; text-align: center; font-weight: bold;"> You've already trained today. Come back tomorrow! </p> </div> <<elseif !_canAffordTraining>> <div style="background-color: #c92a2a; padding: 12px; border-radius: 6px; margin-bottom: 15px;"> <p style="color: white; margin: 0; text-align: center; font-weight: bold;"> You don't have enough money for a training session. (Need: $100) </p> </div> <<else>> <<capture _trainer, _effectiveness, _strengthGain, _dexGain, _charismaGain, _intGain>> <<link "<div style='background: #ff6b6b; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Train with <<= _trainer.name>> ($100, 4 hours)</div>" "FenRisTrainingSession">> <<set _payment = setup.payAmount(100)>> <<if _payment.success>> <<set $lastFenRisTrainingDay = $dayNumber>> <<set $trainedWith = _trainer.name>> <<set $trainingEffectiveness = _effectiveness>> <<set $strengthGained = _strengthGain>> <<set $dexGained = _dexGain>> <<set $charismaGained = _charismaGain>> <<set $intGained = _intGain>> /* Apply stat gains */ <<set $stats.strength += _strengthGain>> <<set $stats.dexterity += _dexGain>> <<set $stats.charisma += _charismaGain>> <<set $stats.intelligence += _intGain>> /* Add relationship XP for training together (skip achievements) */ <<run setup.addRelationshipXP(_trainer.name, 2, true)>> /* Gym Bunny workout satisfaction */ <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> /* Advance time by 4 hours */ <<run advanceTime(240)>> <</if>> <</link>> <</capture>> <</if>> </div> <div style="background-color: #2d2d2d; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; margin-bottom: 20px;"> <h3 style="color: #9b59b6; margin-top: 0;">Other Options</h3> <<capture _trainer>> <<link "<div style='background: #9b59b6; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Talk to <<= _trainer.name>> </div>" "NPCInteraction">> <<set $tradingWithNPC = _trainer>> <<set $currentTradeNPC = _trainer>> /* Add relationship XP for talking */ <<run setup.addRelationshipXP(_trainer.name, 2)>> <</link>> <</capture>> </div> <</for>> <<else>> <div style="background-color: #c92a2a; padding: 20px; border-radius: 8px; border: 2px solid #ff6b6b;"> <p style="color: white; margin: 0; text-align: center;"> No fitness trainers are currently available. </p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Return to Gym</div>" "OpahFitness">><</link>> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(135deg, #ff6b6b 0%, #c92a2a 100%); padding: 20px; border-radius: 10px; margin-bottom: 20px;"> <h2 style="margin: 0; color: white; text-align: center;">Training Complete!</h2> </div> <div style="background-color: #2d2d2d; padding: 20px; border-radius: 8px; border: 2px solid #51cf66; margin-bottom: 20px;"> <<if $trainedWith === "Fen Ris">> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> The next four hours are intense. Fen Ris pushes you through a grueling combination of strength training, cardio, flexibility work, and mental conditioning. Her yellow eyes watch your every move, correcting your form with a sharp but not unkind word. Her clawed hands demonstrate proper technique with surprising grace. </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> "Good," she says simply when you finish, her tail swishing approvingly. "You actually put in the work. That's what I like to see." There's no excessive praise, just honest acknowledgment of your effort. </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> Despite the exhaustion, you feel stronger, more agile, and strangely more confident. Even your mind feels sharper from the mental focus required to keep up with her demanding routine. </p> <<else>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6;"> <<= $trainedWith>> guides you through a <<= $trainingEffectiveness>>% effective training session. While competent, you can't help but notice the difference from when Fen Ris was in charge. </p> <</if>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 6px; margin-top: 20px;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">Your Gains:</h3> <div style="color: #e0e0e0; font-size: 18px; line-height: 2;"> <span style="color: #ff6b6b;">■</span> Strength: <span style="color: #ff6b6b; font-weight: bold;">+<<= $strengthGained>></span><br> <span style="color: #51cf66;">■</span> Dexterity: <span style="color: #51cf66; font-weight: bold;">+<<= $dexGained>></span><br> <span style="color: #ffd43b;">■</span> Charisma: <span style="color: #ffd43b; font-weight: bold;">+<<= $charismaGained>></span><br> <span style="color: #4dabf7;">■</span> Intelligence: <span style="color: #4dabf7; font-weight: bold;">+<<= $intGained>></span> </div> <<if $trainingEffectiveness < 100>> <div style="margin-top: 15px; padding: 10px; background-color: #2d2d2d; border-left: 4px solid #ffd43b; border-radius: 4px;"> <p style="color: #ffd43b; margin: 0; font-size: 14px;"> Training effectiveness was only <<= $trainingEffectiveness>>%. With Fen Ris, you would have gained more! </p> </div> <</if>> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #51cf66; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Continue</div>" "OpahFitness">><</link>> </div> <</nobr>>
<<nobr>> /* Ensure all NPCs have relationship entries - BUT DON'T OVERWRITE EXISTING ONES */ <<for _i = 0; _i < $npcs.length; _i++>> <<if !$relationships[$npcs[_i].name]>> <<set $relationships[$npcs[_i].name] = { level: 0, points: 0 }>> <</if>> <</for>> /* Clean up orphaned relationships (old names that don't match any current NPC) */ <<set _currentNPCNames = $npcs.map(function(npc) { return npc.name; })>> <<set _relationshipNames = Object.keys($relationships)>> <<for _j = 0; _j < _relationshipNames.length; _j++>> <<set _relName = _relationshipNames[_j]>> <<if !_currentNPCNames.includes(_relName) && $metNPCs.includes(_relName)>> /* This is an orphaned relationship - remove it from metNPCs too */ <<set $metNPCs = $metNPCs.filter(function(name) { return name !== _relName; })>> <</if>> <</for>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b9d; text-align: center;">💕 Relationships</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b9d 0%, #c92a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b9d;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> Track your connections with the people of Sunfish City </p> </div> <!-- Sort relationships by points (highest to lowest) - ONLY INCLUDE MET NPCs --> <<set _sortedRelationships = []>> <<for _npcName, _rel range $relationships>> <<if $metNPCs.includes(_npcName)>> <<set _sortedRelationships.push({name: _npcName, rel: _rel})>> <</if>> <</for>> <<run _sortedRelationships.sort(function(a, b) { return b.rel.points - a.rel.points; })>> <<if _sortedRelationships.length === 0>> <div style="background-color: #2d2d2d; padding: 30px; border-radius: 12px; border: 3px solid #666; text-align: center;"> <p style="color: #999; font-size: 18px; margin: 0;"> You haven't met anyone yet. Go explore Sunfish City and make some connections! </p> </div> <<else>> <!-- Relationship List --> <div style="display: grid; gap: 15px; margin-bottom: 25px;"> <<for _i = 0; _i < _sortedRelationships.length; _i++>> <<set _npcName = _sortedRelationships[_i].name>> <<set _rel = _sortedRelationships[_i].rel>> <<set _npc = setup.getNPCByName(_npcName)>> <<set _relColor = setup.getRelationshipColor(_rel.level)>> <<set _levelData = setup.getRelationshipLevelData(_rel.level)>> <<if _rel.level < 4>> <<if _rel.level === -1>> /* Disliked: show progress from -50 to 0 */ <<set _currentLevelMin = -50>> <<set _nextThreshold = 0>> <<elseif _rel.level === 0>> /* Stranger: show progress from 0 to 25 */ <<set _currentLevelMin = 0>> <<set _nextThreshold = 25>> <<elseif _rel.level === 1>> /* Acquaintance: show progress from 25 to 75 */ <<set _currentLevelMin = 25>> <<set _nextThreshold = 75>> <<elseif _rel.level === 2>> /* Friend: show progress from 75 to 175 */ <<set _currentLevelMin = 75>> <<set _nextThreshold = 175>> <<else>> /* Close Friend: show progress from 175 to 425 */ <<set _currentLevelMin = 175>> <<set _nextThreshold = 425>> <</if>> <<set _xpInLevel = _rel.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <<if _xpPercent < 0>><<set _xpPercent = 0>><</if>> <<if _xpPercent > 100>><<set _xpPercent = 100>><</if>> <<else>> <<set _xpPercent = 100>> <</if>> <<set _levelName = _levelData ? _levelData.name : "Unknown">> <<capture _npcName, _relColor, _rel, _xpPercent, _levelName>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid <<= _relColor>>; box-shadow: 0 4px 12px rgba(0,0,0,0.6), 0 0 20px <<= _relColor>>33; cursor: pointer; transition: all 0.3s ease;" onmouseover="this.style.transform='scale(1.02)'; this.style.boxShadow='0 6px 16px rgba(0,0,0,0.8), 0 0 30px <<= _relColor>>66';" onmouseout="this.style.transform='scale(1)'; this.style.boxShadow='0 4px 12px rgba(0,0,0,0.6), 0 0 20px <<= _relColor>>33';"> <<link `"<div style='display: flex; justify-content: space-between; align-items: center;'><h2 style='color: " + _relColor + "; margin: 0; font-size: 22px; text-shadow: 0 0 10px " + _relColor + "88;'>" + _npcName + "</h2><div style='background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%); padding: 8px 15px; border-radius: 20px; border: 2px solid " + _relColor + "; box-shadow: 0 0 10px " + _relColor + "44;'><span style='color: " + _relColor + "; font-weight: bold; font-size: 16px;'>" + _levelName + "</span></div></div><div style='background-color: #0a0a0a; border-radius: 10px; height: 12px; overflow: hidden; border: 1px solid #444; margin-top: 10px; box-shadow: inset 0 2px 4px rgba(0,0,0,0.5);'><div style='background: linear-gradient(90deg, " + _relColor + " 0%, " + _relColor + "dd 100%); height: 100%; width: " + _xpPercent + "%; transition: width 0.3s ease; box-shadow: 0 0 10px " + _relColor + ";'></div></div>"` "RelationshipDetail">> <<set $viewingNPC = _npcName>> <</link>> </div> <</capture>> <</for>> </div> <</if>> <!-- BACK BUTTON --> <div style="margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2);'>← Return to Game</div>">> <<if $lastLocation && $lastLocation !== "">> <<goto $lastLocation>> <<else>> <<goto "Alleyway">> <</if>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$inventoryTab>><<set $inventoryTab = "items">><</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Back</div>">><<goto $lastLocation>><</link>> </div> <h1 style="color: #3498db; text-align: center; margin: 0 0 20px 0;">🎒 Inventory</h1> <!-- Tab Navigation --> <div style="display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center;"> <<link "<div id='invTabItems' style='border: 3px solid #f39c12; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>📦 Items</div>">><<set $inventoryTab = "items">><<goto "Inventory">><</link>> <<link "<div id='invTabFish' style='border: 3px solid #00bcd4; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>🎣 Fishing</div>">><<set $inventoryTab = "fishing">><<goto "Inventory">><</link>> <<link "<div id='invTabMining' style='border: 3px solid #d4a060; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>⛏ Mining</div>">><<set $inventoryTab = "mining">><<goto "Inventory">><</link>> <<link "<div id='invTabArtifacts' style='border: 3px solid #9b59b6; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>✨ Artifacts</div>">><<set $inventoryTab = "artifacts">><<goto "Inventory">><</link>> <<if (($traitStorageUnlocked || $possessionActive) && !$slimePossessionActive) && !$inTundraRegion>> <<link "<div id='invTabTraitStorage' style='border: 3px solid #e040fb; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>🧬 Trait Storage</div>">><<set $inventoryTab = "traitStorage">><<goto "Inventory">><</link>> <</if>> <<if setup.slime.isPlayerSlimeBodied() || $slimePossessionActive>><<link "<div style='display:inline-block;background:#1a4d3e;color:#51e0a8;padding:8px 16px;border-radius:6px;cursor:pointer;font-weight:bold;margin:4px;'>🫧 Slime Powers</div>">><<goto "SlimePanel">><</link>><</if>> <<link "<div id='invTabFood' style='border: 3px solid #51cf66; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>🍽️ Food</div>">><<set $inventoryTab = "food">><<goto "Inventory">><</link>> <<link "<div id='invTabNotes' style='border: 3px solid #fbbf24; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>📝 Notes</div>">><<set $inventoryTab = "notes">><<goto "Inventory">><</link>> </div> <<script>> $(function() { var it = State.variables.inventoryTab || "items"; var tabs = { items: {id: "invTabItems", bg: "#f39c12", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(243,156,18,0.53)"}, fishing: {id: "invTabFish", bg: "#00bcd4", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(0,188,212,0.53)"}, mining: {id: "invTabMining", bg: "#d4a060", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(212,160,96,0.53)"}, artifacts: {id: "invTabArtifacts", bg: "#9b59b6", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(155,89,182,0.53)"}, traitStorage: {id: "invTabTraitStorage", bg: "#e040fb", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(224,64,251,0.53)"}, food: {id: "invTabFood", bg: "#51cf66", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(81,207,102,0.53)"}, notes: {id: "invTabNotes", bg: "#fbbf24", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(251,191,36,0.53)"} }; Object.keys(tabs).forEach(function(key) { var el = document.getElementById(tabs[key].id); if (!el) return; if (key === it) { el.style.background = tabs[key].bg; el.style.boxShadow = tabs[key].shadow; } else { el.style.background = "linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)"; el.style.boxShadow = "0 4px 8px rgba(0,0,0,0.4)"; } }); }); <</script>> <!-- Tab Content --> <<if $inventoryTab === "fish">><<set $inventoryTab = "fishing">><</if>> <<if $inventoryTab === "traitStorage" && !((($traitStorageUnlocked || $possessionActive) && !$slimePossessionActive) && !$inTundraRegion)>><<set $inventoryTab = "items">><</if>> <<if $inventoryTab === "items">><<set _tabColor = "#f39c12">><<elseif $inventoryTab === "fishing">><<set _tabColor = "#00bcd4">><<elseif $inventoryTab === "mining">><<set _tabColor = "#d4a060">><<elseif $inventoryTab === "artifacts">><<set _tabColor = "#9b59b6">><<elseif $inventoryTab === "traitStorage">><<set _tabColor = "#e040fb">><<elseif $inventoryTab === "food">><<set _tabColor = "#51cf66">><<elseif $inventoryTab === "notes">><<set _tabColor = "#fbbf24">><<else>><<set _tabColor = "#f39c12">><</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _tabColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _tabColor>>44;"> <<if $inventoryTab === "items">> <!-- Items Tab Content --> <h2 style="color: #f39c12; margin: 0 0 15px 0;">Items</h2> <<set _sakeQty = ($giftInventory && $giftInventory.sake_bottle) || 0>> <<set _hasAnyItem = $ownsCogBook || $ownsSlimeRecipe || ($questItems && $questItems.length > 0) || _sakeQty > 0>> <<if _hasAnyItem>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<if $ownsCogBook>> <div style="background: linear-gradient(135deg, #2a1a0a 0%, #1a0a00 100%); border: 2px solid #cd7f32; border-radius: 8px; padding: 15px; box-shadow: 0 0 15px rgba(205,127,50,0.3); cursor: pointer;"> <<link "<div><div style='color: #cd7f32; font-weight: bold; font-size: 15px; margin-bottom: 6px; text-shadow: 0 0 10px rgba(205,127,50,0.5);'>The Mechanical Codex</div><div style='color: #c9a06c; font-size: 12px; line-height: 1.4;'>A leather-bound tome with brass clasps and gears embedded in the cover.</div></div>">><<goto "MechanicalCodex">><</link>> </div> <</if>> <<if $ownsSlimeRecipe>> <div style="background: linear-gradient(135deg, #0a1a2a 0%, #00101a 100%); border: 2px solid #4aa8ff; border-radius: 8px; padding: 15px; box-shadow: 0 0 15px rgba(74,168,255,0.3); cursor: pointer;"> <<link "<div><div style='color: #4aa8ff; font-weight: bold; font-size: 15px; margin-bottom: 6px; text-shadow: 0 0 10px rgba(74,168,255,0.5);'>Foreign Recipe Card</div><div style='color: #9cc4e0; font-size: 12px; line-height: 1.4;'>A water stained card covered in dense foreign writing. <b>Read it</b>.</div></div>">><<goto "SlimeRecipeNote">><</link>> </div> <</if>> <<if _sakeQty > 0>> <div style="background: linear-gradient(135deg, #2a1a1a 0%, #1a0a0a 100%); border: 2px solid #b94747; border-radius: 8px; padding: 15px; box-shadow: 0 0 15px rgba(185,71,71,0.3); cursor: pointer;"> <<link "<div><div style='color: #ffb0a0; font-weight: bold; font-size: 15px; margin-bottom: 6px; text-shadow: 0 0 10px rgba(185,71,71,0.5);'>🍶 Sake Bottle (×<<= _sakeQty>>)</div><div style='color: #c9a08c; font-size: 12px; line-height: 1.4;'>A clay bottle of unfiltered sake. Foreign script down the side. <b>Drink one</b>.</div></div>">><<goto "DrinkSake">><</link>> </div> <</if>> <!-- Quest Items --> <<if $questItems && $questItems.length > 0>> <<for _qi range $questItems>> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #0d0d1a 100%); border: 2px solid #7c4dff; border-radius: 8px; padding: 15px; box-shadow: 0 0 15px rgba(124,77,255,0.3);"> <div style="color: #7c4dff; font-weight: bold; font-size: 15px; margin-bottom: 6px; text-shadow: 0 0 10px rgba(124,77,255,0.5);"><<print _qi.name>></div> <div style="color: #aaa; font-size: 12px; line-height: 1.4;"><<print _qi.description>></div> <<if _qi.id === "slip_of_paper" && $xanitharCode>> <div style="margin-top: 10px; padding: 8px; background: #0a0a0a; border: 1px dashed #7c4dff; border-radius: 4px; text-align: center;"> <span style="color: #ffc107; font-family: monospace; font-size: 20px; letter-spacing: 4px;"><<print String($xanitharCode).padStart(4, "0")>></span> </div> <</if>> </div> <</for>> <</if>> </div> <<else>> <div style="background-color: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: #888; font-size: 14px;">No items yet.</div> </div> <</if>> <<elseif $inventoryTab === "fishing">> <!-- Fishing Tab Content --> <h2 style="color: #00bcd4; margin: 0 0 15px 0;">🎣 Fishing</h2> <!-- Fishing level + capacity --> <<set _fLevel = setup.fishing.getLevel()>> <<set _fXP = ($fishingSkill && $fishingSkill.xp) || 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #00bcd4; margin-bottom: 15px; display: flex; justify-content: space-around; flex-wrap: wrap; gap: 10px;"> <div style="text-align: center;"> <div style="color: #00bcd4; font-size: 12px;">Fishing Level</div> <div style="color: #80e0f8; font-weight: bold; font-size: 22px;">Lvl <<= _fLevel>></div> <div style="color: #888; font-size: 11px;"><<= _fXP>> XP</div> </div> <div style="text-align: center;"> <div style="color: #00bcd4; font-size: 12px;">Bucket Capacity</div> <div style="color: #80e0f8; font-weight: bold; font-size: 22px;"><<print setup.fishing.getInventoryCount()>> / <<print setup.fishing.getMaxInventory()>></div> </div> </div> <!-- Rod switcher: click to equip any rod tier you've reached, plus the Sunfish Rod if owned --> <!-- Backfill $maxRodTier from legacy saves where $fishingPole tracked both equipped tier and max owned tier. Capped at 3 since tier 4 (Sunfish) uses $hasSunfishRod. --> <<set $maxRodTier = Math.max($maxRodTier || 0, Math.min($fishingPole || 0, 3))>> <<set _maxRodTier = $maxRodTier>> <<set _hasSunfish = $hasSunfishRod === true>> <<if _maxRodTier > 0 || _hasSunfish>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #00bcd4; margin-bottom: 15px;"> <h3 style="color: #00bcd4; margin: 0 0 8px 0; font-size: 14px;">🎣 Rod Rack</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 8px;"> <<for _t = 1; _t <= 4; _t++>> <<capture _t>> <<set _rodDef = setup.fishing.fishingPoles[_t]>> <<set _rodOwned = (_t <= 3 && _maxRodTier >= _t) || (_t === 4 && _hasSunfish)>> <<set _rodEquipped = $fishingPole === _t>> <<if _rodOwned && _rodDef>> <div style="background: <<= _rodEquipped ? '#0f2a3a' : '#1f1f1f'>>; border: 1px solid <<= _rodEquipped ? '#00bcd4' : '#444'>>; border-radius: 6px; padding: 8px;"> <div style="color: <<= _rodEquipped ? '#80e0f8' : '#ccc'>>; font-weight: bold; font-size: 13px;"><<= _rodDef.name>> <<if _rodEquipped>><span style="color:#4caf50; font-size: 10px;">EQUIPPED</span><</if>></div> <div style="color: #888; font-size: 11px;">Tier <<= _t>></div> <<if !_rodEquipped>> <div style="margin-top: 6px;"> <<link "<div style='display: inline-block; background: #1f3a4a; border: 1px solid #00bcd4; color: #80e0f8; padding: 4px 12px; border-radius: 5px; cursor: pointer; font-size: 11px; font-weight: bold;'>Equip</div>">> <<set $fishingPole = _t>> <<goto "Inventory">> <</link>> </div> <</if>> </div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <div style="text-align: center; margin-bottom: 15px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px; display: inline-block;'>📖 Fish Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> <<if $fishInventory && $fishInventory.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _i, _fish range $fishInventory>> <<set _fishData = setup.fishing.fish[_fish.id]>> <<set _rarityColor = setup.fishing.rarityColors[_fish.rarity] || "#888">> <<set _fishIcon = _fish.icon || (_fishData ? _fishData.icon : null)>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid <<print _rarityColor>>; border-radius: 8px; padding: 12px;"> <div style="display: flex; align-items: center; gap: 10px;"> <div style="width: 48px; height: 48px; flex-shrink: 0;"> <<if _fishIcon>> <img @src="_fishIcon" style="width: 48px; height: 48px; image-rendering: pixelated;"> <<else>> <div style="width: 48px; height: 48px; background: #333; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 24px;">🐟</div> <</if>> </div> <div style="flex: 1;"> <div style="color: <<print _rarityColor>>; font-weight: bold; font-size: 14px;"><<print _fishData ? _fishData.name : _fish.name>></div> <div style="color: #888; font-size: 11px;"><<print _fish.rarity>></div> </div> <div style="color: #00bcd4; font-weight: bold; font-size: 14px;">$<<print _fish.basePrice>></div> </div> </div> <</for>> </div> <!-- Total Value --> <<set _totalFishValue = 0>> <<for _fish range $fishInventory>> <<set _totalFishValue += _fish.basePrice>> <</for>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333; text-align: center;"> <span style="color: #888;">Total Value: </span> <span style="color: #00bcd4; font-weight: bold; font-size: 18px;">$<<print _totalFishValue>></span> </div> </div> <<else>> <div style="background-color: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="font-size: 36px; margin-bottom: 10px;">🐟</div> <div style="color: #888; font-size: 14px;">No fish in storage. Go fishing at the Docks!</div> </div> <</if>> <<elseif $inventoryTab === "mining">> <!-- Mining Tab Content --> <<run setup.mining.ensureState()>> <h2 style="color: #d4a060; margin: 0 0 15px 0;">⛏ Mining</h2> <!-- Skill levels --> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #d4a060; margin-bottom: 15px; display: flex; justify-content: space-around; flex-wrap: wrap; gap: 10px;"> <div style="text-align: center;"> <div style="color: #d4a060; font-size: 12px;">Mining Level</div> <div style="color: #ffd080; font-weight: bold; font-size: 22px;">Lvl <<= $miningSkill.level>></div> <div style="color: #888; font-size: 11px;"><<= $miningSkill.xp>> XP</div> </div> <div style="text-align: center;"> <div style="color: #d4a060; font-size: 12px;">Crafting Level</div> <div style="color: #ffd080; font-weight: bold; font-size: 22px;">Lvl <<= $craftingSkill.level>></div> <div style="color: #888; font-size: 11px;"><<= $craftingSkill.xp>> XP</div> </div> <div style="text-align: center;"> <div style="color: #d4a060; font-size: 12px;">⚡ Energy</div> <div style="color: #ffd080; font-weight: bold; font-size: 22px;"><<= Math.floor(setup.mining._currentEnergy())>> / <<= setup.mining._maxEnergy()>></div> </div> </div> <!-- Mastery traits earned --> <<set _allMasteries = ["Ore Reader", "Forge Lore", "Gem Eye", "Master Craftsman"]>> <<set _earnedMasteries = _allMasteries.filter(function(t){ return ($mentalTraits || []).indexOf(t) !== -1; })>> <<if _earnedMasteries.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #d4a060; margin-bottom: 15px;"> <h3 style="color: #d4a060; margin: 0 0 8px 0; font-size: 14px;">★ Mastery Traits Earned</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _m range _earnedMasteries>> <div style="background: #2a1f10; border: 1px solid #d4a060; color: #ffd080; padding: 5px 12px; border-radius: 5px; font-size: 12px; font-weight: bold;"><<= _m>></div> <</for>> </div> </div> <</if>> <!-- Pickaxe Rack: each pickaxe shown with its slotted heads baked in. Click Equip to switch. --> <<if $pickaxes && $pickaxes.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; margin-bottom: 15px;"> <h3 style="color: #d4a060; margin: 0 0 8px 0; font-size: 14px;">⛏ Pickaxe Rack (<<= $pickaxes.length>>)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 8px;"> <<for _pk range $pickaxes>> <<capture _pk>> <<set _pkStrikes = (_pk.baseStrikes || 0) + (_pk.qualityBonus || 0)>> <<set _pkEquipped = _pk.id === $equippedPickaxe>> <<set _pkSlotHeads = (_pk.slottedHeads || []).map(function(hid){ var h = ($pickaxeHeads || []).find(function(x){ return x.id === hid; }); return h ? h.name : null; }).filter(function(n){ return !!n; })>> <<set _pkLabel = _pkSlotHeads.length ? (_pk.name + " + " + _pkSlotHeads.join(" + ")) : _pk.name>> <div style="background: <<= _pkEquipped ? '#2a1f10' : '#1f1f1f'>>; border: 1px solid <<= _pkEquipped ? '#d4a060' : '#444'>>; border-radius: 6px; padding: 8px;"> <div style="color: <<= _pkEquipped ? '#ffd080' : '#ccc'>>; font-weight: bold; font-size: 13px;"><<= _pkLabel>> <<if _pkEquipped>><span style="color:#4caf50; font-size: 10px;">EQUIPPED</span><</if>></div> <div style="color: #888; font-size: 11px;"><<= _pkStrikes>> strikes • <<= _pk.sockets || 1>> socket<<if (_pk.sockets || 1) > 1>>s<</if>></div> <<if _pk.masterBonus>><div style="color: #ffd080; font-size: 10px;">★ <<= _pk.masterBonus>></div><</if>> <<if !_pkEquipped>> <div style="margin-top: 6px;"> <<link "<div style='display: inline-block; background: #3a2a1a; border: 1px solid #d4a060; color: #ffd080; padding: 4px 12px; border-radius: 5px; cursor: pointer; font-size: 11px; font-weight: bold;'>Equip</div>">> <<run setup.mining.equipPickaxe(_pk.id)>> <<goto "Inventory">> <</link>> </div> <</if>> </div> <</capture>> <</for>> </div> </div> <</if>> <!-- Loose pickaxe heads: only shown if not slotted onto any pickaxe (slotted heads are part of the pickaxe above) --> <<set _looseHeads = ($pickaxeHeads || []).filter(function(h){ return !($pickaxes || []).some(function(p){ return (p.slottedHeads || []).indexOf(h.id) !== -1; }); })>> <<if _looseHeads.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; margin-bottom: 15px;"> <h3 style="color: #d4a060; margin: 0 0 8px 0; font-size: 14px;">🔧 Loose Heads (<<= _looseHeads.length>>)</h3> <p style="color: #888; font-size: 11px; margin: 0 0 6px 0; font-style: italic;">Slot these onto a pickaxe at the Forge.</p> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _hd range _looseHeads>> <div style="background: #1f1f1f; border: 1px solid #444; border-radius: 5px; padding: 5px 10px; font-size: 12px; color: #ccc;"><<= _hd.name>></div> <</for>> </div> </div> <</if>> <!-- Materials grid: ore, ingots, raw gems, cut gems --> <<set _oreKeys = Object.keys($oreInventory || {}).filter(function(k){ return ($oreInventory[k] || 0) > 0; })>> <<set _ingotKeys= Object.keys($ingotInventory || {}).filter(function(k){ return ($ingotInventory[k] || 0) > 0; })>> <<set _rawGemKeys = Object.keys($gemInventory || {}).filter(function(k){ return ($gemInventory[k] || 0) > 0; })>> <<set _cutGemKeys = Object.keys($cutGemInventory||{}).filter(function(k){ return ($cutGemInventory[k] || 0) > 0; })>> <<set _flawlessGemKeys = Object.keys($flawlessGemInventory||{}).filter(function(k){ return ($flawlessGemInventory[k] || 0) > 0; })>> <<if _oreKeys.length || _ingotKeys.length || _rawGemKeys.length || _cutGemKeys.length || _flawlessGemKeys.length || ($relicInventory && $relicInventory.length)>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px;"> <<if _oreKeys.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #8a6a3a;"> <h3 style="color: #d4a060; margin: 0 0 8px 0; font-size: 14px;">🪨 Raw Ore</h3> <<for _ok range _oreKeys>> <div style="display: flex; justify-content: space-between; padding: 3px 0; font-size: 13px;"><span style="color: #d4c4a0;"><<= setup.mining._prettyName(_ok)>></span><span style="color: #ffd080; font-weight: bold;"><<= $oreInventory[_ok]>></span></div> <</for>> </div> <</if>> <<if _ingotKeys.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #8a6a3a;"> <h3 style="color: #d4a060; margin: 0 0 8px 0; font-size: 14px;">Ingots</h3> <<for _ik range _ingotKeys>> <div style="display: flex; justify-content: space-between; padding: 3px 0; font-size: 13px;"><span style="color: #d4c4a0;"><<= setup.mining._prettyName(_ik)>></span><span style="color: #ffd080; font-weight: bold;"><<= $ingotInventory[_ik]>></span></div> <</for>> </div> <</if>> <<if _rawGemKeys.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #80a0ff;"> <h3 style="color: #80a0ff; margin: 0 0 8px 0; font-size: 14px;">💎 Raw Gems</h3> <<for _gk range _rawGemKeys>> <div style="display: flex; justify-content: space-between; align-items:center; padding: 3px 0; font-size: 13px;"><span style="color: #d4c4a0; display:flex; align-items:center; gap:7px;"><span style="width:22px;height:22px;display:inline-block;line-height:0;"><<= setup.flawlessGems.rawStoneSVG(_gk)>></span><<= setup.mining._prettyName(_gk)>></span><span style="color: #a0d0ff; font-weight: bold;"><<= $gemInventory[_gk]>></span></div> <</for>> </div> <</if>> <<if _cutGemKeys.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #f48fb1;"> <h3 style="color: #f48fb1; margin: 0 0 8px 0; font-size: 14px;">✨ Cut Gems</h3> <<for _ck range _cutGemKeys>> <div style="display: flex; justify-content: space-between; align-items:center; padding: 3px 0; font-size: 13px;"><span style="color: #d4c4a0; display:flex; align-items:center; gap:7px;"><span style="width:22px;height:22px;display:inline-block;line-height:0;"><<= setup.flawlessGems.gemSVG(_ck, false)>></span><<= setup.mining._prettyName(_ck)>></span><span style="color: #f8bbd0; font-weight: bold;"><<= $cutGemInventory[_ck]>></span></div> <</for>> </div> <</if>> <<if _flawlessGemKeys.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #ffd27f;"> <h3 style="color: #ffd27f; margin: 0 0 8px 0; font-size: 14px;">💠 Flawless Gems</h3> <<for _fk range _flawlessGemKeys>> <div style="display: flex; justify-content: space-between; align-items:center; padding: 3px 0; font-size: 13px;"><span style="color: #e8dcc6; display:flex; align-items:center; gap:7px;"><span style="width:24px;height:24px;display:inline-block;line-height:0; filter:drop-shadow(0 0 4px <<= setup.flawlessGems.color(_fk)>>);"><<= setup.flawlessGems.gemSVG(_fk, false)>></span>Flawless <<= setup.mining._prettyName(_fk)>></span><span style="color: #ffe9a8; font-weight: bold;"><<= $flawlessGemInventory[_fk]>></span></div> <</for>> </div> <</if>> <<if $relicInventory && $relicInventory.length>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #c2953a;"> <h3 style="color: #c2953a; margin: 0 0 8px 0; font-size: 14px;">🏺 Relics</h3> <<for _rl range $relicInventory>> <div style="display: flex; justify-content: space-between; align-items:center; padding: 3px 0; font-size: 13px;"><span style="color: #d4c4a0;"><<= _rl.name>></span><span style="color: #7ddf9a; font-weight: bold;">$<<= _rl.value>></span></div> <</for>> </div> <</if>> </div> <<else>> <div style="background-color: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="font-size: 36px; margin-bottom: 10px;">⛏</div> <div style="color: #888; font-size: 14px;">No mining materials yet. Visit a quarry to start mining!</div> </div> <</if>> <<elseif $inventoryTab === "artifacts">> <!-- Artifacts Tab Content --> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">✨ Artifacts</h2> <!-- Sunfish Artifact toggle (only appears when bound) --> <<run setup.sunfishCuff.ensureState()>> <<if $sunfishCuffBound>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 12px; padding: 18px; margin-bottom: 18px; box-shadow: 0 0 18px rgba(201,169,255,0.3);"> <h3 style="color: #c9a9ff; margin: 0 0 8px 0;">🐟 Sunfish Artifact</h3> <p style="color: #ddd; font-size: 13px; line-height: 1.6; margin: 0 0 12px 0;">Band, Disc Amulet, Dorsal Spire, Lunar Crescent, and the Eye Stone fitted into one piece. Bound to Roisin Sullivan.</p> <<if $possessionActive>> <p style="color: #ff8fc8; font-size: 13px; font-style: italic; margin: 0 0 12px 0;">The artifact is active on your wrist.</p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #2a1a3a; color: #d4c4f0; padding: 9px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; border: 1px solid #c9a9ff;'>Deactivate the Artifact</div>">> <<run setup.possession.revertRoisin()>> <<goto "Inventory">> <</link>> </div> <<else>> <<set _cuffCheck = setup.possession.canApplyRoisin()>> <<if _cuffCheck.ok>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 9px 22px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Activate the Artifact</div>">> <<set _cuffFirstUse = (($roisinPossessedCount || 0) === 0)>> <<run setup.possession.applyRoisin()>> <<if _cuffFirstUse>> <<goto "RoisinPossessionFirstCutscene">> <<else>> <<goto setup.sunfishCuff.getRoisinCurrentLocation()>> <</if>> <</link>> </div> <<else>> <p style="color: #ffaaaa; font-size: 13px; font-style: italic; margin: 0; text-align: center;"><<= _cuffCheck.reason>></p> <</if>> <</if>> </div> <</if>> <<if $artifactsObtained && $artifactsObtained.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px;"> <<for _artifact range $artifactsObtained>> <<if _artifact === "The Sunfish Hook">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9c27b0; border-radius: 8px; padding: 12px;"> <div style="color: #9c27b0; font-weight: bold; font-size: 14px;">🪝 The Sunfish Hook</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Treasure & Catch</div> <<if $currentArtifact === "The Sunfish Hook">><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <<elseif _artifact === "The Gentle Giant's Heart">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #e91e63; border-radius: 8px; padding: 12px;"> <div style="color: #e91e63; font-weight: bold; font-size: 14px;">💖 The Gentle Giant's Heart</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Relationship Bonus</div> <<if ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad")))>><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <<elseif _artifact === "The Basking Charm">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff9800; border-radius: 8px; padding: 12px;"> <div style="color: #ff9800; font-weight: bold; font-size: 14px;">☀️ The Basking Charm</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Sex XP & Sexual Pay</div> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <<elseif _artifact === "The Drifter's Coin">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #00bcd4; border-radius: 8px; padding: 12px;"> <div style="color: #00bcd4; font-weight: bold; font-size: 14px;">🪙 The Drifter's Coin</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Trading Bonus</div> <<if ($currentArtifact === "The Drifter's Coin" || ($physicalTraits && $physicalTraits.includes("Naiad")))>><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <<elseif _artifact === "The Pearl of Abundance">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #f5f5f5; border-radius: 8px; padding: 12px;"> <div style="color: #f5f5f5; font-weight: bold; font-size: 14px;">🔮 The Pearl of Abundance</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Money Bonus</div> <<if ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <<elseif _artifact === "The Crowd's Eye">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #673ab7; border-radius: 8px; padding: 12px;"> <div style="color: #673ab7; font-weight: bold; font-size: 14px;">👁️ The Crowd's Eye</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Popularity Bonus</div> <<if ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <<elseif _artifact === "The Tidal Memory Stone">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; border-radius: 8px; padding: 12px;"> <div style="color: #4dabf7; font-weight: bold; font-size: 14px;">🌊 The Tidal Memory Stone</div> <div style="color: #888; font-size: 11px; margin-top: 5px;">Teleportation</div> <<if $currentArtifact === "The Tidal Memory Stone">><div style="color: #4caf50; font-size: 10px; margin-top: 5px;">Currently Equipped</div><</if>> </div> <</if>> <</for>> </div> </div> <<else>> <div style="background-color: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="font-size: 36px; margin-bottom: 10px;">✨</div> <div style="color: #888; font-size: 14px;">No artifacts discovered yet. Explore the island to find hidden treasures!</div> </div> <</if>> <!-- Unique Artifacts Section --> <<if $ownedArtifacts && $ownedArtifacts.length > 0>> <h2 style="color: #e040fb; margin: 25px 0 15px 0;">🔮 Unique Artifacts</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #e040fb;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px;"> <<for _uArtifact range $ownedArtifacts>> <<if _uArtifact === "Witch's Amulet">> <div style="background: linear-gradient(135deg, #2d1a3d 0%, #1a1a2e 100%); border: 2px solid #e040fb; border-radius: 8px; padding: 12px; box-shadow: 0 0 10px rgba(224,64,251,0.2);"> <div style="color: #e040fb; font-weight: bold; font-size: 14px;">🧿 Witch's Amulet</div> <div style="color: #bb86fc; font-size: 11px; margin-top: 5px;">Enables Witch Transformation</div> <div style="color: #666; font-size: 10px; margin-top: 5px; font-style: italic;">Soulbound: Cannot be removed</div> <<if $activeTransformation === "Witch">> <div style="margin-top: 8px;"> <div style="color: #4caf50; font-size: 10px; margin-bottom: 6px;">Currently Active<<if $witchFirstName>> as <<print $firstName + " " + $lastName>><</if>></div> <<if $clairFormActive>> <div style="background: #333; color: #a78bfa; padding: 6px 10px; border-radius: 6px; font-size: 11px;">Another shape holds you. Release the Twinning spell first.</div> <<else>> <<link "<div style='background: #555; color: white; padding: 8px 16px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 12px;'>Deactivate</div>">> <<run setup.revertFullTransformation("Witch")>> <<goto "Inventory">> <</link>> <</if>> <div style="margin-top: 6px;"> <<if $witchUseWitchPortrait>> <<link "<div style='background: #2d1a3d; color: #bb86fc; padding: 6px 12px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 11px; border: 1px solid #8b00ff;'>Portrait: Witch | Switch to Default</div>">> <<set $witchUseWitchPortrait = false>> <<goto "Inventory">> <</link>> <<else>> <<link "<div style='background: #2d1a3d; color: #bb86fc; padding: 6px 12px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 11px; border: 1px solid #8b00ff;'>Portrait: Default | Switch to Witch</div>">> <<set $witchUseWitchPortrait = true>> <<goto "Inventory">> <</link>> <</if>> </div> </div> <<elseif !setup.oni.isPlayerInOwnBody()>> <div style="margin-top: 8px;"> <div style="background: #333; color: #888; padding: 8px 16px; border-radius: 6px; text-align: center; font-size: 11px; font-style: italic;">Bound to your own body. Return to it to wear.</div> </div> <<elseif setup.slime && (setup.slime.isPlayerSlimeBodied() || $slimePossessionActive)>> <div style="margin-top: 8px;"> <div style="background: #1a1a1a; color: #888; padding: 8px 16px; border-radius: 6px; text-align: center; font-size: 11px; font-style: italic;">A slime cannot take the witch's shape.</div> </div> <<else>> <div style="margin-top: 8px;"> <<link "<div style='background: #e040fb; color: white; padding: 8px 16px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 12px;'>Activate</div>">> <<if $witchFirstTransformDone>> <<run setup.applyFullTransformation("Witch")>> <<goto "Inventory">> <<else>> <<goto "WitchTransformationScene">> <</if>> <</link>> </div> <</if>> </div> <</if>> <</for>> </div> </div> <</if>> <<elseif $inventoryTab === "traitStorage" && $inTundraRegion>> <div style="padding: 40px 20px; text-align: center;"> <div style="font-size: 40px; margin-bottom: 10px;">🧬</div> <p style="color: #9bbccc; font-size: 16px; line-height: 1.7; max-width: 480px; margin: 0 auto;">The trait storage cannot be reached from the tundra. Out here you are only what you are. Return to the world below to store or retrieve a trait.</p> </div> <<elseif $inventoryTab === "traitStorage">> <!-- Trait Storage Tab Content --> <<if $possessionActive>> <!-- Possession: show Roisin's separate trait storage instead of the player's --> <<run setup.sunfishCuff.ensureState()>> <h2 style="color: #c9a9ff; margin: 0 0 15px 0;">🐟 Roisin's Trait Storage</h2> <p style="color: #c9a9ff; font-size: 13px; font-style: italic; margin: 0 0 15px 0;">You are wearing the Sunfish Artifact. Roisin Sullivan keeps her traits in a sealed cradle separate from your own. Anything stored here stays with her. Anything you take from here goes onto her body, not yours.</p> <!-- Stored Traits Section --> <div style="background-color: #1a0f2a; padding: 15px; border-radius: 8px; border: 1px solid #c9a9ff44; margin-bottom: 15px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">In Storage</h3> <<set _cuffStoredAny = false>> <<for _cuffCat range ["physical", "mental", "voice", "skills"]>> <<set _cuffStoredArr = ($roisinTraitStorage && $roisinTraitStorage[_cuffCat]) || []>> <<if _cuffStoredArr.length > 0>> <<set _cuffStoredAny = true>> <h4 style="color: #d4c4f0; margin: 8px 0 4px 0; text-transform: capitalize;"><<= _cuffCat>></h4> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _cuffStoredTrait range _cuffStoredArr>> <<capture _cuffCat, _cuffStoredTrait>> <div style="background: #2a1a3a; border: 1px solid #c9a9ff; color: #d4c4f0; padding: 5px 10px; border-radius: 5px; font-size: 12px;"> <<= _cuffStoredTrait>> <<link "<span style='color: #ff8fc8; margin-left: 8px; cursor: pointer;'>Grant</span>">> <<run setup.roisinTraits.grantStored(_cuffCat, _cuffStoredTrait)>> <<goto "Inventory">> <</link>> </div> <</capture>> <</for>> </div> <</if>> <</for>> <<if !_cuffStoredAny>> <p style="color: #888; margin: 0;">Nothing in her storage yet.</p> <</if>> </div> <!-- Store Traits Section: only available once trait-manipulation threshold reached --> <<if setup.sunfishCuff.canManipulateRoisinTraits()>> <div style="background-color: #1a0f2a; padding: 15px; border-radius: 8px; border: 1px solid #c9a9ff44;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">Strip a Trait</h3> <p style="color: #888; font-size: 12px; margin: 0 0 10px 0;">Identity-locked traits cannot be removed. Anything else is yours to peel off and keep.</p> <<for _cuffCat2 range ["physical", "mental", "voice", "skills"]>> <<set _cuffArrName = (_cuffCat2 === "skills" ? "skills" : (_cuffCat2 + "Traits"))>> <<set _cuffCurrentArr = State.variables[_cuffArrName] || []>> <<if _cuffCurrentArr.length > 0>> <h4 style="color: #d4c4f0; margin: 10px 0 5px 0; text-transform: capitalize;"><<= _cuffCat2>></h4> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _cuffTraitOnHer range _cuffCurrentArr>> <<capture _cuffCat2, _cuffTraitOnHer>> <<set _cuffLocked = setup.roisinTraits.isLocked(_cuffCat2, _cuffTraitOnHer)>> <<if _cuffLocked>> <div style="background: #1a0a2a; border: 1px solid #6e4ea8; color: #888; padding: 5px 10px; border-radius: 5px; font-size: 12px;">🔒 <<= _cuffTraitOnHer>></div> <<else>> <<link "<div style='background: #2a1a3a; border: 1px solid #c9a9ff; color: #c9a9ff; padding: 5px 10px; border-radius: 5px; font-size: 12px; cursor: pointer;'><<= _cuffTraitOnHer>></div>">> <<run setup.roisinTraits.storeTrait(_cuffCat2, _cuffTraitOnHer)>> <<goto "Inventory">> <</link>> <</if>> <</capture>> <</for>> </div> <</if>> <</for>> </div> <<else>> <div style="background-color: #1a0f2a; padding: 15px; border-radius: 8px; border: 1px solid #6e4ea8;"> <p style="color: #c9a9ff; margin: 0; font-size: 13px;">You haven't worn the artifact enough to start reshaping her. Possess her at least <<= setup.sunfishCuff.TRAIT_MANIP_THRESHOLD>> times. Currently: <<= ($roisinPossessedCount || 0)>> / <<= setup.sunfishCuff.TRAIT_MANIP_THRESHOLD>>.</p> </div> <</if>> <<else>> <h2 style="color: #e040fb; margin: 0 0 15px 0;">🧬 Trait Storage</h2> <!-- Life Swap Warning --> <<if $lifeSwapOriginalBodyNPC>> <div style="background: #3a2020; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0; font-weight: bold;">⚠️ Life Swapped Body Detected</p> <p style="color: #aaa; margin: 5px 0 0 0; font-size: 13px;">You can TAKE traits from storage, but cannot STORE traits while in another body.</p> </div> <</if>> <!-- Stored Traits Section --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-bottom: 15px;"> <h3 style="color: #e040fb; margin: 0 0 10px 0;">Stored Traits</h3> <<if $traitStorage && $traitStorage.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _i, _storedTrait range $traitStorage>> <<set _traitValue = setup.getTraitValue(_storedTrait.type, _storedTrait.name)>> <<set _traitColor = _storedTrait.type === "physical" ? "#51cf66" : "#9b59b6">> <div style="background: #2d2d2d; border: 2px solid <<print _traitColor>>; border-radius: 8px; padding: 10px 15px;"> <div style="color: <<print _traitColor>>; font-weight: bold;"><<print _storedTrait.name>></div> <div style="color: #888; font-size: 11px;"><<print _storedTrait.type>> (Value: <<print _traitValue>>)</div> <!-- Retrieve Button --> <<capture _storedTrait, _i>> <<set _alreadyHas = (_storedTrait.type === "physical" && $physicalTraits.includes(_storedTrait.name)) || (_storedTrait.type === "mental" && $mentalTraits.includes(_storedTrait.name))>> <<set _blockReason = setup.fishing.checkTraitStorageBlock(_storedTrait.name)>> <<if _alreadyHas>> <div style="color: #888; font-size: 11px; margin-top: 5px;">Already have this trait</div> <<elseif _blockReason>> <div style="color: #ff6b6b; font-size: 11px; margin-top: 5px;"><<print _blockReason>></div> <<else>> <<link "<div style='background: #28a745; color: white; padding: 5px 10px; border-radius: 5px; font-size: 12px; margin-top: 5px; cursor: pointer;'>Retrieve</div>">> <<run setup.fishing.retrieveTraitFromStorage(_i)>> <<goto "Inventory">> <</link>> <</if>> <</capture>> </div> <</for>> </div> <<else>> <p style="color: #888; margin: 0;">No traits stored yet.</p> <</if>> </div> <!-- Store Traits Section (only if not life-swapped) --> <<if !$lifeSwapOriginalBodyNPC>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #e040fb; margin: 0 0 10px 0;">Store a Trait</h3> <p style="color: #aaa; font-size: 12px; margin: 0 0 10px 0;">Only positive traits can be stored. One of each trait maximum.</p> <!-- Physical Traits --> <<if $physicalTraits && $physicalTraits.length > 0>> <h4 style="color: #51cf66; margin: 10px 0 5px 0;">Physical Traits</h4> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _trait range $physicalTraits>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <<if _traitValue >= 0 && _trait !== "Soul">> <<set _alreadyStored = $traitStorage.some(function(t) { return t.name === _trait; })>> <<capture _trait>> <<if _alreadyStored>> <div style="background: #333; color: #666; padding: 5px 10px; border-radius: 5px; font-size: 12px;"><<print _trait>> (stored)</div> <<else>> <<link "<div style='background: #2d2d2d; border: 1px solid #51cf66; color: #51cf66; padding: 5px 10px; border-radius: 5px; font-size: 12px; cursor: pointer;'><<print _trait>></div>">> <<run setup.fishing.storeTraitToStorage("physical", _trait)>> <<goto "Inventory">> <</link>> <</if>> <</capture>> <</if>> <</for>> </div> <</if>> <!-- Mental Traits --> <<if $mentalTraits && $mentalTraits.length > 0>> <h4 style="color: #9b59b6; margin: 10px 0 5px 0;">Mental Traits</h4> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _trait range $mentalTraits>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<if _traitValue >= 0 && _trait !== "Soul">> <<set _alreadyStored = $traitStorage.some(function(t) { return t.name === _trait; })>> <<capture _trait>> <<if _alreadyStored>> <div style="background: #333; color: #666; padding: 5px 10px; border-radius: 5px; font-size: 12px;"><<print _trait>> (stored)</div> <<else>> <<link "<div style='background: #2d2d2d; border: 1px solid #9b59b6; color: #9b59b6; padding: 5px 10px; border-radius: 5px; font-size: 12px; cursor: pointer;'><<print _trait>></div>">> <<run setup.fishing.storeTraitToStorage("mental", _trait)>> <<goto "Inventory">> <</link>> <</if>> <</capture>> <</if>> <</for>> </div> <</if>> </div> <</if>> <</if>> <<elseif $inventoryTab === "food">> <!-- Food Tab Content --> <h2 style="color: #51cf66; margin: 0 0 15px 0;">🍽️ Cooked Meals</h2> <<if !$foodInventory>><<set $foodInventory = []>><</if>> <<if $foodInventory.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 15px;"> <<for _i, _food range $foodInventory>> <<set _buffDef = setup.foodBuffs[_food.buffId]>> <<capture _i, _food, _buffDef>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; border-radius: 10px; padding: 15px;"> <div style="display: flex; align-items: center; gap: 12px; margin-bottom: 12px;"> <div style="font-size: 36px;"><<print _buffDef ? _buffDef.icon : "🍽️">></div> <div style="flex: 1;"> <div style="color: #51cf66; font-weight: bold; font-size: 16px;"><<print _food.name>></div> <div style="color: #888; font-size: 12px;"><<print _buffDef ? _buffDef.name : "Unknown Buff">></div> </div> </div> <div style="background: #0a0a0a; padding: 10px; border-radius: 6px; margin-bottom: 12px;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 5px 0;"><<print _buffDef ? _buffDef.description : "">></p> <p style="color: #1e90ff; font-size: 12px; margin: 0;">Duration: <<print Math.floor(_food.buffDuration / 60)>> hours</p> </div> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🍴 Eat</div>">> <<set $eatFoodIndex = _i>> <<goto "EatFood">> <</link>><<if setup.slime.isPlayerSlimeBodied()>><<link "<div style='background: #7dd3fc; color: #06283d; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 6px;'>🫧 Absorb (+15 slime)</div>">><<run setup.slime.absorbFood(_i)>><<set $inventoryTab = "food">><<goto "Inventory">><</link>><</if>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background-color: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="font-size: 36px; margin-bottom: 10px;">🍽️</div> <div style="color: #888; font-size: 14px;">No cooked meals in storage. Cook something in your kitchen!</div> </div> <</if>> <<elseif $inventoryTab === "notes">> <!-- Notes Tab Content --> <h2 style="color: #fbbf24; margin: 0 0 15px 0;">📝 Notes</h2> <<if !$notes>><<set $notes = []>><</if>> <<if typeof $noteFormTitle !== "string">><<set $noteFormTitle = "">><</if>> <<if typeof $noteFormBody !== "string">><<set $noteFormBody = "">><</if>> <<if typeof $noteFormOpen !== "boolean">><<set $noteFormOpen = false>><</if>> <<if typeof $noteEditId !== "string">><<set $noteEditId = "">><</if>> <!-- Add / Close Note button --> <div style="display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 14px; align-items: center;"> <<if !$noteFormOpen>> <<link "<div style='background: #fbbf24; color: #1a1a1a; padding: 10px 18px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 14px; display: inline-block;'>➕ Add Note</div>">> <<set $noteFormOpen = true>> <<set $noteEditId = "">> <<set $noteFormTitle = "">> <<set $noteFormBody = "">> <<goto "Inventory">> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #888; color: #ccc; padding: 10px 18px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 14px; display: inline-block;'>✕ Close Form</div>">> <<set $noteFormOpen = false>> <<set $noteEditId = "">> <<set $noteFormTitle = "">> <<set $noteFormBody = "">> <<goto "Inventory">> <</link>> <</if>> <span style="color: #888; font-size: 13px;"><<print $notes.length>> note<<if $notes.length !== 1>>s<</if>></span> </div> <!-- New / Edit Note Form (only shown when open) --> <<if $noteFormOpen>> <<set _isEditing = $noteEditId !== "">> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #fbbf24; border-radius: 10px; padding: 16px; margin-bottom: 18px; box-shadow: 0 0 15px rgba(251,191,36,0.2);"> <div style="color: #fbbf24; font-weight: bold; font-size: 15px; margin-bottom: 10px;"><<if _isEditing>>📝 Editing Note<<else>>✏️ New Note<</if>></div> <div style="margin-bottom: 10px;"> <label style="display: block; color: #aaa; font-size: 12px; margin-bottom: 4px;">Title</label> <<textbox "$noteFormTitle" $noteFormTitle>> </div> <div style="margin-bottom: 12px;"> <label style="display: block; color: #aaa; font-size: 12px; margin-bottom: 4px;">Body</label> <<textarea "$noteFormBody" $noteFormBody>> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<link "<div style='background: #fbbf24; color: #1a1a1a; padding: 10px 18px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 14px; display: inline-block;'>💾 Save Note</div>">> <<if ($noteFormTitle && $noteFormTitle.trim() !== "") || ($noteFormBody && $noteFormBody.trim() !== "")>> <<if $noteEditId !== "">> <<set _editIdx = $notes.findIndex(function(n){ return n.id === $noteEditId; })>> <<if _editIdx >= 0>> <<set $notes[_editIdx].title = ($noteFormTitle || "").trim() || "Untitled">> <<set $notes[_editIdx].body = $noteFormBody || "">> <<set $notes[_editIdx].updatedAt = Date.now()>> <</if>> <<else>> <<set _newNoteId = "n_" + Date.now() + "_" + Math.floor(Math.random() * 1000)>> <<run $notes.push({ id: _newNoteId, title: ($noteFormTitle || "").trim() || "Untitled", body: $noteFormBody || "", createdAt: Date.now(), collapsed: false })>> <</if>> <<set $noteFormTitle = "">> <<set $noteFormBody = "">> <<set $noteEditId = "">> <<set $noteFormOpen = false>> <</if>> <<goto "Inventory">> <</link>> <<if $noteEditId !== "">> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #888; color: #ccc; padding: 10px 18px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 14px; display: inline-block;'>Cancel Edit</div>">> <<set $noteEditId = "">> <<set $noteFormTitle = "">> <<set $noteFormBody = "">> <<set $noteFormOpen = false>> <<goto "Inventory">> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #888; color: #ccc; padding: 10px 18px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 14px; display: inline-block;'>Clear Fields</div>">> <<set $noteFormTitle = "">> <<set $noteFormBody = "">> <<goto "Inventory">> <</link>> <</if>> </div> </div> <</if>> <!-- Saved Notes List --> <<if $notes.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px;"> <<for _i, _note range $notes>> <<capture _i, _note>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #fbbf24; border-radius: 10px; padding: 14px; box-shadow: 0 0 12px rgba(251,191,36,0.15);"> <!-- Title row with minimize button --> <div style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;"> <div style="color: #fbbf24; font-weight: bold; font-size: 15px; flex: 1; word-break: break-word;"><<print _note.title>></div> <<link "<div style='background: rgba(251,191,36,0.15); border: 1px solid #fbbf24; color: #fbbf24; width: 28px; height: 28px; border-radius: 6px; text-align: center; line-height: 26px; cursor: pointer; font-weight: bold; font-size: 14px; flex-shrink: 0;'><<if _note.collapsed>>▼<<else>>▲<</if>></div>">> <<set $notes[_i].collapsed = !$notes[_i].collapsed>> <<goto "Inventory">> <</link>> </div> <<if !_note.collapsed>> <div style="color: #ccc; font-size: 13px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; background: #0a0a0a; padding: 10px; border-radius: 6px; margin-bottom: 10px; max-height: 220px; overflow-y: auto;"><<print _note.body && _note.body.length > 0 ? _note.body : "(empty)">></div> <</if>> <div style="color: #666; font-size: 11px; margin-bottom: 10px;"> Saved <<print new Date(_note.createdAt).toLocaleString()>><<if _note.updatedAt && _note.updatedAt !== _note.createdAt>> · Edited <<print new Date(_note.updatedAt).toLocaleString()>><</if>> </div> <div style="display: flex; gap: 8px; flex-wrap: wrap;"> <<link "<div style='background: rgba(125,211,252,0.15); border: 1px solid #7dd3fc; color: #7dd3fc; padding: 8px 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px; flex: 1;'>✏️ Edit</div>">> <<set $noteEditId = _note.id>> <<set $noteFormTitle = _note.title || "">> <<set $noteFormBody = _note.body || "">> <<set $noteFormOpen = true>> <<goto "Inventory">> <</link>> <<link "<div style='background: rgba(255,107,107,0.15); border: 1px solid #ff6b6b; color: #ff6b6b; padding: 8px 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px; flex: 1;'>🗑️ Delete</div>">> <<set $notes = $notes.filter(function(n){ return n.id !== _note.id; })>> <<if $noteEditId === _note.id>> <<set $noteEditId = "">> <<set $noteFormOpen = false>> <</if>> <<goto "Inventory">> <</link>> </div> </div> <</capture>> <</for>> </div> <<else>> <div style="background-color: #1a1a1a; padding: 30px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="font-size: 36px; margin-bottom: 10px;">📝</div> <div style="color: #888; font-size: 14px;">No notes yet. Click the Add Note button above to create one.</div> </div> <</if>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<if !$giftInventory || !$giftInventory.sake_bottle || $giftInventory.sake_bottle <= 0>> <<set $sakeDrinkMessage = "You have no sake bottles to drink.">> <<else>> <<run (function () { var V = State.variables; V.giftInventory.sake_bottle -= 1; if (V.giftInventory.sake_bottle <= 0) delete V.giftInventory.sake_bottle; if (typeof advanceTime === "function") { advanceTime(5); } else if (typeof window !== "undefined" && typeof window.advanceTime === "function") { window.advanceTime(5); } var msg = (setup.oni && typeof setup.oni.onDrinkSake === "function") ? setup.oni.onDrinkSake() : "You drink the sake. It is warm and slightly sweet."; V.sakeDrinkMessage = msg; })()>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="max-width: 640px; margin: 60px auto 0 auto; background: linear-gradient(135deg, #2a1a1a 0%, #1a0a0a 100%); border: 3px solid #b94747; border-radius: 12px; padding: 28px; box-shadow: 0 0 24px rgba(185,71,71,0.35);"> <h2 style="color: #ffb0a0; margin: 0 0 14px 0; text-align: center;">🍶 Sake Bottle</h2> <div style="color: #e8d0c0; font-size: 15px; line-height: 1.6; text-align: center; white-space: pre-wrap;"><<= $sakeDrinkMessage>></div> <div style="text-align: center; margin-top: 22px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #b94747; color: white; padding: 14px 28px; border-radius: 10px; font-weight: bold; font-size: 15px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue</div>">><<goto $lastLocation>><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<if !$viewingNPC || !$relationships[$viewingNPC]>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">Error: NPC not found</h1> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2);'>← Back</div>">> <<set $viewingNPC = null>> <<goto $lastLocation>> <</link>> </div> </div> <<else>> <<set _npc = setup.getNPCByName($viewingNPC)>> <<set _rel = $relationships[$viewingNPC]>> <<set _relColor = setup.getRelationshipColor(_rel.level)>> <<set _levelData = setup.getRelationshipLevelData(_rel.level)>> <<set _levelName = _levelData ? _levelData.name : "Unknown">> <<set _isRomantic = setup.romance.isRomantic($viewingNPC)>> <<set _barPoints = _rel.points>> <<set _barLevelNum = _rel.level>> <<set _showBar = (_rel.level < 5)>> <<if _isRomantic>> <<set _romLevel = setup.romance.getRomanceLevel($viewingNPC)>> <<set _romData = setup.romance.levels[_romLevel]>> <<if _romData>><<set _levelName = _romData.icon + " " + _romData.name>><<set _relColor = _romData.color>><</if>> <<set _romLevelOrder = ["dating", "exclusive", "lover", "soulmate"]>> <<set _romThresholds = [75, 175, 350, 600]>> <<set _romIdx = _romLevelOrder.indexOf(_romLevel)>> <<if _romIdx < 0>><<set _romIdx = 0>><</if>> <<set _barLevelNum = _romIdx + 1>> <<set _currentLevelMin = _romThresholds[_romIdx]>> <<if _romIdx < 3>><<set _nextThreshold = _romThresholds[_romIdx + 1]>><<else>><<set _nextThreshold = _romThresholds[3]>><</if>> <<set _barPoints = ($npcRomance && $npcRomance[$viewingNPC] && typeof $npcRomance[$viewingNPC].romancePoints === "number") ? $npcRomance[$viewingNPC].romancePoints : 0>> <<set _showBar = (_romLevel !== "soulmate")>> <<if _showBar>> <<set _xpInLevel = _barPoints - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <<if _xpPercent < 0>><<set _xpPercent = 0>><</if>> <<if _xpPercent > 100>><<set _xpPercent = 100>><</if>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div @style="'padding: 20px; background: linear-gradient(135deg, ' + _relColor + ' 0%, ' + _relColor + 'aa 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid ' + _relColor + '; box-shadow: 0 0 20px ' + _relColor + '66;'"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);"><<print $viewingNPC>></h1> </div> <!-- Relationship Status Card --> <div @style="'background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid ' + _relColor + '; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px ' + _relColor + '44; margin-bottom: 20px;'"> <h2 @style="'color: ' + _relColor + '; margin: 0 0 15px 0; text-shadow: 0 0 10px ' + _relColor + '88;'">Relationship Status</h2> <div style="background-color: #0a0a0a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> <span style="color: #fff; font-weight: bold; font-size: 18px;"><<print _levelName>> (Level <<print _barLevelNum>>)</span> <<if _showBar>> <<if !_isRomantic>> <<if _rel.level === -1>> <<set _currentLevelMin = -50>> <<set _nextThreshold = 0>> <<elseif _rel.level === 0>> <<set _currentLevelMin = 0>> <<set _nextThreshold = 25>> <<elseif _rel.level === 1>> <<set _currentLevelMin = 25>> <<set _nextThreshold = 75>> <<elseif _rel.level === 2>> <<set _currentLevelMin = 75>> <<set _nextThreshold = 175>> <<elseif _rel.level === 3>> <<set _currentLevelMin = 175>> <<set _nextThreshold = 425>> <<else>> <<set _currentLevelMin = 425>> <<set _nextThreshold = 600>> <</if>> <<set _xpInLevel = _rel.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <<if _xpPercent < 0>><<set _xpPercent = 0>><</if>> <<if _xpPercent > 100>><<set _xpPercent = 100>><</if>> <</if>> <span @style="'color: ' + _relColor + '; font-weight: bold; font-size: 18px;'"><<print _barPoints>> / <<print _nextThreshold>> points</span> <<else>> <span @style="'color: ' + _relColor + '; font-weight: bold; font-size: 18px;'">MAX LEVEL</span> <</if>> </div> <<if _showBar>> <!-- XP Progress Bar --> <div @style="'background-color: #000; border-radius: 10px; height: 25px; overflow: hidden; border: 2px solid ' + _relColor + '; box-shadow: inset 0 2px 4px rgba(0,0,0,0.8); position: relative;'"> <div @style="'background: linear-gradient(90deg, ' + _relColor + ' 0%, ' + _relColor + 'dd 100%); height: 100%; width: ' + _xpPercent + '%; transition: width 0.3s ease; box-shadow: 0 0 15px ' + _relColor + '; position: relative; overflow: hidden;'"> <<if _xpPercent > 0>> <div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.3) 50%, transparent 100%); background-size: 200% 100%; animation: shimmer 2s infinite;"></div> <</if>> </div> </div> <p style="color: #aaa; margin: 10px 0 0 0; font-size: 14px;"> <<print _nextThreshold - _barPoints>> points until next level </p> <<else>> <p style="color: #ff6b9d; margin: 10px 0 0 0; font-size: 14px; font-weight: bold;"> Maximum relationship level! </p> <</if>> </div> </div> <!-- NPC Information Card --> <<if _npc>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #4dabf7; margin: 0 0 15px 0;">Character Information</h2> <!-- Basic Info with Image --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <div style="display: flex; gap: 20px; align-items: flex-start;"> <!-- Stats Grid --> <div style="flex: 1; display: grid; grid-template-columns: 1fr 1fr; gap: 15px; color: #e0e0e0; font-size: 15px;"> <div> <strong style="color: #4dabf7;">Job:</strong><br> <<print _npc.jobs && _npc.jobs.length > 0 ? _npc.jobs.join(", ") : "Unemployed">> </div> <div> <strong style="color: #4dabf7;">Gender:</strong><br> <<print _npc.bodyParts.gender.charAt(0).toUpperCase() + _npc.bodyParts.gender.slice(1)>> </div> <div> <strong style="color: #4dabf7;">Age:</strong><br> <<print _npc.appearance.age>> </div> <div> <strong style="color: #4dabf7;">Skin Tone:</strong><br> <<print _npc.appearance.skinTone.charAt(0).toUpperCase() + _npc.appearance.skinTone.slice(1)>> </div> <div> <strong style="color: #4dabf7;">Hair:</strong><br> <<print _npc.appearance.hairLength ? (_npc.appearance.hairLength.charAt(0).toUpperCase() + _npc.appearance.hairLength.slice(1)) : "Unknown">> <<print _npc.appearance.hairColor>> </div> <div> <strong style="color: #4dabf7;">Build:</strong><br> <<print _npc.appearance.physique.charAt(0).toUpperCase() + _npc.appearance.physique.slice(1)>> </div> <div> <strong style="color: #4dabf7;">Chest:</strong><br> <<print _npc.bodyParts.chest.charAt(0).toUpperCase() + _npc.bodyParts.chest.slice(1)>> </div> <div> <strong style="color: #4dabf7;">Butt:</strong><br> <<print _npc.bodyParts.butt.charAt(0).toUpperCase() + _npc.bodyParts.butt.slice(1)>> </div> <div style="grid-column: 1 / -1;"> <strong style="color: #4dabf7;">Genitals:</strong><br> <<print (_npc.bodyParts.genitals || "Unknown").charAt(0).toUpperCase() + (_npc.bodyParts.genitals || "Unknown").slice(1)>> </div> </div> <!-- NPC Image --> <<if $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <<set _npcImage = setup.getNPCImage(_npc.name)>> <<if _npcImage>> <div style="flex-shrink: 0;"> <img @src="_npcImage" style="max-width: 250px; max-height: 350px; border-radius: 8px; border: 2px solid #4dabf7; box-shadow: 0 0 15px rgba(77,171,247,0.4);" onerror="this.style.display='none';"> </div> <</if>> <</if>> </div> </div> <!-- Stats --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Stats</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; color: #e0e0e0; font-size: 15px;"> <div> <span style="color: #ff6b6b;">■</span> <strong>Strength:</strong> <<print _npc.stats.strength>> </div> <div> <span style="color: #51cf66;">■</span> <strong>Dexterity:</strong> <<print _npc.stats.dexterity>> </div> <div> <span style="color: #ffd43b;">■</span> <strong>Charisma:</strong> <<print _npc.stats.charisma>> </div> <div> <span style="color: #4dabf7;">■</span> <strong>Intelligence:</strong> <<print _npc.stats.intelligence>> </div> </div> </div> <!-- Physical Traits --> <<if _npc.physicalTraits && _npc.physicalTraits.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Physical Traits</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _j = 0; _j < _npc.physicalTraits.length; _j++>> <<if _npc.physicalTraits[_j] !== "Short Hair" && _npc.physicalTraits[_j] !== "Long Hair">> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #51cf66; padding: 6px 12px; border-radius: 15px; font-size: 13px; border: 1px solid #51cf66; box-shadow: 0 0 5px #51cf6644;"> <<print _npc.physicalTraits[_j]>> </span> <</if>> <</for>> </div> </div> <</if>> <!-- Mental Traits --> <<if _npc.mentalTraits && _npc.mentalTraits.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Mental Traits</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _j = 0; _j < _npc.mentalTraits.length; _j++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #9b59b6; padding: 6px 12px; border-radius: 15px; font-size: 13px; border: 1px solid #9b59b6; box-shadow: 0 0 5px #9b59b644;"> <<print _npc.mentalTraits[_j]>> </span> <</for>> </div> </div> <</if>> <!-- Skills --> <<if _npc.skills && _npc.skills.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Skills</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _j = 0; _j < _npc.skills.length; _j++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #ffd43b; padding: 6px 12px; border-radius: 15px; font-size: 13px; border: 1px solid #ffd43b; box-shadow: 0 0 5px #ffd43b44;"> <<print _npc.skills[_j]>> </span> <</for>> </div> </div> <</if>> </div> <</if>> <!-- Current Location (Level 3+) --> <<if _rel.level >= 3>> <<set _currentDay = $dayOfWeek || "Monday">> <<set _currentHour = Math.floor($timeInMinutes / 60) % 24>> <<set _npcLocation = setup.getNPCLocation(_npc, _currentDay, _currentHour)>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #51cf66; margin: 0 0 15px 0;">📍 Current Location</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <<if _npcLocation>> <div style="color: #e0e0e0; font-size: 16px; text-align: center;"> <span style="color: #51cf66; font-weight: bold; font-size: 18px;"> <<print _npcLocation.replace(/([A-Z])/g, ' $1').trim()>> </span> </div> <div style="color: #aaa; font-size: 14px; text-align: center; margin-top: 8px;"> As of <<print _currentDay>>, <<print _currentHour>>:00 </div> <<else>> <div style="color: #ff6b6b; font-size: 16px; text-align: center;"> Location unknown </div> <</if>> </div> <p style="color: #aaa; margin: 10px 0 0 0; font-size: 13px; font-style: italic; text-align: center;"> You know where they are! </p> </div> <</if>> <!-- Desired Traits (Level 4+) --> <<if (_rel.level >= 4 || (_npc && setup.witchSpells && setup.witchSpells.sandmanActiveFor(_npc.name))) && _npc>> <<set _tradePrefs = setup.npcTradingPreferences[_npc.name] || null>> <<if _tradePrefs && _tradePrefs.desires>> <<set _desires = _tradePrefs.desires>> <<set _hasDesires = (_desires.skills && _desires.skills.length > 0) || (_desires.mental && _desires.mental.length > 0) || (_desires.physical && _desires.physical.length > 0) || (_desires.bodyParts && _desires.bodyParts.length > 0) || (_desires.chestSize && _desires.chestSize.length > 0) || (_desires.buttSize && _desires.buttSize.length > 0) || (_desires.genitals && _desires.genitals.length > 0)>> <<if _hasDesires>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #e83e8c; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(232, 62, 140, 0.3); margin-bottom: 20px;"> <h2 style="color: #e83e8c; margin: 0 0 15px 0;">💝 Desired Traits</h2> <p style="color: #aaa; margin: 0 0 15px 0; font-size: 13px; font-style: italic;"> <<if _rel.level < 4>> They told you in their sleep, in a way. Their wants drift plainly on the surface today. <<else>> Your close relationship has revealed what traits they desire in trades. <</if>> </p> <<if _desires.skills && _desires.skills.length > 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 10px; border: 1px solid #333;"> <h4 style="color: #ffd43b; margin: 0 0 8px 0; font-size: 14px;">Skills Wanted:</h4> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _i = 0; _i < _desires.skills.length; _i++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #ffd43b; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid #ffd43b;"> <<print _desires.skills[_i]>> </span> <</for>> </div> </div> <</if>> <<if _desires.mental && _desires.mental.length > 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 10px; border: 1px solid #333;"> <h4 style="color: #9b59b6; margin: 0 0 8px 0; font-size: 14px;">Mental Traits Wanted:</h4> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _i = 0; _i < _desires.mental.length; _i++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #9b59b6; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid #9b59b6;"> <<print _desires.mental[_i]>> </span> <</for>> </div> </div> <</if>> <<if _desires.physical && _desires.physical.length > 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 10px; border: 1px solid #333;"> <h4 style="color: #51cf66; margin: 0 0 8px 0; font-size: 14px;">Physical Traits Wanted:</h4> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _i = 0; _i < _desires.physical.length; _i++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #51cf66; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid #51cf66;"> <<print _desires.physical[_i]>> </span> <</for>> </div> </div> <</if>> <<if _desires.chestSize && _desires.chestSize.length > 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 10px; border: 1px solid #333;"> <h4 style="color: #ff6b9d; margin: 0 0 8px 0; font-size: 14px;">Chest Size Wanted:</h4> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _i = 0; _i < _desires.chestSize.length; _i++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #ff6b9d; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid #ff6b9d;"> <<print _desires.chestSize[_i].charAt(0).toUpperCase() + _desires.chestSize[_i].slice(1)>> </span> <</for>> </div> </div> <</if>> <<if _desires.buttSize && _desires.buttSize.length > 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 10px; border: 1px solid #333;"> <h4 style="color: #ff9f43; margin: 0 0 8px 0; font-size: 14px;">Butt Size Wanted:</h4> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _i = 0; _i < _desires.buttSize.length; _i++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #ff9f43; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid #ff9f43;"> <<print _desires.buttSize[_i].charAt(0).toUpperCase() + _desires.buttSize[_i].slice(1)>> </span> <</for>> </div> </div> <</if>> <<if _desires.genitals && _desires.genitals.length > 0>> <div style="background-color: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333;"> <h4 style="color: #a29bfe; margin: 0 0 8px 0; font-size: 14px;">Genitals Wanted:</h4> <div style="display: flex; flex-wrap: wrap; gap: 6px;"> <<for _i = 0; _i < _desires.genitals.length; _i++>> <span style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #a29bfe; padding: 4px 10px; border-radius: 12px; font-size: 12px; border: 1px solid #a29bfe;"> <<print _desires.genitals[_i].charAt(0).toUpperCase() + _desires.genitals[_i].slice(1)>> </span> <</for>> </div> </div> <</if>> </div> <</if>> <</if>> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2);'>← Back</div>">> <<set $viewingNPC = null>> <<goto $lastLocation>> <</link>> </div> </div> <</if>> <</nobr>> <style> @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } </style>
<<nobr>> <<set $lastLocation = "GymLockerRoom">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("GymLockerRoom")>> <<run $visitedLocations.push("GymLockerRoom")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #667eeaaa 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea; box-shadow: 0 0 20px #667eea66;"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">🚿 Locker Room</h1> </div> <!-- Shower Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #667eea; margin: 0 0 15px 0;">💧 Shower</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6; margin: 0;"> The locker room is clean and well-maintained. Rows of lockers line the walls, and you can hear the sound of running water from the shower stalls. </p> </div> <span id="showerMessage"></span> <<link "<div style='background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>🚿 Take a Shower</div>">> <<run advanceTime(15)>> <<run setup.addBuff("shower_fresh", 180)>> <<run setup.setHairMessy()>> <<replace "#showerMessage">> <div style="background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #51cf66;"> <p style="color: white; font-size: 16px; font-weight: bold; margin: 0; text-align: center;"> ✨ You take a refreshing shower and feel clean and rejuvenated! 🚿 Fresh & Clean buff gained (+15% trading bonus, 3h). </p> </div> <</replace>> <</link>> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); display: inline-block;'>← Back</div>">> <<goto "OpahFitness">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "GymNPCs">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("GymNPCs")>> <<run $visitedLocations.push("GymNPCs")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #e91e63aa 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63; box-shadow: 0 0 20px #e91e6366;"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">👥 Gym Floor</h1> </div> <!-- Get NPCs at this location --> <<set _npcsHere = setup.getNPCsAtLocation("GymNPCs")>> <<if _npcsHere && _npcsHere.length > 0>> <!-- NPCs Present --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #f48fb1; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic;"> You spot some people working out on the gym floor... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #f48fb1; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <!-- Empty State --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 40px; border-radius: 12px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4); text-align: center;"> <div style="font-size: 64px; margin-bottom: 20px;">🏋️</div> <h2 style="color: #e91e63; margin: 0 0 15px 0;">Nobody Around Right Now</h2> <p style="color: #aaa; font-size: 16px; line-height: 1.6; max-width: 500px; margin: 0 auto;"> The gym floor is pretty empty at the moment. You don't see anyone you can chat with right now. Maybe try coming back later? </p> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); display: inline-block;'>← Back</div>">> <<goto "OpahFitness">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubVIP">> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 30px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FFD700; box-shadow: 0 0 30px rgba(255, 215, 0, 0.5), inset 0 0 20px rgba(255, 165, 0, 0.2);"> <h1 style="color: #FFD700; text-align: center; margin: 0; font-size: 36px; text-shadow: 0 0 20px rgba(255, 215, 0, 0.8), 0 0 40px rgba(255, 165, 0, 0.6);">👑 VIP Lounge</h1> <p style="color: #FFE4B5; text-align: center; margin: 10px 0 0 0; font-size: 18px; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Elite Members Only </p> </div> <!-- Description --> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 30px; border-radius: 15px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.4), 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 30px; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FFD700, #9D00FF, #FFD700, transparent); opacity: 0.8;"></div> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Behind the velvet rope lies true luxury. The VIP lounge is bathed in soft purple and gold lighting, with plush leather booths and champagne on ice. Here, the club's most exclusive services are available—intimate performances by the best strippers, complete privacy, and absolute discretion. </p> </div> <!-- Available Strippers (schedule-aware) --> <<set _strippers = setup.getNPCsAtLocation("StripClub").filter(function(n) { return n.jobs && n.jobs.includes("Stripper"); })>> <<if _strippers && _strippers.length > 0>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💃 Available Strippers</h2> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 25px; border-radius: 15px; margin-bottom: 30px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.3);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;"> <<for _npc range _strippers>> <<capture _npc>> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 20px rgba(255, 20, 147, 0.3), 0 8px 16px rgba(0,0,0,0.6); position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h3 style="color: #FF1493; margin: 0 0 15px 0; font-size: 24px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);"><<= _npc.name>></h3> <!-- Service Options --> <div style="background: #0a0a0a; padding: 15px; border-radius: 10px; margin-bottom: 15px; border: 2px solid #FFD700; box-shadow: 0 0 15px rgba(255, 215, 0, 0.2);"> <p style="color: #FFD700; font-size: 18px; font-weight: bold; margin: 0 0 8px 0; text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);">💎 Private Dance: $500</p> <p style="color: #D8BFD8; font-size: 14px; margin: 0; line-height: 1.5;">An intimate, personal performance just for you. One-on-one in a private room.</p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<if $money >= 500>> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 15px rgba(255, 20, 147, 0.5); font-size: 14px;'>💃 Book Show</div>">> <<set $money -= 500>> <<set $currentVIPStriper = _npc>> <<goto "StripClubVIPPrivateDance">> <</link>> <<else>> <div style='background: #444; color: #666; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: not-allowed; font-size: 14px; border: 2px solid #666;'>💃 Book Show</div> <</if>> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 12px rgba(157, 0, 255, 0.4); font-size: 14px;'>💬 Chat</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💃 Available Strippers</h2> <div style="background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; border: 3px solid #666; box-shadow: 0 0 15px rgba(102, 102, 102, 0.2);"> <p style="text-align: center; color: #888; margin: 0; font-style: italic; font-size: 16px;"> No strippers are available in the VIP lounge right now. Check back later. </p> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #444 100%); color: white; padding: 14px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #888;'>← Back to Main Floor</div>">> <<goto "StripClub">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubVIPPrivateDance">> <!-- Initialize private dance variables --> <<set $privateDanceTips = 0>> <<set $privateDanceStage = 1>> <<set $privateDanceActions = []>> <<set $privateDanceMistreated = false>> <!-- Get NPC info --> <<set _stripper = $currentVIPStriper>> <<set _stripperGender = (_stripper.bodyParts && _stripper.bodyParts.gender) || _stripper.gender || "female">> <<set _playerGender = $bodyParts.gender || "male">> <!-- Check traits --> <<set _isSeductive = _stripper.physicalTraits && _stripper.physicalTraits.includes("Seductive")>> <<set _isConfident = _stripper.mentalTraits && _stripper.mentalTraits.includes("Confident")>> <<set _isShy = _stripper.mentalTraits && _stripper.mentalTraits.includes("Shy")>> <<set _isAlluring = _stripper.physicalTraits && _stripper.physicalTraits.includes("Alluring")>> <<set _isGraceful = _stripper.physicalTraits && _stripper.physicalTraits.includes("Graceful")>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FF1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.5), inset 0 0 20px rgba(157, 0, 255, 0.2);"> <h1 style="color: #FF1493; text-align: center; margin: 0; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8), 0 0 40px rgba(157, 0, 255, 0.6);">💃 Private Dance</h1> <p style="color: #FFB6C1; text-align: center; margin: 10px 0 0 0; font-size: 18px; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> An Exclusive Performance by <<= _stripper.name>> </p> </div> <!-- Scene Setting --> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 35px; border-radius: 15px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.4), 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 30px; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #9D00FF, #FF1493, #9D00FF, transparent); opacity: 0.8;"></div> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The VIP room door closes with a soft click, sealing you in privacy. Purple and pink lights pulse gently across velvet walls. A plush chair sits in the center of the room, positioned perfectly for the show. </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _isShy>> <<= _stripper.name>> gives you a nervous but genuine smile, fingers fidgeting slightly. "Make yourself comfortable," <<if _stripperGender === "female">>she<<else>>he<</if>> says softly. The shyness only makes <<if _stripperGender === "female">>her<<else>>him<</if>> more endearing. <<elseif _isConfident>> <<= _stripper.name>> locks eyes with you, a confident smirk playing on <<if _stripperGender === "female">>her<<else>>his<</if>> lips. "Sit back and enjoy the show," <<if _stripperGender === "female">>she<<else>>he<</if>> purrs, voice dripping with self-assurance. <<elseif _isSeductive>> <<= _stripper.name>> circles you slowly, one finger trailing along your shoulder. "I'm going to make this worth every penny," <<if _stripperGender === "female">>she<<else>>he<</if>> whispers close to your ear, breath hot against your skin. <<else>> <<= _stripper.name>> gives you a warm smile. "Ready for your private show?" <<if _stripperGender === "female">>she<<else>>he<</if>> asks, already beginning to move to the music. <</if>> </p> <p style="color: #D8BFD8; font-size: 16px; line-height: 1.7; margin: 0; font-style: italic; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The music starts—a slow, sensual beat that seems to pulse in time with your heartbeat. </p> </div> <!-- Performance Stage 1 --> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 35px; border-radius: 15px; border: 3px solid #FF69B4; box-shadow: 0 0 25px rgba(255, 105, 180, 0.4), 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 30px; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF69B4, transparent); opacity: 0.8;"></div> <h3 style="color: #FF69B4; margin: 0 0 20px 0; font-size: 24px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.8);">🎭 The Show Begins</h3> <p style="color: #fff; font-size: 17px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _isGraceful>> <<= _stripper.name>> moves with liquid grace, each motion flowing perfectly into the next. <<if _stripperGender === "female">>Her<<else>>His<</if>> body sways hypnotically, hands gliding over <<if _stripperGender === "female">>her<<else>>his<</if>> curves in time with the music. <<else>> <<= _stripper.name>> begins to strip, body moving sensually to the rhythm. <<if _stripperGender === "female">>Her<<else>>His<</if>> hips roll in slow circles as <<if _stripperGender === "female">>she<<else>>he<</if>> runs hands through <<if _stripperGender === "female">>her<<else>>his<</if>> hair. <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> She turns slowly, giving you a view of her ass as she bends forward, looking back over her shoulder with a teasing smile. Her hands slide up her thighs, pushing her skirt higher... <<else>> He turns, showing you his toned back and ass as he moves. His hands slide over his chest, fingers teasing at the buttons of his shirt... <</if>> </p> </div> <!-- Tip Options --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 30px; border: 3px solid #FFD700; box-shadow: 0 0 20px rgba(255, 215, 0, 0.3);"> <h3 style="color: #FFD700; margin: 0 0 20px 0; text-align: center; text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);">💵 Show Your Appreciation</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <!-- Just Watch --> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #666;"> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Keep enjoying the standard show</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>👀 Just Watch</div>">> <<goto "StripClubVIPPrivateDanceStage2">> <</link>> </div> <!-- Tip $50 --> <<if $money >= 50>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0;">Show more skin, tease me</p> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💵 Tip $50</div>">> <<set $money -= 50>> <<set $privateDanceTips += 50>> <<run $privateDanceActions.push("tipped_stage1")>> <<goto "StripClubVIPPrivateDanceStage2">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #444; opacity: 0.5;"> <p style="color: #666; font-size: 14px; margin: 0 0 10px 0;">Show more skin, tease me</p> <div style='background: #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💵 Tip $50 (Broke)</div> </div> <</if>> <!-- Tip $100 --> <<if $money >= 100>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #FFD700;"> <p style="color: #FFD700; font-size: 14px; margin: 0 0 10px 0;">Get closer, let me touch</p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💰 Tip $100</div>">> <<set $money -= 100>> <<set $privateDanceTips += 100>> <<run $privateDanceActions.push("touching_stage1")>> <<goto "StripClubVIPPrivateDanceStage2">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #444; opacity: 0.5;"> <p style="color: #666; font-size: 14px; margin: 0 0 10px 0;">Get closer, let me touch</p> <div style='background: #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💰 Tip $100 (Broke)</div> </div> <</if>> </div> <p style="color: #888; font-size: 13px; margin: 15px 0 0 0; text-align: center; font-style: italic;"> Tips given: $<<print $privateDanceTips>> • Current balance: $<<print $money>> </p> </div> </div> <</nobr>>
<<nobr>> <!-- Initialize dance progress if needed --> <<if !$danceProgress>> <<set $danceProgress = 0>> <</if>> <!-- Increment weekly group lesson counter --> <<if !$weeklyDanceGroupLessons>> <<set $weeklyDanceGroupLessons = {week: Math.floor($dayNumber / 7), count: 0}>> <</if>> <<set $weeklyDanceGroupLessons.count += 1>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b9d 0%, #f06595 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b9d; box-shadow: 0 0 20px #ff6b9d66;"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">🩰 Group Dance Lesson</h1> </div> <!-- Lesson Description --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; border: 3px solid #ff6b9d; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px; text-align: center;"> <div style="font-size: 64px; margin-bottom: 20px;">💃</div> <h2 style="color: #ff6b9d; margin: 0 0 15px 0;">A Graceful Session</h2> <p style="color: #e0e0e0; font-size: 18px; line-height: 1.6; max-width: 600px; margin: 0 auto 20px auto;"> You spend an hour learning choreography and practicing your movements. The instructor guides the group through various steps and techniques, helping you develop your coordination and grace. </p> </div> <!-- Stat Gain --> <<set $stats.dexterity += 1>> <div style="background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #51cf66; text-align: center;"> <p style="color: white; font-size: 16px; font-weight: bold; margin: 0;"> 💪 +1 Dexterity! </p> </div> <!-- Dancer Trait Progress --> <<if $skills.includes("Dancing")>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <p style="color: #000; font-size: 18px; font-weight: bold; margin: 0;"> ⭐ You already have the Dancing skill! </p> </div> <<else>> <<set _danceChance = random(1, 100)>> <<if _danceChance <= 3>> <<run $skills.push("Dancing")>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <div style="font-size: 48px; margin-bottom: 10px;">✨</div> <p style="color: #000; font-size: 20px; font-weight: bold; margin: 0;"> 🎉 Congratulations! You've learned the Dancing skill! </p> </div> <<else>> <<set $danceProgress += 1>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #ff6b9d;"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0; text-align: center;">🎯 Dancing Skill Progress</h3> <p style="color: #e0e0e0; text-align: center; margin: 0 0 15px 0;">Keep practicing! You're getting closer to mastering dance.</p> <div style="background: #0a0a0a; border-radius: 6px; padding: 10px; border: 1px solid #444;"> <p style="color: #aaa; font-size: 14px; margin: 0; text-align: center;"> Sessions completed: <span style="color: #ff6b9d; font-weight: bold;"><<= $danceProgress>></span> </p> <p style="color: #aaa; font-size: 13px; margin: 5px 0 0 0; text-align: center; font-style: italic;"> (3% chance per session with group lessons) </p> </div> </div> <</if>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); display: inline-block;'>← Back to Studio</div>">> <<run advanceTime(60)>> <<goto "DanceStudio">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Initialize coach sessions if needed --> <<if !$danceCoachSessions>> <<set $danceCoachSessions = 0>> <</if>> <!-- Increment weekly private lesson counter --> <<if !$weeklyDancePrivateLessons>> <<set $weeklyDancePrivateLessons = {week: Math.floor($dayNumber / 7), count: 0}>> <</if>> <<set $weeklyDancePrivateLessons.count += 1>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700; box-shadow: 0 0 20px #FFD70066;"> <h1 style="color: #000; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(255,255,255,0.3);">👥 Private Coaching Session</h1> </div> <!-- Lesson Description --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px; text-align: center;"> <div style="font-size: 64px; margin-bottom: 20px;">🌟</div> <h2 style="color: #FFD700; margin: 0 0 15px 0;">Intensive One-on-One Training</h2> <p style="color: #e0e0e0; font-size: 18px; line-height: 1.6; max-width: 600px; margin: 0 auto 20px auto;"> Your private coach dedicates their full attention to refining your technique. Every movement is analyzed and perfected, pushing your abilities to new heights. The personalized instruction accelerates your progress dramatically. </p> </div> <!-- Stat Gain --> <<set $stats.dexterity += 5>> <div style="background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #51cf66; text-align: center;"> <p style="color: white; font-size: 16px; font-weight: bold; margin: 0;"> 💪 +5 Dexterity! </p> </div> <!-- Dancer Trait Progress --> <<if $skills.includes("Dancing")>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <p style="color: #000; font-size: 18px; font-weight: bold; margin: 0;"> ⭐ You've already mastered the Dancing skill! </p> </div> <<else>> <<set $danceCoachSessions += 1>> <<if $danceCoachSessions >= 3>> <<run $skills.push("Dancing")>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <div style="font-size: 64px; margin-bottom: 10px;">✨</div> <p style="color: #000; font-size: 22px; font-weight: bold; margin: 0 0 10px 0;"> 🎉 Mastery Achieved! </p> <p style="color: #000; font-size: 18px; font-weight: bold; margin: 0;"> You've learned the Dancing skill through dedicated coaching! </p> </div> <<else>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700;"> <h3 style="color: #FFD700; margin: 0 0 10px 0; text-align: center;">🎯 Coaching Progress</h3> <p style="color: #e0e0e0; text-align: center; margin: 0 0 15px 0;">Your coach is guiding you toward mastery!</p> <div style="background: #0a0a0a; border-radius: 6px; padding: 15px; border: 1px solid #444;"> <div style="margin-bottom: 10px;"> <p style="color: #aaa; font-size: 14px; margin: 0; text-align: center;"> Coaching sessions: <span style="color: #FFD700; font-weight: bold; font-size: 18px;"><<= $danceCoachSessions>> / 3</span> </p> </div> <div style="background: #000; border-radius: 6px; height: 12px; overflow: hidden; border: 1px solid #444;"> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); height: 100%; width: <<= Math.floor(($danceCoachSessions / 3) * 100)>>%; transition: width 0.3s;"></div> </div> <p style="color: #51cf66; font-size: 13px; margin: 10px 0 0 0; text-align: center; font-weight: bold;"> <<= 3 - $danceCoachSessions>> more session<<if 3 - $danceCoachSessions !== 1>>s<</if>> until mastery! </p> </div> </div> <</if>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); display: inline-block;'>← Back to Studio</div>">> <<run advanceTime(60)>> <<goto "DanceStudio">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.addBuff("vending_focus", 360)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #8d6e63 0%, #6d4c41 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8d6e63; box-shadow: 0 0 20px #8d6e6366;"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">☕ Premium Coffee</h1> </div> <!-- Coffee Description --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; border: 3px solid #8d6e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px; text-align: center;"> <div style="font-size: 64px; margin-bottom: 20px;">☕</div> <h2 style="color: #8d6e63; margin: 0 0 15px 0;">A Perfect Cup</h2> <p style="color: #e0e0e0; font-size: 18px; line-height: 1.6; max-width: 600px; margin: 0 auto 20px auto;"> The barista hands you a perfectly crafted cup of coffee. The rich, smooth taste energizes you instantly. You feel ready to take on whatever comes next. </p> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 10px 0 0 0;">☕ Focused buff gained (+2% trading chance, 6h).</p> </div> <!-- Trait Chance --> <<set _traitRoll = random(1, 100)>> <<if _traitRoll <= 1>> <<if !$mentalTraits.includes("Energetic") && !$mentalTraits.includes("Fast")>> <<set _gainedTrait = either("Energetic", "Fast")>> <<if _gainedTrait === "Energetic">> <<run $mentalTraits.push("Energetic")>> <<else>> <<run $physicalTraits.push("Fast")>> <</if>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <div style="font-size: 48px; margin-bottom: 10px;">✨</div> <p style="color: #000; font-size: 20px; font-weight: bold; margin: 0;"> 🎉 The coffee has awakened something in you! </p> <p style="color: #000; font-size: 18px; font-weight: bold; margin: 10px 0 0 0;"> You've gained the <<= _gainedTrait>> trait! </p> </div> <<elseif $mentalTraits.includes("Energetic") && !$physicalTraits.includes("Fast")>> <<run $physicalTraits.push("Fast")>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <div style="font-size: 48px; margin-bottom: 10px;">✨</div> <p style="color: #000; font-size: 20px; font-weight: bold; margin: 0;"> 🎉 The coffee has awakened something in you! </p> <p style="color: #000; font-size: 18px; font-weight: bold; margin: 10px 0 0 0;"> You've gained the Fast trait! </p> </div> <<elseif !$mentalTraits.includes("Energetic") && $physicalTraits.includes("Fast")>> <<run $mentalTraits.push("Energetic")>> <div style="background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #FFD700; text-align: center;"> <div style="font-size: 48px; margin-bottom: 10px;">✨</div> <p style="color: #000; font-size: 20px; font-weight: bold; margin: 0;"> 🎉 The coffee has awakened something in you! </p> <p style="color: #000; font-size: 18px; font-weight: bold; margin: 10px 0 0 0;"> You've gained the Energetic trait! </p> </div> <<else>> <div style="background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #4dabf7; text-align: center;"> <p style="color: white; font-size: 16px; font-weight: bold; margin: 0;"> ☕ You already have both the Energetic and Fast traits! </p> </div> <</if>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); display: inline-block;'>← Back to Cafe</div>">> <<run advanceTime(15)>> <<goto "Cafe">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #51cf66; box-shadow: 0 0 20px #51cf6666;"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">🎉 Congratulations!</h1> </div> <!-- Hiring Message --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px; text-align: center;"> <div style="font-size: 64px; margin-bottom: 20px;">☕</div> <h2 style="color: #51cf66; margin: 0 0 15px 0;">Welcome to Manta Ray Cafe!</h2> <p style="color: #e0e0e0; font-size: 18px; line-height: 1.6; max-width: 600px; margin: 0 auto 20px auto;"> The manager reviews your application and smiles. "Your skills are exactly what we're looking for! Welcome to the team. You'll be making $13 per hour. Come back during work hours to start your shift." </p> <p style="color: #ffd43b; font-size: 16px; font-weight: bold; margin: 0;"> 💰 Hourly Pay: $13 </p> </div> <!-- Job Details --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h3 style="color: #4dabf7; margin: 0 0 15px 0; text-align: center;">📋 Job Information</h3> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <p style="color: #e0e0e0; margin: 0 0 10px 0;"><strong style="color: #4dabf7;">Position:</strong> Barista</p> <p style="color: #e0e0e0; margin: 0 0 10px 0;"><strong style="color: #4dabf7;">Work Hours:</strong> 7:00 AM - 3:00 PM</p> <p style="color: #e0e0e0; margin: 0;"><strong style="color: #4dabf7;">Location:</strong> Manta Ray Cafe</p> </div> </div> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.2); display: inline-block;'>Start Your New Job!</div>">> <<goto "Cafe">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">⚙️ Settings</h1> <!-- Passage Effects Section --> <<if typeof $ambientEffectsEnabled === "undefined">> <<set $ambientEffectsEnabled = true>> <</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $ambientEffectsEnabled>>#7ec8e3<<else>>#888<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $ambientEffectsEnabled>>#7ec8e344<<else>>#88888844<</if>>;"> <h2 style="color: <<if $ambientEffectsEnabled>>#7ec8e3<<else>>#888<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $ambientEffectsEnabled>>#7ec8e388<<else>>#88888888<</if>>;"> ❄️ Passage Effects: <<if $ambientEffectsEnabled>>Enabled<<else>>Disabled<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> Ambient background effects for certain locations: blowing sand in the desert, rising embers at the volcano, falling snow in the mountains during rain and storms, and pale motes at the searing pool of lava. Turn this off if you prefer a still background or want to save battery. </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if $ambientEffectsEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #7ec8e3; color: #7ec8e3; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #7ec8e366, inset 0 0 20px #7ec8e322;'> ✓ Enabled <span style="color: #7ec8e3; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #7ec8e3; color: #7ec8e3; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✓ Enable Effects</div>">> <<set $ambientEffectsEnabled = true>> <<goto "ImageSettings">> <</link>> <</if>> <<if !$ambientEffectsEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #888; color: #888; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #88888866, inset 0 0 20px #88888822;'> ✗ Disabled <span style="color: #888; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #888; color: #888; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✗ Disable Effects</div>">> <<set $ambientEffectsEnabled = false>> <<run setup.ambientParticles && setup.ambientParticles.stop()>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <!-- Achievement Carryover Section --> <<if typeof $achievementCarryover === "undefined">> <<set $achievementCarryover = false>> <</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $achievementCarryover>>#51cf66<<else>>#ff6b6b<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $achievementCarryover>>#51cf6644<<else>>#ff6b6b44<</if>>;"> <h2 style="color: <<if $achievementCarryover>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $achievementCarryover>>#51cf6688<<else>>#ff6b6b88<</if>>;"> 🏆 Achievement Point Carryover: <<if $achievementCarryover>>Enabled<<else>>Disabled<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $achievementCarryover>> Achievement points will carry over when you restart the game. Your skill tree will reset but you'll keep all earned points. <<else>> Achievement points will NOT carry over on restart. Enable this for New Game+ style progression. <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if $achievementCarryover>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #51cf6666, inset 0 0 20px #51cf6622;'> ✓ Enable Carryover <span style="color: #51cf66; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✓ Enable Carryover</div>">> <<set $achievementCarryover = true>> <<run localStorage.setItem('sunfishCity_achievementCarryover', 'true')>> <<run localStorage.setItem('sunfishCity_achievements', JSON.stringify($unlockedAchievements || []))>> <<goto "ImageSettings">> <</link>> <</if>> <<if !$achievementCarryover>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ff6b6b66, inset 0 0 20px #ff6b6b22;'> ✗ Disable Carryover <span style="color: #ff6b6b; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✗ Disable Carryover</div>">> <<set $achievementCarryover = false>> <<run localStorage.setItem('sunfishCity_achievementCarryover', 'false')>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <!-- Time Format Section --> <<if typeof $use24HourTime === "undefined">> <<set $use24HourTime = false>> <</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $use24HourTime>>#4dabf7<<else>>#ffc107<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $use24HourTime>>#4dabf744<<else>>#ffc10744<</if>>;"> <h2 style="color: <<if $use24HourTime>>#4dabf7<<else>>#ffc107<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $use24HourTime>>#4dabf788<<else>>#ffc10788<</if>>;"> 🕐 Time Format: <<if $use24HourTime>>24-Hour<<else>>12-Hour (AM/PM)<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $use24HourTime>> Time is displayed in 24-hour format (e.g., 14:30 instead of 2:30 PM). <<else>> Time is displayed in 12-hour format with AM/PM (e.g., 2:30 PM). <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if !$use24HourTime>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffc107; color: #ffc107; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ffc10766, inset 0 0 20px #ffc10722;'> 12-Hour (AM/PM) <span style="color: #ffc107; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ffc107; color: #ffc107; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>12-Hour (AM/PM)</div>">> <<set $use24HourTime = false>> <<goto "ImageSettings">> <</link>> <</if>> <<if $use24HourTime>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #4dabf7; color: #4dabf7; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #4dabf766, inset 0 0 20px #4dabf722;'> 24-Hour <span style="color: #4dabf7; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>24-Hour</div>">> <<set $use24HourTime = true>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <h2 style="color: #667eea; text-align: center; margin-top: 30px;">🖼️ Image Settings</h2> <!-- Default Images Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $imageSettings.imagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $imageSettings.imagesEnabled>>#51cf6644<<else>>#ff6b6b44<</if>>;"> <!-- Default Images Toggle --> <h2 style="color: <<if $imageSettings.imagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $imageSettings.imagesEnabled>>#51cf6688<<else>>#ff6b6b88<</if>>;"> 📷 Default Images: <<if $imageSettings.imagesEnabled>>Enabled<<else>>Disabled<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $imageSettings.imagesEnabled>> Default game images are currently shown. Disable them to use custom images instead. <<else>> Default images are hidden. You can now upload custom images below. <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if $imageSettings.imagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #51cf6666, inset 0 0 20px #51cf6622;'> ✓ Enable Default Images <span style="color: #51cf66; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✓ Enable Default Images</div>">> <<set $imageSettings.imagesEnabled = true>> <<goto "ImageSettings">> <</link>> <</if>> <<if !$imageSettings.imagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ff6b6b66, inset 0 0 20px #ff6b6b22;'> ✗ Disable Default Images <span style="color: #ff6b6b; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✗ Disable Default Images</div>">> <<set $imageSettings.imagesEnabled = false>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <!-- Location Images Toggle --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $imageSettings.locationImagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $imageSettings.locationImagesEnabled>>#51cf6644<<else>>#ff6b6b44<</if>>;"> <h2 style="color: <<if $imageSettings.locationImagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $imageSettings.locationImagesEnabled>>#51cf6688<<else>>#ff6b6b88<</if>>;"> 🗺️ Location Images: <<if $imageSettings.locationImagesEnabled>>Enabled<<else>>Disabled<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $imageSettings.locationImagesEnabled>> Location images are displayed at the top of area passages. Disable them for a text-only experience. <<else>> Location images are hidden. Enable them to see visuals for each area you visit. <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if $imageSettings.locationImagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #51cf6666, inset 0 0 20px #51cf6622;'> ✓ Enable Location Images <span style="color: #51cf66; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✓ Enable Location Images</div>">> <<set $imageSettings.locationImagesEnabled = true>> <<goto "ImageSettings">> <</link>> <</if>> <<if !$imageSettings.locationImagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ff6b6b66, inset 0 0 20px #ff6b6b22;'> ✗ Disable Location Images <span style="color: #ff6b6b; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✗ Disable Location Images</div>">> <<set $imageSettings.locationImagesEnabled = false>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <!-- NPC Images Toggle --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $imageSettings.npcImagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $imageSettings.npcImagesEnabled>>#51cf6644<<else>>#ff6b6b44<</if>>;"> <h2 style="color: <<if $imageSettings.npcImagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $imageSettings.npcImagesEnabled>>#51cf6688<<else>>#ff6b6b88<</if>>;"> 👥 NPC Images: <<if $imageSettings.npcImagesEnabled>>Enabled<<else>>Disabled<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $imageSettings.npcImagesEnabled>> NPC character images are displayed when interacting with characters. Disable them to hide all NPC portraits. <<else>> NPC images are hidden. Enable them to see character portraits during interactions. <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if $imageSettings.npcImagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #51cf6666, inset 0 0 20px #51cf6622;'> ✓ Enable NPC Images <span style="color: #51cf66; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✓ Enable NPC Images</div>">> <<set $imageSettings.npcImagesEnabled = true>> <<goto "ImageSettings">> <</link>> <</if>> <<if !$imageSettings.npcImagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ff6b6b66, inset 0 0 20px #ff6b6b22;'> ✗ Disable NPC Images <span style="color: #ff6b6b; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✗ Disable NPC Images</div>">> <<set $imageSettings.npcImagesEnabled = false>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <!-- Erotic Imagery Toggle --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $imageSettings.eroticImagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $imageSettings.eroticImagesEnabled>>#51cf6644<<else>>#ff6b6b44<</if>>;"> <h2 style="color: <<if $imageSettings.eroticImagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $imageSettings.eroticImagesEnabled>>#51cf6688<<else>>#ff6b6b88<</if>>;"> 🔞 Erotic Imagery: <<if $imageSettings.eroticImagesEnabled>>Enabled<<else>>Disabled<</if>> </h2> <p style="color: #ccc; margin-bottom: 10px;"> Toggle explicit adult content images for jobs and activities like the Mayor's Secretary and Brothel work. </p> <p style="color: #ffc107; font-size: 14px; margin: 0 0 20px 0; font-style: italic;"> ⚠️ Warning: These images contain explicit adult sexual content. </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if $imageSettings.eroticImagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #51cf6666, inset 0 0 20px #51cf6622;'> ✓ Enable Erotic Images <span style="color: #51cf66; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✓ Enable Erotic Images</div>">> <<set $imageSettings.eroticImagesEnabled = true>> <<goto "ImageSettings">> <</link>> <</if>> <<if !$imageSettings.eroticImagesEnabled>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ff6b6b66, inset 0 0 20px #ff6b6b22;'> ✗ Disable Erotic Images <span style="color: #ff6b6b; font-size: 18px;">●</span> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>✗ Disable Erotic Images</div>">> <<set $imageSettings.eroticImagesEnabled = false>> <<goto "ImageSettings">> <</link>> <</if>> </div> </div> <!-- Custom Image Upload Section --> <<if !$imageSettings.imagesEnabled>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #667eea44;"> <h2 style="color: #667eea; margin: 0 0 15px 0; text-shadow: 0 0 10px #667eea88;">📤 Upload Custom Images</h2> <p style="color: #4dabf7; background: #1f2a3a; padding: 15px; border-radius: 8px; border: 2px solid #4dabf7; margin-bottom: 20px;"> ℹ️ <strong>Note:</strong> Upload images from your device or enter a URL. Uploaded images are stored in your browser and will persist across sessions. </p> <!-- Face Image --> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">😊 Face Image</h3> <<if $imageSettings.customImages.face>> <div style="margin-bottom: 15px; text-align: center;"> <img @src="$imageSettings.customImages.face" style="max-width: 300px; max-height: 300px; border-radius: 8px; border: 2px solid #9b59b6;" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; padding: 40px; background: #3a2a3a; border-radius: 8px; color: #ff6b6b;"> ❌ Failed to load image </div> </div> <p style="color: #51cf66; margin-bottom: 10px;">✓ Custom face image set</p> <<else>> <p style="color: #aaa; margin-bottom: 10px; font-style: italic;">No custom face image set</p> <</if>> <!-- File Upload --> <label style="display: block; color: #ccc; margin-bottom: 8px;"><strong>Upload from Device:</strong></label> <input type="file" id="faceImageFile" accept="image/*" style="width: 100%; padding: 10px; background: #1a1a1a; color: #fff; border: 2px solid #9b59b6; border-radius: 6px; font-size: 14px; margin-bottom: 15px; cursor: pointer;"> <div style="text-align: center; margin: 15px 0; color: #666;">OR</div> <!-- URL Input --> <label style="display: block; color: #ccc; margin-bottom: 8px;"><strong>Image URL:</strong></label> <input type="text" id="faceImageInput" placeholder="https://example.com/face.webp" @value="$imageSettings.customImages.face || ''" style="width: 100%; padding: 10px; background: #1a1a1a; color: #fff; border: 2px solid #9b59b6; border-radius: 6px; font-size: 14px; margin-bottom: 10px;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;' onclick=" var fileInput = document.getElementById('faceImageFile'); var urlInput = document.getElementById('faceImageInput'); if (fileInput.files && fileInput.files[0]) { var reader = new FileReader(); reader.onload = function(e) { SugarCube.State.variables.imageSettings.customImages.face = e.target.result; SugarCube.Engine.play('ImageSettings'); }; reader.readAsDataURL(fileInput.files[0]); } else if (urlInput.value && (urlInput.value.startsWith('http://') || urlInput.value.startsWith('https://'))) { SugarCube.State.variables.imageSettings.customImages.face = urlInput.value.trim(); SugarCube.Engine.play('ImageSettings'); } "> 💾 Save Face Image </div> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🗑️ Clear</div>">> <<set $imageSettings.customImages.face = "">> <<goto "ImageSettings">> <</link>> </div> </div> <!-- Chest Image --> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #51cf66;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">👕 Chest Image</h3> <<if $imageSettings.customImages.chest>> <div style="margin-bottom: 15px; text-align: center;"> <img @src="$imageSettings.customImages.chest" style="max-width: 300px; max-height: 300px; border-radius: 8px; border: 2px solid #51cf66;" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; padding: 40px; background: #2a3a2a; border-radius: 8px; color: #ff6b6b;"> ❌ Failed to load image </div> </div> <p style="color: #51cf66; margin-bottom: 10px;">✓ Custom chest image set</p> <<else>> <p style="color: #aaa; margin-bottom: 10px; font-style: italic;">No custom chest image set</p> <</if>> <!-- File Upload --> <label style="display: block; color: #ccc; margin-bottom: 8px;"><strong>Upload from Device:</strong></label> <input type="file" id="chestImageFile" accept="image/*" style="width: 100%; padding: 10px; background: #1a1a1a; color: #fff; border: 2px solid #51cf66; border-radius: 6px; font-size: 14px; margin-bottom: 15px; cursor: pointer;"> <div style="text-align: center; margin: 15px 0; color: #666;">OR</div> <!-- URL Input --> <label style="display: block; color: #ccc; margin-bottom: 8px;"><strong>Image URL:</strong></label> <input type="text" id="chestImageInput" placeholder="https://example.com/chest.webp" @value="$imageSettings.customImages.chest || ''" style="width: 100%; padding: 10px; background: #1a1a1a; color: #fff; border: 2px solid #51cf66; border-radius: 6px; font-size: 14px; margin-bottom: 10px;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;' onclick=" var fileInput = document.getElementById('chestImageFile'); var urlInput = document.getElementById('chestImageInput'); if (fileInput.files && fileInput.files[0]) { var reader = new FileReader(); reader.onload = function(e) { SugarCube.State.variables.imageSettings.customImages.chest = e.target.result; SugarCube.Engine.play('ImageSettings'); }; reader.readAsDataURL(fileInput.files[0]); } else if (urlInput.value && (urlInput.value.startsWith('http://') || urlInput.value.startsWith('https://'))) { SugarCube.State.variables.imageSettings.customImages.chest = urlInput.value.trim(); SugarCube.Engine.play('ImageSettings'); } "> 💾 Save Chest Image </div> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🗑️ Clear</div>">> <<set $imageSettings.customImages.chest = "">> <<goto "ImageSettings">> <</link>> </div> </div> <!-- Butt Image --> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #ffc107;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🍑 Butt Image</h3> <<if $imageSettings.customImages.butt>> <div style="margin-bottom: 15px; text-align: center;"> <img @src="$imageSettings.customImages.butt" style="max-width: 300px; max-height: 300px; border-radius: 8px; border: 2px solid #ffc107;" onerror="this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; padding: 40px; background: #3a3020; border-radius: 8px; color: #ff6b6b;"> ❌ Failed to load image </div> </div> <p style="color: #51cf66; margin-bottom: 10px;">✓ Custom butt image set</p> <<else>> <p style="color: #aaa; margin-bottom: 10px; font-style: italic;">No custom butt image set</p> <</if>> <!-- File Upload --> <label style="display: block; color: #ccc; margin-bottom: 8px;"><strong>Upload from Device:</strong></label> <input type="file" id="buttImageFile" accept="image/*" style="width: 100%; padding: 10px; background: #1a1a1a; color: #fff; border: 2px solid #ffc107; border-radius: 6px; font-size: 14px; margin-bottom: 15px; cursor: pointer;"> <div style="text-align: center; margin: 15px 0; color: #666;">OR</div> <!-- URL Input --> <label style="display: block; color: #ccc; margin-bottom: 8px;"><strong>Image URL:</strong></label> <input type="text" id="buttImageInput" placeholder="https://example.com/butt.webp" @value="$imageSettings.customImages.butt || ''" style="width: 100%; padding: 10px; background: #1a1a1a; color: #fff; border: 2px solid #ffc107; border-radius: 6px; font-size: 14px; margin-bottom: 10px;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <div style='background: linear-gradient(135deg, #ffc107 0%, #ff9800 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;' onclick=" var fileInput = document.getElementById('buttImageFile'); var urlInput = document.getElementById('buttImageInput'); if (fileInput.files && fileInput.files[0]) { var reader = new FileReader(); reader.onload = function(e) { SugarCube.State.variables.imageSettings.customImages.butt = e.target.result; SugarCube.Engine.play('ImageSettings'); }; reader.readAsDataURL(fileInput.files[0]); } else if (urlInput.value && (urlInput.value.startsWith('http://') || urlInput.value.startsWith('https://'))) { SugarCube.State.variables.imageSettings.customImages.butt = urlInput.value.trim(); SugarCube.Engine.play('ImageSettings'); } "> 💾 Save Butt Image </div> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🗑️ Clear</div>">> <<set $imageSettings.customImages.butt = "">> <<goto "ImageSettings">> <</link>> </div> </div> <!-- Clear All Button --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🗑️ Clear All Custom Images</div>">> <<set $imageSettings.customImages.face = "">> <<set $imageSettings.customImages.chest = "">> <<set $imageSettings.customImages.butt = "">> <<goto "ImageSettings">> <</link>> </div> </div> <<else>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; text-align: center; font-style: italic; margin: 0;"> Custom image uploads are only available when default images are disabled. </p> </div> <</if>> <!-- Trade Interface Mode --> <<if typeof $compactTradeUI === "undefined">> <<set $compactTradeUI = true>> <</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $compactTradeUI>>#51cf66<<else>>#ffc107<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $compactTradeUI>>#51cf6644<<else>>#ffc10744<</if>>;"> <h2 style="color: <<if $compactTradeUI>>#51cf66<<else>>#ffc107<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $compactTradeUI>>#51cf6688<<else>>#ffc10788<</if>>;"> Trade Interface: <<if $compactTradeUI>>Compact<<else>>Classic<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $compactTradeUI>> Compact mode shows all tradeable items on a single screen with side-by-side columns. Click items to toggle them on/off with live-updating values. <<else>> Classic mode uses the original multi-screen trading flow where you navigate between screens to build your trade packages. <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if !$compactTradeUI>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Compact (Single Screen)</div>">> <<set $compactTradeUI = true>> <<goto "ImageSettings">> <</link>> <<else>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #51cf6666, inset 0 0 20px #51cf6622;'> Compact (Single Screen) <span style="font-size: 18px;">●</span> </div> <</if>> <<if $compactTradeUI>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ffc107; color: #ffc107; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Classic (Multi-Screen)</div>">> <<set $compactTradeUI = false>> <<goto "ImageSettings">> <</link>> <<else>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffc107; color: #ffc107; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ffc10766, inset 0 0 20px #ffc10722;'> Classic (Multi-Screen) <span style="font-size: 18px;">●</span> </div> <</if>> </div> </div> <!-- NPC Menu Mode --> <<if typeof $compactNPCMenu === "undefined">> <<set $compactNPCMenu = true>> <</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $compactNPCMenu>>#7dd3fc<<else>>#ffc107<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px <<if $compactNPCMenu>>#7dd3fc44<<else>>#ffc10744<</if>>;"> <h2 style="color: <<if $compactNPCMenu>>#7dd3fc<<else>>#ffc107<</if>>; margin: 0 0 15px 0; text-shadow: 0 0 10px <<if $compactNPCMenu>>#7dd3fc88<<else>>#ffc10788<</if>>;"> NPC Menu: <<if $compactNPCMenu>>Compact<<else>>Classic<</if>> </h2> <p style="color: #ccc; margin-bottom: 20px;"> <<if $compactNPCMenu>> Compact mode places Talk and Trade in a sticky top bar with a styled two column layout for stats, traits, and skills, matching the compact trade interface. <<else>> Classic mode uses the original NPC menu with action buttons at the bottom and large stat panels. <</if>> </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <<if !$compactNPCMenu>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #7dd3fc; color: #7dd3fc; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Compact (Top Bar)</div>">> <<set $compactNPCMenu = true>> <<goto "ImageSettings">> <</link>> <<else>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #7dd3fc; color: #7dd3fc; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #7dd3fc66, inset 0 0 20px #7dd3fc22;'> Compact (Top Bar) <span style="font-size: 18px;">●</span> </div> <</if>> <<if $compactNPCMenu>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ffc107; color: #ffc107; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Classic (Bottom Buttons)</div>">> <<set $compactNPCMenu = false>> <<goto "ImageSettings">> <</link>> <<else>> <div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffc107; color: #ffc107; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; box-shadow: 0 0 15px #ffc10766, inset 0 0 20px #ffc10722;'> Classic (Bottom Buttons) <span style="font-size: 18px;">●</span> </div> <</if>> </div> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Casino")>> <<run $visitedLocations.push("Casino")>> <</if>> <<set $lastLocation = "Casino">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">🎰 Silver Marlin - Casino Staff</h1> <div style="padding: 20px; background: linear-gradient(135deg, #d4af37 0%, #8b7355 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700;"> <p style="color: white; font-size: 18px; margin: 0;"> Professional dealers in crisp uniforms manage the gaming tables with practiced efficiency. They shuffle cards with theatrical flair, spin roulette wheels with perfect timing, and maintain the house edge with unwavering precision. </p> </div> <<set _casinoNPCs = setup.getNPCsAtLocation("Casino").filter(function(n) { return n.jobs && n.jobs.includes("Casino Dealer"); })>> <<if _casinoNPCs.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-top: 20px;"> <<for _i, _npc range _casinoNPCs>> <<if setup.isNPCAvailable(_npc.name)>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🎲 <<print _npc.name>></h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 10px;"> <strong style="color: #ffd700;">Job:</strong> <<if _npc.jobs && _npc.jobs.length > 0>> <<print _npc.jobs.join(", ")>> <<else>> No current position <</if>> </p> <<link "<div style='background: #ffd700; color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Approach</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</if>> <</for>> </div> <<else>> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6; text-align: center;"> <p style="color: #666; font-size: 16px;">No casino staff available at the moment.</p> </div> <</if>> <br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Casino</div>">> <<goto "Casino">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("SlotMachine")>> <<run $visitedLocations.push("SlotMachine")>> <</if>> <<set $lastLocation = "SlotMachine">> <!-- ===== SKILL TREE: Get gambling bonuses ===== --> <<set _slotsWinBonus = setup.skillTree.getEffect("slotsWinBonus")>> <<set _slotsPayoutBonus = setup.skillTree.getEffect("slotsPayoutBonus")>> <<set _slotCost = setup.getSlotCost()>> <<set _isCasinoStaff = $jobs && ($jobs.includes("Security Guard") || $jobs.includes("Cocktail Waitress"))>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 0 20px #ffd700;">🎰 Slot Machine</h1> <div style="padding: 20px; background: linear-gradient(135deg, #0f4c3a 0%, #1a5c4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(46, 204, 113, 0.3);"> <p style="color: #a8e6cf; font-size: 18px; margin: 0; text-align: center;"> Pull the lever and watch the reels spin! Three matching symbols means you win! </p> </div> <!-- Player Status --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <h3 style="color: #ffd700; margin: 0 0 15px 0; text-align: center;">Your Status</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="text-align: center;"> <p style="color: #51cf66; font-size: 24px; font-weight: bold; margin: 0;">$<<print $money.toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Available Cash</p> </div> <div style="text-align: center;"> <p style="color: #4dabf7; font-size: 24px; font-weight: bold; margin: 0;">$slotMachineSystem.totalPlays</p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Total Plays</p> </div> <div style="text-align: center;"> <<if _isCasinoStaff>> <p style="color: #e91e63; font-size: 24px; font-weight: bold; margin: 0;"><span style="text-decoration: line-through; color: #666;">$50</span> $<<print _slotCost>></p> <<else>> <p style="color: #e91e63; font-size: 24px; font-weight: bold; margin: 0;">$50</p> <</if>> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Cost Per Spin</p> </div> </div> <!-- Trait/Artifact/Skill Tree Status --> <<set _hasLucky = ($mentalTraits && $mentalTraits.includes("Lucky")) || ($physicalTraits && $physicalTraits.includes("Cerberus")) || ($physicalTraits && $physicalTraits.includes("Cupid")) || ($physicalTraits && $physicalTraits.includes("Cheshire Cat"))>> <<set _hasUnlucky = $mentalTraits && ($mentalTraits.includes("Unlucky") || $mentalTraits.includes("Bad Luck"))>> <<set _hasPearl = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _hasAddiction = $mentalTraits && $mentalTraits.includes("Gambling Addiction")>> <<set _hasSkillTreeBonus = _slotsWinBonus > 0 || _slotsPayoutBonus > 0>> <<if _hasLucky || _hasUnlucky || _hasPearl || _hasAddiction || _hasSkillTreeBonus>> <div style="margin-top: 15px; padding-top: 15px; border-top: 2px solid #333;"> <!-- ===== SKILL TREE: Display bonuses ===== --> <<if _hasSkillTreeBonus>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 10px; border-radius: 6px; margin-bottom: 8px; border: 2px solid #CE93D8; box-shadow: 0 0 10px rgba(156, 39, 176, 0.3);"> <p style="color: #CE93D8; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> ⭐ Skill Tree Bonuses Active </p> <<if _slotsWinBonus > 0>> <p style="color: #E1BEE7; font-size: 12px; margin: 5px 0 0 0; text-align: center;"> Win Chance: +<<print _slotsWinBonus>>% </p> <</if>> <<if _slotsPayoutBonus > 0>> <p style="color: #E1BEE7; font-size: 12px; margin: 5px 0 0 0; text-align: center;"> Payout Bonus: +<<print _slotsPayoutBonus>>% </p> <</if>> </div> <</if>> <<if _hasPearl>> <div style="background: linear-gradient(135deg, #f5f5f5 0%, #e0e0e0 100%); padding: 10px; border-radius: 6px; margin-bottom: 8px; border: 2px solid #f5f5f5; box-shadow: 0 0 10px rgba(245, 245, 245, 0.3);"> <p style="color: #333; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> 🔮 Pearl of Abundance: +50% winnings! </p> </div> <</if>> <<if _hasLucky>> <div style="background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); padding: 10px; border-radius: 6px; margin-bottom: 8px; border: 2px solid #ffd700; box-shadow: 0 0 10px rgba(255, 215, 0, 0.3);"> <p style="color: #000; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> ✨ Lucky: Better odds! </p> </div> <</if>> <<if _hasUnlucky>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 10px; border-radius: 6px; margin-bottom: 8px; border: 2px solid #c62828; box-shadow: 0 0 10px rgba(198, 40, 40, 0.3);"> <p style="color: #ff6b6b; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> 💀 Unlucky: Worse odds </p> </div> <</if>> <<if _hasAddiction>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 10px; border-radius: 6px; border: 2px solid #ff6b6b; box-shadow: 0 0 10px rgba(255, 107, 107, 0.3);"> <p style="color: #ff6b6b; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> 🎲 Gambling Addiction: You're hooked... </p> </div> <</if>> <<if _isCasinoStaff>> <div style="background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); padding: 10px; border-radius: 6px; margin-top: 8px; border: 2px solid #51cf66; box-shadow: 0 0 10px rgba(46, 204, 113, 0.3);"> <p style="color: #fff; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> 🎰 Casino Staff: 5% discount on spins! </p> </div> <</if>> </div> <</if>> </div> <!-- Slot Machine Display --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 40px 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <div id="slotDisplay" style="display: flex; justify-content: center; gap: 20px; margin-bottom: 30px;"> <div style="background: #1a1a1a; border: 3px solid #667eea; border-radius: 10px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 64px; box-shadow: inset 0 0 20px rgba(0,0,0,0.5);"> <span id="reel1">🎰</span> </div> <div style="background: #1a1a1a; border: 3px solid #667eea; border-radius: 10px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 64px; box-shadow: inset 0 0 20px rgba(0,0,0,0.5);"> <span id="reel2">🎰</span> </div> <div style="background: #1a1a1a; border: 3px solid #667eea; border-radius: 10px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 64px; box-shadow: inset 0 0 20px rgba(0,0,0,0.5);"> <span id="reel3">🎰</span> </div> </div> <!-- Spin Button --> <<if $money >= _slotCost>> <<capture _slotCost>> <div id='spinButton' style='background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 20px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 24px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 215, 0, 0.5); margin: 0 auto; display: inline-block;'> <<link `"🎰 PULL LEVER ($" + _slotCost + ")"`>> <<goto "SlotMachineResult">> <</link>> </div> <</capture>> <<else>> <div style='background: #444; color: #888; padding: 20px 40px; border-radius: 10px; text-align: center; font-weight: bold; font-size: 24px; cursor: not-allowed; margin: 0 auto; display: inline-block;'>🎰 Not Enough Money</div> <</if>> </div> <!-- Payout Table --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #4dabf744;"> <h3 style="color: #4dabf7; margin: 0 0 15px 0; text-align: center;">💰 Payout Table</h3> <!-- ===== SKILL TREE: Show boosted payouts if bonus active ===== --> <<if _slotsPayoutBonus > 0>> <p style="color: #CE93D8; font-size: 12px; text-align: center; margin: 0 0 10px 0;"> ⭐ Payouts boosted by +<<print _slotsPayoutBonus>>%! </p> <</if>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #333;"> <span style="font-size: 24px;">💎 💎 💎</span> <span style="color: #ffd700; font-weight: bold; float: right;"> <<if _slotsPayoutBonus > 0>> $<<print Math.floor(1000000 * (1 + _slotsPayoutBonus/100)).toLocaleString()>> <<else>> $1,000,000 <</if>> </span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #333;"> <span style="font-size: 24px;">👑 👑 👑</span> <span style="color: #ffd700; font-weight: bold; float: right;"> <<if _slotsPayoutBonus > 0>> $<<print Math.floor(10000 * (1 + _slotsPayoutBonus/100)).toLocaleString()>> <<else>> $10,000 <</if>> </span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #333;"> <span style="font-size: 24px;">🍀 🍀 🍀</span> <span style="color: #51cf66; font-weight: bold; float: right;"> <<if _slotsPayoutBonus > 0>> $<<print Math.floor(1000 * (1 + _slotsPayoutBonus/100)).toLocaleString()>> <<else>> $1,000 <</if>> </span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #333;"> <span style="font-size: 24px;">🎰 🎰 🎰</span> <span style="color: #51cf66; font-weight: bold; float: right;"> <<if _slotsPayoutBonus > 0>> $<<print Math.floor(250 * (1 + _slotsPayoutBonus/100)).toLocaleString()>> <<else>> $250 <</if>> </span> </div> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; border: 2px solid #333; grid-column: 1 / -1;"> <span style="font-size: 24px;">🍒 🍒 🍒</span> <span style="color: #51cf66; font-weight: bold; float: right;"> <<if _slotsPayoutBonus > 0>> $<<print Math.floor(100 * (1 + _slotsPayoutBonus/100)).toLocaleString()>> <<else>> $100 <</if>> </span> </div> </div> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44;'>← Back to Casino</div>">> <<goto "Casino">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("RouletteRoom")>> <<run $visitedLocations.push("RouletteRoom")>> <</if>> <<set $lastLocation = "RouletteRoom">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 0 20px #ffd700;">🎡 Roulette Room</h1> <div style="padding: 20px; background: linear-gradient(135deg, #0f4c3a 0%, #1a5c4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(46, 204, 113, 0.3);"> <p style="color: #a8e6cf; font-size: 18px; margin: 0; text-align: center;"> The roulette wheel spins under elegant lighting. Chips clatter on the felt table as other gamblers place their bets. The dealer watches with practiced indifference, ready to call the winning number. </p> </div> <!-- Player Status --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <h3 style="color: #ffd700; margin: 0 0 15px 0; text-align: center;">Your Status</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="text-align: center;"> <p style="color: #51cf66; font-size: 24px; font-weight: bold; margin: 0;">$<<print $money.toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Available Cash</p> </div> <div style="text-align: center;"> <p style="color: <<if $rouletteSystem.periodWinnings >= 50000>>#c62828<<elseif $rouletteSystem.periodWinnings >= 25000>>#f39c12<<else>>#51cf66<</if>>; font-size: 24px; font-weight: bold; margin: 0;">$<<print $rouletteSystem.periodWinnings.toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Period Winnings</p> </div> <div style="text-align: center;"> <p style="color: #ffd43b; font-size: 24px; font-weight: bold; margin: 0;">$<<print (50000 - $rouletteSystem.periodWinnings).toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Until 30-Day Ban</p> </div> </div> <!-- Trait Status --> <<set _hasLucky = ($mentalTraits && $mentalTraits.includes("Lucky")) || ($physicalTraits && $physicalTraits.includes("Cerberus")) || ($physicalTraits && $physicalTraits.includes("Cupid")) || ($physicalTraits && $physicalTraits.includes("Cheshire Cat"))>> <<set _hasUnlucky = $mentalTraits && ($mentalTraits.includes("Unlucky") || $mentalTraits.includes("Bad Luck"))>> <<set _hasPearl = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _hasLucky || _hasUnlucky || _hasPearl>> <div style="margin-top: 15px; padding-top: 15px; border-top: 2px solid #333;"> <<if _hasPearl>> <div style="background: linear-gradient(135deg, #f5f5f5 0%, #e0e0e0 100%); padding: 10px; border-radius: 6px; margin-bottom: 8px; border: 2px solid #f5f5f5; box-shadow: 0 0 10px rgba(245, 245, 245, 0.3);"> <p style="color: #333; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> 🔮 Pearl of Abundance: +50% winnings (doesn't count toward limit)! </p> </div> <</if>> <<if _hasLucky>> <div style="background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); padding: 10px; border-radius: 6px; margin-bottom: 8px; border: 2px solid #ffd700; box-shadow: 0 0 10px rgba(255, 215, 0, 0.3);"> <p style="color: #000; font-size: 14px; font-weight: bold; margin: 0; text-align: center;"> ✨ Lucky Trait Active: +10% win chance! </p> </div> <</if>> <<if _hasUnlucky>> <</if>> </div> <</if>> </div> <!-- Betting Interface --> <h2 style="color: #ffd700; text-align: center;">Place Your Bet</h2> <!-- Bet Amount Selection --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #4dabf744;"> <h3 style="color: #4dabf7; margin: 0 0 15px 0;">💰 Bet Amount</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">Select how much you want to wager (Max: $50,000):</p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px;"> <!-- $100 --> <<if $money >= 100>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$100</div>">> <<set $currentBetAmount = 100>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$100</div> <</if>> <!-- $500 --> <<if $money >= 500>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$500</div>">> <<set $currentBetAmount = 500>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$500</div> <</if>> <!-- $1,000 --> <<if $money >= 1000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$1,000</div>">> <<set $currentBetAmount = 1000>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$1,000</div> <</if>> <!-- $2,500 --> <<if $money >= 2500>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$2,500</div>">> <<set $currentBetAmount = 2500>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$2,500</div> <</if>> <!-- $5,000 --> <<if $money >= 5000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #51cf66; color: #51cf66; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$5,000</div>">> <<set $currentBetAmount = 5000>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$5,000</div> <</if>> <!-- $10,000 --> <<if $money >= 10000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ffd43b; color: #ffd43b; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$10,000</div>">> <<set $currentBetAmount = 10000>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$10,000</div> <</if>> <!-- $25,000 --> <<if $money >= 25000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ff8787; color: #ff8787; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$25,000</div>">> <<set $currentBetAmount = 25000>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$25,000</div> <</if>> <!-- $50,000 --> <<if $money >= 50000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #e91e63; color: #e91e63; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>$50,000</div>">> <<set $currentBetAmount = 50000>> <<goto "RouletteRoom">> <</link>> <<else>> <div style='background: #1a1a1a; border: 2px solid #444; color: #666; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>$50,000</div> <</if>> </div> <<if $currentBetAmount>> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 15px 0 0 0; text-align: center;"> Current Bet: $<<print $currentBetAmount.toLocaleString()>> </p> <<else>> <p style="color: #888; font-size: 14px; margin: 15px 0 0 0; text-align: center; font-style: italic;"> No bet selected yet </p> <</if>> </div> <<if $currentBetAmount>> <!-- Color Betting --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #e91e6344;"> <h3 style="color: #e91e63; margin: 0 0 15px 0;">🎨 Bet on Color</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">Payout: 2x your bet (1:1 odds)</p> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;"> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>🔴 Red</div>">> <<set $rouletteBetType = "color">> <<set $rouletteBetValue = "red">> <<goto "RouletteSpinResult">> <</link>> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #666;'>⚫ Black</div>">> <<set $rouletteBetType = "color">> <<set $rouletteBetValue = "black">> <<goto "RouletteSpinResult">> <</link>> </div> </div> <!-- Number Betting --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9775fa; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #9775fa44;"> <h3 style="color: #9775fa; margin: 0 0 15px 0;">🔢 Bet on Number</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">Payout: 35x your bet (35:1 odds)</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(60px, 1fr)); gap: 8px;"> <!-- 0 (Green) --> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #1b7943 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>0</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 0>> <<goto "RouletteSpinResult">> <</link>> <!-- 1 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>1</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 1>> <<goto "RouletteSpinResult">> <</link>> <!-- 2 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>2</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 2>> <<goto "RouletteSpinResult">> <</link>> <!-- 3 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>3</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 3>> <<goto "RouletteSpinResult">> <</link>> <!-- 4 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>4</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 4>> <<goto "RouletteSpinResult">> <</link>> <!-- 5 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>5</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 5>> <<goto "RouletteSpinResult">> <</link>> <!-- 6 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>6</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 6>> <<goto "RouletteSpinResult">> <</link>> <!-- 7 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>7</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 7>> <<goto "RouletteSpinResult">> <</link>> <!-- 8 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>8</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 8>> <<goto "RouletteSpinResult">> <</link>> <!-- 9 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>9</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 9>> <<goto "RouletteSpinResult">> <</link>> <!-- 10 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>10</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 10>> <<goto "RouletteSpinResult">> <</link>> <!-- 11 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>11</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 11>> <<goto "RouletteSpinResult">> <</link>> <!-- 12 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>12</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 12>> <<goto "RouletteSpinResult">> <</link>> <!-- 13 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>13</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 13>> <<goto "RouletteSpinResult">> <</link>> <!-- 14 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>14</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 14>> <<goto "RouletteSpinResult">> <</link>> <!-- 15 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>15</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 15>> <<goto "RouletteSpinResult">> <</link>> <!-- 16 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>16</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 16>> <<goto "RouletteSpinResult">> <</link>> <!-- 17 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>17</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 17>> <<goto "RouletteSpinResult">> <</link>> <!-- 18 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>18</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 18>> <<goto "RouletteSpinResult">> <</link>> <!-- 19 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>19</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 19>> <<goto "RouletteSpinResult">> <</link>> <!-- 20 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>20</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 20>> <<goto "RouletteSpinResult">> <</link>> <!-- 21 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>21</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 21>> <<goto "RouletteSpinResult">> <</link>> <!-- 22 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>22</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 22>> <<goto "RouletteSpinResult">> <</link>> <!-- 23 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>23</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 23>> <<goto "RouletteSpinResult">> <</link>> <!-- 24 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>24</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 24>> <<goto "RouletteSpinResult">> <</link>> <!-- 25 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>25</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 25>> <<goto "RouletteSpinResult">> <</link>> <!-- 26 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>26</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 26>> <<goto "RouletteSpinResult">> <</link>> <!-- 27 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>27</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 27>> <<goto "RouletteSpinResult">> <</link>> <!-- 28 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>28</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 28>> <<goto "RouletteSpinResult">> <</link>> <!-- 29 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>29</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 29>> <<goto "RouletteSpinResult">> <</link>> <!-- 30 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>30</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 30>> <<goto "RouletteSpinResult">> <</link>> <!-- 31 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>31</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 31>> <<goto "RouletteSpinResult">> <</link>> <!-- 32 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>32</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 32>> <<goto "RouletteSpinResult">> <</link>> <!-- 33 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>33</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 33>> <<goto "RouletteSpinResult">> <</link>> <!-- 34 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>34</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 34>> <<goto "RouletteSpinResult">> <</link>> <!-- 35 (Red) --> <<link "<div style='background: linear-gradient(135deg, #c62828 0%, #8b0000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4);'>35</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 35>> <<goto "RouletteSpinResult">> <</link>> <!-- 36 (Black) --> <<link "<div style='background: linear-gradient(135deg, #1a1a1a 0%, #000000 100%); color: white; padding: 15px 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.4); border: 2px solid #666;'>36</div>">> <<set $rouletteBetType = "number">> <<set $rouletteBetValue = 36>> <<goto "RouletteSpinResult">> <</link>> </div> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<if $forcedGambling>> <div style="display: inline-block; background: linear-gradient(135deg, #1a1a1a 0%, #0d0d0d 100%); border: 3px solid #666; color: #666; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: not-allowed;">🔒 You Can't Leave Yet...</div> <p style="color: #ff6b6b; font-size: 14px; margin-top: 10px; font-style: italic;">Your gambling addiction compels you to keep playing until you win big or lose everything.</p> <<else>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44;'>← Leave Roulette Table</div>">> <<set $currentBetAmount = null>> <<goto "Casino">> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("SeabassPark")>> <<run $visitedLocations.push("SeabassPark")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "SeabassPark">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4a7c2c; text-align: center;">🌳 Seabass Park</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Park.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #4a7c2c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Seabass Park"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #2d5016 0%, #3d6b1f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4a7c2c;"> <p style="color: white; font-size: 18px; margin: 0;"> A sprawling green space in the heart of the business district. Tall trees provide shade over winding pathways, while joggers and dog walkers enjoy the fresh air. Park benches line the paths, and the distant sounds of the city seem muffled here. </p> </div> <h2 style="color: #4a7c2c;">What do you want to do?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Return to Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Return to the business district.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Park</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- Go to Outskirts --> <div style="border: 3px solid #8b4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #d2691e; margin: 0 0 10px 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Head to the edge of the city.</p> <<link "<div style='background: #8b4513; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>To Outskirts</div>">> <<goto "Outskirts">> <</link>> </div> <!-- Residential District --> <div style="border: 3px solid #a3d9a5; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #a3d9a5; margin: 0 0 10px 0;">🏠 Residential District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Quiet neighborhoods and housing areas.</p> <<link "<div style='background: #a3d9a5; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>To Residential District</div>">> <<goto "ResidentialDistrict">> <</link>> </div> <!-- Pond Fishing (requires parkEntrance skill or hiddenPondUnlocked) --> <<if $hiddenPondUnlocked || setup.skillTree.getEffect("parkEntrance")>> <div style="border: 3px solid #1e8449; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #1e8449; margin: 0 0 10px 0;">🎣 Pond Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Fish in the hidden pond.</p> <<link "<div style='background: #1e8449; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Fishing</div>">> <<set $fishingLocation = "pond">> <<goto "FishingPond">> <</link>> </div> <<else>> <div style="border: 3px solid #555; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; opacity: 0.6;"> <h3 style="color: #555; margin: 0 0 10px 0;">🔒 Pond Fishing</h3> <p style="font-size: 14px; color: #666; margin: 0 0 auto 0; line-height: 1.4;">A hidden pond is rumored to be somewhere in the park...</p> <div style='background: #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; cursor: not-allowed; font-weight: bold; margin-top: 10px;'>Locked</div> </div> <</if>> </div> <!-- Street Performer Discovery --> <<if (!$jobs || $jobs.length === 0 || $jobs[0] !== "Street Performer") && setup.playerHasTrait("Performer")>> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #3e2a1a 0%, #2e1a1a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🎭 Performance Spot</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0; line-height: 1.4;">This park has great foot traffic and an open area perfect for performing. With your talents, you could draw a crowd and earn tips here.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🎭 Start Performing Here</div>">> <<if !$discoveredJobs>><<set $discoveredJobs = []>><</if>> <<if !$discoveredJobs.includes("Street Performer")>><<run $discoveredJobs.push("Street Performer")>><</if>> <<set $jobs = ["Street Performer"]>> <<goto "SeabassPark">> <</link>> </div> <</if>> <!-- Street Performer Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Street Performer">> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🎭 Street Performer Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Set up and perform for tips! Choose your act and build a crowd. (Max 8 hours/day)</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Work Shift</div>">> <<goto "StreetPerformerWork">> <</link>> </div> <</if>> <!-- Add after the travel grid, before NPCs section --> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "SeabassPark">> <<goto "CrimeHub">> <</link>> <</if>> </div> <!-- ===== SKILL TREE: Secret Park Entrance ===== --> <<if setup.skillTree.getEffect("parkEntrance")>> <div style="background: linear-gradient(135deg, #0a2a2a 0%, #0a1a1a 100%); padding: 20px; border-radius: 12px; margin: 20px 0; border: 3px solid #40E0D0; box-shadow: 0 0 20px rgba(64, 224, 208, 0.4);"> <h3 style="color: #40E0D0; margin: 0 0 15px 0; text-align: center;">🐟 Strange Pond 🐟</h3> <p style="color: #7dd3d3; font-size: 14px; text-align: center; margin: 0 0 15px 0; font-style: italic;"> A shimmering pond hidden behind the bushes catches your eye. The water glows with an unnatural turquoise light... </p> <div style="text-align: center;"> <<if ($skills && $skills.includes("Sunfish")) || ($physicalTraits && $physicalTraits.includes("Sunfish")) || ($mentalTraits && $mentalTraits.includes("Sunfish"))>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #40E0D0 0%, #20B2AA 100%); color: #000; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer; border: 2px solid #7FFFD4; box-shadow: 0 0 15px rgba(64, 224, 208, 0.5);'>🐟 Dive In</div>">> <<set $comingFromParkPond = true>> <<goto "TheAlter">> <</link>> <<else>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #1a3a3a 0%, #0a2020 100%); color: #5a9a9a; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer; border: 2px solid #2a5a5a; box-shadow: 0 0 10px rgba(64, 224, 208, 0.3);'>🐟 Dive In</div>">> <<run Dialog.setup("Strange Barrier", "park-barrier-dialog")>> <<run Dialog.wiki("<div style='text-align: center; padding: 20px;'><p style='font-size: 18px; color: #40E0D0; margin: 0 0 15px 0;'>🐟 You aren't fishy enough to enter. 🐟</p><p style='font-size: 14px; color: #888; margin: 0;'>The water seems to reject you...</p></div>")>> <<run Dialog.open()>> <</link>> <</if>> </div> </div> <</if>> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("SeabassPark")>> <h2 style="color: #4a7c2c;">🌳 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a7c2c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #4a7c2c; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #4a7c2c; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The park is peaceful and empty right now. Just you and the trees. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("LampreyTomes")>> <<run $visitedLocations.push("LampreyTomes")>> <</if>> <<set $lastLocation = "LampreyTomes">> <<run setup.tickOjouRefinement("lampreyTomes", 5)>> <!-- Sunfish Cuff: Revna leaves the Dorsal Spire here (one-time, max relationship + Cuff Band held) --> <<run setup.sunfishCuff.ensureState()>> <<set _cuffRevnaPts = ($relationships && $relationships["Revna McKraken"] && $relationships["Revna McKraken"].points) || 0>> <<set _cuffRevnaMax = setup.calculateRelationshipLevel(_cuffRevnaPts) >= 5>> <<if !$cuffRevnaGiftReceived && $cuffPieces && $cuffPieces.band && _cuffRevnaMax>> <div style="background: linear-gradient(135deg, #1a0a2a 0%, #2a1a3a 100%); border: 2px solid #b388ff; border-radius: 14px; padding: 22px; margin: 20px auto; max-width: 720px; box-shadow: 0 0 24px rgba(179,136,255,0.3);"> <p style="color: #e0c8ff; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;">The shopkeeper looks up before you can speak. “Something for you. Left it on the counter this morning.” She slides a small parcel across the wood. The wax seal has Revna McKraken's mark pressed into it.</p> <p style="color: #e0c8ff; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;">Inside the parcel, wrapped in oilcloth: a tall, narrow shard of pale metal, edge worn smooth by handling. A dorsal fin, stylized like a quill. The Dorsal Spire of the Sunfish Cuff.</p> <p style="color: #e0c8ff; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0; font-style: italic;">There is no note.</p> <p style="color: #b388ff; font-size: 14px; font-weight: bold; text-align: center; margin: 0;">You found the Dorsal Spire.</p> </div> <<run setup.sunfishCuff.grantPiece("spire"); State.variables.cuffRevnaGiftReceived = true;>> <</if>> <!-- Check if inventory needs to be refreshed (at noon) --> <<set _currentTomeBonus = setup.getSkillTreeTomeBonus()>> <<set _lastTomeBonus = $lampreyLastTomeBonus || 0>> <<set _bonusChanged = _currentTomeBonus !== _lastTomeBonus>> <<if !$lampreyInventory || setup.shouldRefreshLampreyInventory() || _bonusChanged>> <<set $lampreyInventory = setup.generateLampreyInventory()>> <<set $lampreyLastRefreshDay = $dayNumber>> <<set $lampreyLastRefreshAfterNoon = (Math.floor($timeInMinutes / 60) % 24) >= 12>> <<set $lampreyLastTomeBonus = _currentTomeBonus>> <<set $lampreyLastRevnaBoost = setup.getLampreyRevnaRareBoost()>> <</if>> <!-- ===== SKILL TREE: Get bonuses for display ===== --> <<set _skillTreeTomeDiscount = setup.getSkillTreeTomeDiscount()>> <<set _skillTreeTomeBonus = setup.getSkillTreeTomeBonus()>> <div style="background: linear-gradient(135deg, #0a0015 0%, #1a0a2e 50%, #16001e 100%); min-height: 100vh; padding: 20px; box-shadow: inset 0 0 100px rgba(139,0,255,0.3);"> <h1 style="color: #d4b3ff; text-align: center; text-shadow: 0 0 20px rgba(212,179,255,0.8), 0 0 40px rgba(139,0,255,0.5);">📚 Lamprey Tomes</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a0e4e 0%, #6b1e6b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8b00ff; box-shadow: 0 0 30px rgba(139,0,255,0.5), inset 0 0 20px rgba(177,156,217,0.2);"> <p style="color: #f0e5ff; font-size: 18px; margin: 0; text-shadow: 0 0 10px rgba(240,229,255,0.5);"> The smell of old paper and incense fills the air. Violet light emanates from mysterious crystals placed throughout the shop. Ancient tomes line the walls. Behind the counter stands Revna McKraken, her pale skin almost luminous in the ethereal glow, watching you with eyes that seem to pierce through your very soul. Her smile reveals just a hint of unusually sharp canines. </p> </div> <!-- Money Display --> <div style="background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2e 100%); padding: 15px; border-radius: 8px; border: 2px solid #8b00ff; margin-bottom: 20px; box-shadow: 0 0 20px rgba(139,0,255,0.4);"> <p style="color: #d4b3ff; margin: 0; text-align: center; font-size: 18px; text-shadow: 0 0 10px rgba(212,179,255,0.6);"> <strong>Your Money:</strong> <<print setup.formatMoney($money)>> </p> </div> <!-- Relationship Discount Display --> <<set _revnaRelationship = $relationships["Revna McKraken"] || {level: 1, points: 0}>> <<set _discount = setup.getLampreyDiscount()>> <<if _discount > 0>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #51cf66; margin-bottom: 20px; box-shadow: 0 0 15px rgba(81,207,102,0.4);"> <p style="color: #a3ff8f; margin: 0; text-align: center; font-size: 14px; font-weight: bold; text-shadow: 0 0 8px rgba(163,255,143,0.5);"> Relationship Discount: <<print Math.round(_discount * 100)>>% off all tomes </p> </div> <</if>> <!-- Revna's Favor: rare-tome chance boost --> <<set _revnaRareBoost = setup.getLampreyRevnaRareBoost()>> <<if _revnaRareBoost > 0>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #b388ff; margin-bottom: 20px; box-shadow: 0 0 15px rgba(179,136,255,0.4);"> <p style="color: #e0c8ff; margin: 0; text-align: center; font-size: 14px; font-weight: bold; text-shadow: 0 0 8px rgba(224,200,255,0.5);"> Revna's Favor: +<<print Math.round(_revnaRareBoost * 10000) / 100>>% chance for rarer tomes </p> </div> <</if>> <!-- Living Doll Discount Display --> <<if $physicalTraits && ($physicalTraits.includes("Living Doll") || $physicalTraits.includes("Automaton"))>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #e6c4ff; margin-bottom: 20px; box-shadow: 0 0 15px rgba(230,196,255,0.4);"> <p style="color: #e6c4ff; margin: 0; text-align: center; font-size: 14px; font-weight: bold; text-shadow: 0 0 8px rgba(230,196,255,0.5);"> ✓ <<if $physicalTraits.includes("Automaton")>>Automaton<<else>>Living Doll<</if>>: 60% off all tomes </p> </div> <</if>> <!-- ===== SKILL TREE: Bonus Display ===== --> <<if _skillTreeTomeDiscount > 0 || _skillTreeTomeBonus > 0>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #9C27B0; margin-bottom: 20px; box-shadow: 0 0 15px rgba(156,39,176,0.4);"> <p style="color: #CE93D8; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> ⭐ Skill Tree Bonuses: <<if _skillTreeTomeDiscount > 0>> -<<print _skillTreeTomeDiscount>>% prices <</if>> <<if _skillTreeTomeDiscount > 0 && _skillTreeTomeBonus > 0>> | <</if>> <<if _skillTreeTomeBonus > 0>> +<<print _skillTreeTomeBonus>> extra tome<<if _skillTreeTomeBonus !== 1>>s<</if>> daily <</if>> </p> </div> <</if>> <!-- NPC Interaction --> <<set _revna = setup.findNPCByName("Revna McKraken")>> <<if _revna>> <h2 style="color: #d4b3ff; text-shadow: 0 0 15px rgba(212,179,255,0.7);">Shopkeeper</h2> <div style="border: 3px solid #8b00ff; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2e 100%); box-shadow: 0 0 25px rgba(139,0,255,0.5); margin-bottom: 25px;"> <!-- NPC Image --> <<set _npcImage = setup.getNPCImage("Revna McKraken")>> <<if _npcImage>> <div style="text-align: center; margin-bottom: 20px;"> <img @src="_npcImage" style="max-width: 300px; max-height: 400px; border-radius: 10px; border: 3px solid #8b00ff; box-shadow: 0 0 20px rgba(139,0,255,0.6);" onerror="this.style.display='none';"> </div> <</if>> <h3 style="color: #d4b3ff; margin: 0 0 10px 0; text-shadow: 0 0 12px rgba(212,179,255,0.7);">Revna McKraken</h3> <p style="font-size: 14px; color: #e5d5ff; margin: 0 0 15px 0; line-height: 1.4;"> A hypnotic and cunning woman who pulls you in so naturally you don't even notice her pointy teeth. Her words and methods are strange, and she seems quite cagey about her past and personal life. You get the feeling she won't trade you anything of hers, but she might appreciate a donation. </p> <<link "<div style='background: linear-gradient(135deg, #8b00ff 0%, #6b1e6b 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 15px rgba(139,0,255,0.6); text-shadow: 0 0 5px rgba(255,255,255,0.5);'>Talk to Revna</div>">> <<set $tradingWithNPC = _revna>> <<goto "NPCInteraction">> <</link>> </div> <</if>> <!-- Special Books Shelf --> <<if !$ownsCogBook>> <h2 style="color: #cd7f32; text-shadow: 0 0 15px rgba(205,127,50,0.7);">⚙️ Curiosities Shelf</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 25px;"> <div style="border: 2px solid #cd7f32; border-radius: 8px; padding: 12px; background: linear-gradient(135deg, #2a1a0a 0%, #1a0a00 100%); box-shadow: 0 0 20px rgba(205,127,50,0.4), 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px;"> <h3 style="color: #cd7f32; margin: 0 0 10px 0; font-size: 16px; text-shadow: 0 0 15px rgba(205,127,50,0.5);">The Mechanical Codex</h3> <p style="color: #c9a06c; font-size: 12px; margin: 0 0 10px 0; line-height: 1.4;">A strange leather-bound tome with brass clasps and gears embedded in the cover. Revna eyes it warily.</p> <div style="flex-grow: 1;"></div> <p style="color: #ffd700; font-size: 14px; margin: 0 0 8px 0; font-weight: bold;"><<print setup.formatMoney($codexPrice)>></p> <<if $money >= $codexPrice>> <<link "<div style='background: linear-gradient(135deg, #cd7f32 0%, #8B6914 100%); color: white; padding: 8px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold;'>Purchase</div>">> <<set $money -= $codexPrice>> <<set $ownsCogBook = true>> <<goto "LampreyTomes">> <</link>> <<else>> <div style="background: #1a0a00; border: 1px solid #555; color: #888; padding: 8px; border-radius: 4px; text-align: center; font-size: 13px;">Not Enough Money</div> <</if>> </div> </div> <</if>> <!-- Foreign Slime recipe: only once the Mechanical Codex is owned, one-time $10,000 purchase --> <<if $ownsCogBook && !$ownsSlimeRecipe>> <h2 style="color: #4aa8ff; text-shadow: 0 0 15px rgba(74,168,255,0.7);">📜 Curiosities Shelf</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 25px;"> <div style="border: 2px solid #4aa8ff; border-radius: 8px; padding: 12px; background: linear-gradient(135deg, #0a1a2a 0%, #00101a 100%); box-shadow: 0 0 20px rgba(74,168,255,0.4), 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px;"> <h3 style="color: #4aa8ff; margin: 0 0 10px 0; font-size: 16px; text-shadow: 0 0 15px rgba(74,168,255,0.5);">A Recipe in Foreign Script</h3> <p style="color: #9cc4e0; font-size: 12px; margin: 0 0 10px 0; line-height: 1.4;">A water stained card covered in dense foreign writing. Revna says it goes with that codex you bought. She has no idea what it makes.</p> <div style="flex-grow: 1;"></div> <p style="color: #ffd700; font-size: 14px; margin: 0 0 8px 0; font-weight: bold;"><<print setup.formatMoney(10000)>></p> <<if $money >= 10000>> <<link "<div style='background: linear-gradient(135deg, #4aa8ff 0%, #1a6ab0 100%); color: white; padding: 8px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold;'>Purchase</div>">> <<set $money -= 10000>> <<set $ownsSlimeRecipe = true>> <<goto "LampreyTomes">> <</link>> <<else>> <div style="background: #00101a; border: 1px solid #555; color: #888; padding: 8px; border-radius: 4px; text-align: center; font-size: 13px;">Not Enough Money</div> <</if>> </div> </div> <</if>> <h2 style="color: #d4b3ff; text-shadow: 0 0 15px rgba(212,179,255,0.7);">Tomes for Sale</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 25px;"> <<for _i = 0; _i < $lampreyInventory.length; _i++>> <<set _item = $lampreyInventory[_i]>> <<set _rarityColor = setup.getRarityColor(_item.rarity)>> <<set _tomeName = setup.getTraitTomeName(_item.trait)>> <<set _discountedPrice = setup.calculateLampreyPrice(_item.price)>> <div style="border: 2px solid <<print _rarityColor>>; border-radius: 8px; padding: 12px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2e 100%); box-shadow: 0 0 20px <<print _rarityColor>>66, 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 140px;"> <h3 style="color: <<print _rarityColor>>; margin: 0 0 10px 0; font-size: 16px; text-shadow: 0 0 15px <<print _rarityColor>>, 0 0 25px <<print _rarityColor>>88;"><<print _tomeName>></h3> <div style="flex-grow: 1;"></div> <<if _discountedPrice < _item.price>> <p style="font-size: 14px; color: #888; margin: 0; text-align: center; text-decoration: line-through;"> <<print setup.formatMoney(_item.price)>> </p> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center; text-shadow: 0 0 10px rgba(81,207,102,0.6);"> <<print setup.formatMoney(_discountedPrice)>> </p> <<else>> <p style="font-size: 16px; color: #51cf66; margin: 0 0 10px 0; font-weight: bold; text-align: center; text-shadow: 0 0 10px rgba(81,207,102,0.6);"> <<print setup.formatMoney(_item.price)>> </p> <</if>> <<set _blockedByTransform = setup.isTraitBlockedByTransformation && (setup.isTraitBlockedByTransformation(_item.trait, "physical") || setup.isTraitBlockedByTransformation(_item.trait, "mental"))>> <<if _blockedByTransform>> <div style='background: linear-gradient(135deg, #5a2a4a 0%, #4a1a3a 100%); color: #ff9999; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #7b4a6b;'>Blocked by Transformation</div> <<elseif setup.hasLampreyTrait(_item.trait)>> <div style='background: linear-gradient(135deg, #4a2a5a 0%, #3a1a4a 100%); color: #c9a8ff; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a7b;'>Already Owned</div> <<elseif $money >= _discountedPrice>> <<capture _item, _rarityColor, _discountedPrice>> <<link "Purchase Tome">> <<set $money -= _discountedPrice>> <<if $physicalTraits.includes("Ocelomeh") && !$ocelomehFreeTomeToday && Math.random() < 0.20>> <<set $money += _discountedPrice>> <<set $ocelomehFreeTomeToday = true>> <<set $lampreyOcelomehFreeTome = true>> <<else>> <<set $lampreyOcelomehFreeTome = false>> <</if>> <<run setup.addLampreyTrait(_item.trait, _item.type)>> <!-- Random Revna dialogue --> <<set _revnaDialogue = [ "An excellent selection. The pages of this tome have been waiting for a reader such as yourself.", "How marvelous. I can see the words already weaving themselves into your essence.", "Yes... I suspected you would be drawn to this particular volume.", "A most discerning choice, dear patron. The knowledge within shall serve you exquisitely well.", "Ah, the wisdom contained in these pages is truly transformative. You shall find it most... enlightening.", "This manuscript has lingered on my shelves for some time, yearning for the right reader. How fortuitous.", "The binding itself seems to resonate with your presence. A perfect pairing, wouldn't you say?", "The ancient scribes would be pleased to know their words have found such a worthy inheritor.", "How delightful. Another soul enriched by the forbidden libraries of old.", "The illuminated script within holds secrets most profound. Use them as you see fit.", "A tome of considerable potency, that one. Its passages do not take kindly to careless readers.", "The vellum practically sings in your hands, does it not? A testament to its compatibility.", "Such refined taste. I do so appreciate a patron who recognizes quality literature.", "The ink upon those pages carries power most intoxicating. Savor each word carefully.", "These words have traveled through centuries to find you. Destiny, perhaps?" ].random()>> <<set $lampreyLastPurchaseDialogue = _revnaDialogue>> <<set $lampreyLastPurchasedTrait = _item.trait>> <<goto "LampreyTomesPurchase">> <</link>> <</capture>> <<else>> <div style='background: linear-gradient(135deg, #4a2a5a 0%, #3a1a4a 100%); color: #c9a8ff; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a7b;'>Not Enough Money</div> <</if>> </div> <</for>> </div> <!-- Leave --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <div style="border: 3px solid #8b00ff; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2e 100%); box-shadow: 0 0 25px rgba(139,0,255,0.5); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #d4b3ff; margin: 0 0 10px 0; text-shadow: 0 0 12px rgba(212,179,255,0.7);">🚪 Exit</h3> <p style="font-size: 14px; color: #e5d5ff; margin: 0 0 auto 0; line-height: 1.4;">Leave the mystical bookstore and return to the outskirts.</p> <<link "<div style='background: linear-gradient(135deg, #8b00ff 0%, #6b1e6b 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 15px rgba(139,0,255,0.6); text-shadow: 0 0 5px rgba(255,255,255,0.5);'>Leave Bookstore</div>">> <<goto "Outskirts">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Outskirts")>> <<run $visitedLocations.push("Outskirts")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <<set $lastLocation = "Outskirts">> <!-- Check if player has bank account --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #888; text-align: center;">🌾 Outskirts</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a4a4a 0%, #5a5a5a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #888;"> <p style="color: white; font-size: 18px; margin: 0;"> The city fades into rural landscape here. Scattered buildings line quieter roads, and open fields stretch beyond. The air feels fresher, the pace slower. This is where the urban sprawl meets the countryside. </p> </div> <h2 style="color: #888;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<goto "BusStop">> <</link>> </div> <!-- ATM --> <div style="border: 3px solid <<if _hasBankAccount>>#4dabf7<<else>>#555<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: <<if _hasBankAccount>>#4dabf7<<else>>#888<</if>>; margin: 0 0 10px 0;">🏧 ATM</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;"> <<if _hasBankAccount>> Quick cash withdrawals. FREE - no fees! $30,000/day limit. <<else>> Requires bank account. Open one at Sunfish City Bank for $250. <</if>> </p> <<if _hasBankAccount>> <<link "<div style='background: #4dabf7; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Use ATM</div>" "ATM">><</link>> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed; border: 1px solid #555;'> No Account </div> <</if>> </div> <!-- Lamprey Tomes (Evening/Night Only) --> <<if getTimeOfDay() === "evening" || getTimeOfDay() === "night">> <style> @keyframes violetPulse { 0% { box-shadow: 0 0 10px rgba(139,0,255,0.3), 0 0 20px rgba(139,0,255,0.2); } 50% { box-shadow: 0 0 20px rgba(139,0,255,0.8), 0 0 30px rgba(139,0,255,0.5); } 100% { box-shadow: 0 0 10px rgba(139,0,255,0.3), 0 0 20px rgba(139,0,255,0.2); } } .lamprey-glow { animation: violetPulse 3s ease-in-out infinite; } </style> <div class="lamprey-glow" style="border: 3px solid #8b00ff; border-radius: 10px; padding: 15px; background: #2a2a2a; display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #b19cd9; margin: 0 0 10px 0;">📚 Lamprey Tomes</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">A mysterious bookstore glowing with violet light.</p> <<link "<div style='background: #8b00ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bookstore</div>">> <<goto "LampreyTomes">> <</link>> </div> <</if>> <!-- Cafe Card (owned = active, not owned = abandoned) --> <<if $cafeOwnership && $cafeOwnership.owned>> <style> @keyframes floatHeart { 0% { opacity: 0; transform: translateY(0) scale(0.5); } 10% { opacity: 1; } 80% { opacity: 0.6; } 100% { opacity: 0; transform: translateY(-80px) scale(1); } } .pufferfish-card { position: relative; overflow: visible; animation: puffyGlow 3s ease-in-out infinite; } @keyframes puffyGlow { 0% { box-shadow: 0 0 10px rgba(255,105,180,0.3), 0 0 20px rgba(255,105,180,0.2); } 50% { box-shadow: 0 0 20px rgba(255,105,180,0.7), 0 0 35px rgba(255,105,180,0.4); } 100% { box-shadow: 0 0 10px rgba(255,105,180,0.3), 0 0 20px rgba(255,105,180,0.2); } } .pufferfish-card .heart-particle { position: absolute; font-size: 10px; pointer-events: none; animation: floatHeart 3s ease-out infinite; z-index: 10; color: #ff69b4; } .pufferfish-card .heart-particle:nth-child(1) { left: 15%; bottom: 20%; animation-delay: 0s; font-size: 8px; } .pufferfish-card .heart-particle:nth-child(2) { left: 45%; bottom: 30%; animation-delay: 0.7s; font-size: 12px; } .pufferfish-card .heart-particle:nth-child(3) { left: 75%; bottom: 15%; animation-delay: 1.4s; font-size: 9px; } .pufferfish-card .heart-particle:nth-child(4) { left: 30%; bottom: 40%; animation-delay: 2.1s; font-size: 11px; } .pufferfish-card .heart-particle:nth-child(5) { left: 60%; bottom: 25%; animation-delay: 0.3s; font-size: 7px; } .pufferfish-card .heart-particle:nth-child(6) { left: 85%; bottom: 35%; animation-delay: 1.8s; font-size: 10px; } </style> <div class="pufferfish-card" style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; display: flex; flex-direction: column; min-height: 180px;"> <span class="heart-particle">❤</span> <span class="heart-particle">❤</span> <span class="heart-particle">❤</span> <span class="heart-particle">❤</span> <span class="heart-particle">❤</span> <span class="heart-particle">❤</span> <h3 style="color: #ffb6c1; margin: 0 0 10px 0;">🐡 <<= $cafeOwnership.cafeName>></h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Your maid cafe. Fish-themed treats and charming staff.</p> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> <<else>> <div style="border: 3px solid #555; border-radius: 10px; padding: 15px; background: #1a1a1a; display: flex; flex-direction: column; min-height: 180px; opacity: 0.7;"> <h3 style="color: #666; margin: 0 0 10px 0;">🏚 Abandoned Cafe</h3> <p style="font-size: 14px; color: #555; margin: 0 0 auto 0; line-height: 1.4;">A rundown building with boarded-up windows. Looks like it could be something someday. Check Town Hall for property listings.</p> <div style="background: #333; color: #555; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;">Locked</div> </div> <</if>> <!-- Secret Door (appears once cafe is owned + all three maids hired) --> <<if $cafeOwnership && $cafeOwnership.owned && $cafeOwnership.staff && $cafeOwnership.staff.filter(function(s){ return setup.cafe.maidNPCs.has(s.name); }).length >= 3>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #1a1a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(201,169,255,0.2); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🚪 Hidden Door</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">An unmarked door tucked into the alley behind <<= $cafeOwnership.cafeName>>. You've never noticed it before. A tiny heart-shaped keyhole glints in the shadows.</p> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #8b6fc9 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<advancetime 2>> <<goto "SecretCafeDoor">> <</link>> </div> <</if>> </div> <h2 style="color: #888;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Industrial District (travel) --> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🏭 Industrial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Smelters, forge, and quarry. The working edge of town.</p> <<link "<div style='background: #555; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Head to the Industrial District</div>">> <<run advanceTime(15)>> <<goto "IndustrialOutskirts">> <</link>> </div> <!-- Seabass Park --> <div style="border: 3px solid #2d5016; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #4a7c2c; margin: 0 0 10px 0;">🌳 Seabass Park</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Public park with green spaces.</p> <<link "<div style='background: #2d5016; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Park</div>">> <<goto "SeabassPark">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">🌃 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Neon-lit entertainment district.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Outskirts")>> <h2 style="color: #888;">🌾 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #888; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic;"> A few people wander the quiet edges of the city... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #888; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The outskirts are quiet and empty. Just open fields and distant buildings. </p> </div> <</if>> <!-- CRIME SECTION --> <div style="text-align: center; margin: 20px 0;"> <<if $possessionActive>> <div style="display: inline-block; background: #1a1a1a; color: #555; padding: 10px 20px; border-radius: 6px; font-weight: bold; border: 2px solid #444; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: not-allowed; opacity: 0.55;">🦹 Criminal Activities (Locked by Possession)</div> <<else>> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #666; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🦹 Criminal Activities</div>">> <<set $currentCrimeLocation = "Outskirts">> <<goto "CrimeHub">> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <!-- Unlock buy tome achievement --> <<run setup.achievements.unlock("buy_tome")>> <!-- Check for Lucky trait achievement --> <<if $lampreyLastPurchasedTrait === "Lucky">> <<run setup.achievements.unlock("lucky_trait")>> <</if>> <!-- Check for Bimbo trait achievement --> <<if $lampreyLastPurchasedTrait === "Bimbo">> <<run setup.achievements.unlock("become_bimbo")>> <</if>> <!-- Check for gigantic proportions WITHOUT bimbo achievement --> <<if $bodyParts.chest === "gigantic" && $bodyParts.butt === "gigantic">> <<if !$mentalTraits || !$mentalTraits.includes("Bimbo")>> <<run setup.achievements.unlock("gigantic_no_bimbo")>> <</if>> <</if>> <<set $lastLocation = "LampreyTomesResult">> <!-- Determine trait type if not already set --> <<if !$lampreyLastPurchasedTraitType>> <<set _trait = $lampreyLastPurchasedTrait>> <<if $physicalTraits.includes(_trait)>> <<set $lampreyLastPurchasedTraitType = "physical">> <<elseif $mentalTraits.includes(_trait)>> <<set $lampreyLastPurchasedTraitType = "mental">> <<elseif $skills.includes(_trait)>> <<set $lampreyLastPurchasedTraitType = "skill">> <<else>> <<set $lampreyLastPurchasedTraitType = "unknown">> <</if>> <</if>> <div style="background: linear-gradient(135deg, #0a0015 0%, #1a0a2e 50%, #16001e 100%); min-height: 100vh; padding: 20px; box-shadow: inset 0 0 100px rgba(139,0,255,0.3);"> <h1 style="color: #d4b3ff; text-align: center; text-shadow: 0 0 20px rgba(212,179,255,0.8), 0 0 40px rgba(139,0,255,0.5);">📚 Lamprey Tomes</h1> <!-- Trait Acquired Display --> <div style="padding: 20px; background: linear-gradient(135deg, #1a4a1a 0%, #2d6b2d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #51cf66; box-shadow: 0 0 30px rgba(81,207,102,0.5), inset 0 0 20px rgba(81,207,102,0.2);"> <p style="color: #a3ff8f; font-size: 22px; margin: 0 0 15px 0; text-align: center; font-weight: bold; text-shadow: 0 0 15px rgba(163,255,143,0.8);"> ✨ Trait Acquired: <<print $lampreyLastPurchasedTrait>> ✨ </p> <p style="color: #e0ffe0; font-size: 16px; margin: 0; text-align: center;"> The ancient knowledge flows into your being, transforming you from within. </p> </div> <!-- Ocelomeh Free Tome Notification --> <<if $lampreyOcelomehFreeTome>> <div style="padding: 15px; background: linear-gradient(135deg, #4a3a1a 0%, #6b5a2d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffc107; box-shadow: 0 0 30px rgba(255,193,7,0.5);"> <p style="color: #ffe082; font-size: 18px; margin: 0; text-align: center; font-weight: bold; text-shadow: 0 0 15px rgba(255,224,130,0.8);"> 🐾 Ocelomeh Instinct: FREE TOME! 🐾 </p> <p style="color: #ffd54f; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> Your predatory instincts kicked in — you swiped the tome without Revna noticing! No charge today. </p> </div> <</if>> <!-- Transformation Image Display --> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _traitKey = $lampreyLastPurchasedTrait.toLowerCase().replace(/\s+/g, "_")>> <<set _genderKey = $bodyParts.gender || "female">> <<set _ageKey = $appearance.age === "Mature Adult" ? "mature" : "adult">> <div style="text-align: center; margin-bottom: 25px;"> <img src="Images/Transformations/<<print _traitKey>>_result_<<print _genderKey>>_<<print _ageKey>>.webp" style="max-width: 600px; max-height: 600px; border-radius: 15px; border: 3px solid #8b00ff; box-shadow: 0 0 30px rgba(139,0,255,0.7);" onerror="this.onerror=null; this.style.display='none'; this.nextElementSibling.style.display='block';"> <div style="display: none; background: #2a2a2a; width: 400px; height: 300px; border-radius: 15px; border: 3px solid #8b00ff; margin: 0 auto; box-shadow: 0 0 30px rgba(139,0,255,0.3);"></div> </div> <</if>> <!-- Transformation Text Display --> <div style="padding: 20px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2e 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #b19cd9; box-shadow: 0 0 25px rgba(177,156,217,0.5), inset 0 0 15px rgba(177,156,217,0.2);"> <h3 style="color: #d4b3ff; margin: 0 0 15px 0; text-align: center; text-shadow: 0 0 12px rgba(212,179,255,0.7);"> 🌟 Transformation </h3> <<set _trait = $lampreyLastPurchasedTrait>> <<set _traitType = $lampreyLastPurchasedTraitType>> <!-- Physical Trait Transformation --> <<if _traitType === "physical">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #28a745;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getPhysicalTraitChangeText(_trait, true)>> </p> </div> <!-- Special transformation text for specific traits --> <<if _trait === "Were-Creature">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #ffa500;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getWereCreatureTransformationText(true, "wolf")>> </p> </div> <<elseif _trait === "Definitely not a Vampire">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #8b0000;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getVampireTransformationText(true)>> </p> </div> <<elseif _trait === "Sunfish">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #4169e1;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSunfishTransformationText(true)>> </p> </div> <</if>> <!-- Mental Trait Transformation --> <<elseif _traitType === "mental">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #764ba2;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getMentalTraitChangeText(_trait, true)>> </p> </div> <!-- Special Bimbo transformation --> <<if _trait === "Bimbo">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #ff69b4;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getBimboTransformationText(true)>> </p> </div> <</if>> <!-- Skill Gain --> <<elseif _traitType === "skill">> <div style="background: #1a1a1a; padding: 15px; margin: 10px 0; border-radius: 8px; border: 2px solid #ffc107;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSkillGainText(_trait)>> </p> </div> <!-- Fallback for unknown type --> <<else>> <p style="color: #e5d5ff; font-size: 16px; margin: 0; line-height: 1.6; text-align: center;"> You feel the mystical energy of the tome coursing through your veins as the trait "<strong>_trait</strong>" becomes part of your very essence. </p> <</if>> </div> <!-- Revna's Dialogue --> <div style="padding: 30px; background: linear-gradient(135deg, #4a0e4e 0%, #6b1e6b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8b00ff; box-shadow: 0 0 30px rgba(139,0,255,0.5), inset 0 0 20px rgba(177,156,217,0.2);"> <p style="color: #f0e5ff; font-size: 20px; margin: 0 0 20px 0; text-align: center; font-style: italic; text-shadow: 0 0 10px rgba(240,229,255,0.5);"> "<<print $lampreyLastPurchaseDialogue>>" </p> <p style="color: #d4b3ff; font-size: 16px; margin: 0; text-align: center;"> The power flows through you as Revna's eyes gleam with mysterious satisfaction. </p> </div> <div style="text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #8b00ff 0%, #6b1e6b 100%); color: white; padding: 15px 30px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 15px rgba(139,0,255,0.6); text-shadow: 0 0 5px rgba(255,255,255,0.5);'>Continue Shopping</div>">> <<unset $lampreyLastPurchasedTraitType>> <<goto "LampreyTomes">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #7dd3fc; color: white; padding: 12px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(125,211,252,0.25); display: inline-block;'>← Back</div>">> <<if $lastLocation && $lastLocation !== "Credits" && $lastLocation !== "ArtGallery">> <<goto $lastLocation>> <<else>> <<goto "Start">> <</if>> <</link>> </div> <!-- Title --> <div style="text-align: center; margin-bottom: 30px;"> <div style="color: #7dd3fc; margin: 0 0 5px 0; font-size: 32px; font-weight: bold;">Sunfish City</div> <p style="color: #666; font-size: 14px; margin: 0;">Credits & Acknowledgments</p> </div> <!-- Game Credits --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #7dd3fc; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #7dd3fc; margin: 0 0 15px 0; text-align: center; font-size: 20px;">🎮 Game</h2> <div style="text-align: center;"> <p style="color: #eee; font-size: 16px; margin: 0 0 5px 0;"><strong>Created by</strong> Grankor</p> <p style="color: #888; font-size: 13px; margin: 0;">Built with Twine & SugarCube 2.36.1</p> </div> </div> <!-- Patron NPCs --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #ffd700; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffd700; margin: 0 0 15px 0; text-align: center; font-size: 20px;">⭐ Patron NPCs</h2> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <div style="background: rgba(255,215,0,0.08); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #ffd700; font-weight: bold; font-size: 13px;">Cerberus</div> <div style="color: #ccc; font-size: 12px;">Fen Ris</div> </div> <div style="background: rgba(255,215,0,0.08); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #ffd700; font-weight: bold; font-size: 13px;">The Flying Duckman</div> <div style="color: #ccc; font-size: 12px;">Revna McKraken</div> </div> <div style="background: rgba(255,215,0,0.08); border: 1px solid rgba(255,215,0,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #ffd700; font-weight: bold; font-size: 13px;">Ratticus</div> <div style="color: #ccc; font-size: 12px;">Luna Snow</div> </div> </div> <p style="color: #aaa; text-align: center; font-size: 12px; margin: 15px 0 0 0; font-style: italic;">Banana tier patrons and above can get their own custom NPC (within reason)!</p> </div> <!-- Wiki Contributors --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4ade80; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #4ade80; margin: 0 0 5px 0; text-align: center; font-size: 20px;">📖 <a href="https://wiki.grankgames.com/index.php?title=Main_Page" target="_blank" style="color: #4ade80; text-decoration: underline;">Wiki</a> Contributors</h2> <p style="color: #aaa; text-align: center; font-size: 13px; margin: 0 0 15px 0;">Contributors who have an NPC are shown below their name.</p> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <div style="background: rgba(74,222,128,0.08); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #4ade80; font-weight: bold; font-size: 13px;">CranberryPurree</div> <div style="color: #ccc; font-size: 12px;">Cid Cranberry</div> </div> <div style="background: rgba(74,222,128,0.08); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #4ade80; font-weight: bold; font-size: 13px;">TheSlyCoopster</div> </div> <div style="background: rgba(74,222,128,0.08); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #4ade80; font-weight: bold; font-size: 13px;">anrie</div> </div> <div style="background: rgba(74,222,128,0.08); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #4ade80; font-weight: bold; font-size: 13px;">jade0352</div> </div> <div style="background: rgba(74,222,128,0.08); border: 1px solid rgba(74,222,128,0.3); border-radius: 8px; padding: 8px 14px; text-align: center;"> <div style="color: #4ade80; font-weight: bold; font-size: 13px;">Rainbow kittens</div> </div> </div> </div> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(224,64,251,0.4); display: inline-block;'>🖼️ Art Gallery</div>">> <<goto "ArtGallery">> <</link>> </div> <!-- Commissioned Artists --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #e040fb; border-radius: 12px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #e040fb; margin: 0 0 15px 0; text-align: center; font-size: 20px;">🎨 Commissioned Artists</h2> <div style="display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin-top: 15px;"> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Santiart7</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Santiart7" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/2_larrosa?t=Juh_JaiUUOuxYRoA5bHptA" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.instagram.com/santiart7" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Starstruckofficialz</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Starstruckofficialz" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.instagram.com/starstruckofficial18?utm_source=qr" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://www.tiktok.com/@bunzyewlf?_r=1&_t=ZN-94jpZCzwICc" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">TikTok</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">CranberryPurree</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">YouTube</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Prof.Thresh</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/profthresh" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.youtube.com/@profthresh" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Youtube</a> <a href="https://x.com/profthresh" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Schlee</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/schlee" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.instagram.com/schleezee/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://x.com/schleezi" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Brownice</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Brownice" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/Iceicebrownice" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.pixiv.net/en/users/96269510" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Pixiv</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Roxx</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/RoxxLuma/portfolio" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">rinkatth</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/rinkatth" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.instagram.com/rinkatth" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://x.com/rinkatth_katy" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Rain_Lambda</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Rain_Lambda" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/Rain_Lambda" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://rlambdart.carrd.co/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Portfolio</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Mio✧・゚</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Aimio" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://linktr.ee/miiaiko" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Linktree</a> <a href="https://www.tiktok.com/@miomayoi" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">TikTok</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">yodogama</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/yodogama" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.patreon.com/yodogama" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Patreon</a> <a href="https://x.com/yodogama" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://x.com/yabegama_art" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter (NSFW)</a> <a href="https://www.pixiv.net/en/users/86168400" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Pixiv</a> <a href="https://bsky.app/profile/yodogama.bsky.social" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Bluesky</a> <a href="https://bsky.app/profile/yodogama-nsfw.bsky.social" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Bluesky (NSFW)</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Cress🔮</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/bunvinyl" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/bunvinyl" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.instagram.com/bunvinyl?utm_source=qr" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://youtube.com/@cressdavids?si=xULEt0SqeQpawrzf" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Youtube</a> <a href="https://www.tiktok.com/@bunvinyl?_t=ZN-8vWDHog3GS6&_r=1" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">TikTok</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Lazulash Star 🦭</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Lazulash_star" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.instagram.com/lazulash_art" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://x.com/Lazulash_Star?t=6YzwPu_YXn0pxEEuurpU0Q" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.tiktok.com/@lazulash_star?_t=ZM-8uwHpftMGOL&_r=1" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">TikTok</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">auzulvox</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/auzulvox" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.twitch.tv/auzulvox" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitch</a> <a href="https://www.youtube.com/@AuzulVox" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Youtube</a> <a href="https://www.pixiv.net/en/users/114015112" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Pixiv</a> <a href="https://x.com/AuzulVox" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://bsky.app/profile/auzulvox.bsky.social" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Bluesky</a> <a href="https://www.tiktok.com/@auzul.vox" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">TikTok</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">「 Layla 」≽༏≼</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Layla_chiii" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/Layla_chiii" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.deviantart.com/isi-chisi" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">DeviantArt</a> <a href="https://toyhou.se/isi-chisi" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Toyhouse</a> <a href="https://www.twitch.tv/layla_chii" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitch</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">VeckHick</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/VeckHick" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/VeckHick" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.twitch.tv/VeckHick" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitch</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">GhostFireee</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/GhostFireee" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/GhostFireee" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.facebook.com/GhostyFire3000" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Facebook</a> <a href="https://t.me/GhostFireCMM" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Telegram</a> <a href="https://www.furaffinity.net/user/ghostfireee/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">FurAffinity</a> <a href="https://ping.commishes.com/@ghostfire/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Commishes</a> <a href="https://ghostfirecommissions.carrd.co/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Portfolio</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Cigmaier</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Cigmaier" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/Cigmaier" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.instagram.com/cigmaier/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://bsky.app/profile/cigmaier.bsky.social" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Bluesky</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Brownie B.</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/brownie_bzk" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.instagram.com/brownie_bazooka" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> <a href="https://acggoods.com/store/brownie-bazooka" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Store</a> <a href="https://ko-fi.com/brownie_bzk" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Ko-fi</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Sea Sluggy</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/seasluggy" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://seasluggypixy.carrd.co/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Portfolio</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Don Cross Xart VT</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/doncrossxart" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://kick.com/don-cross-Sutcliff" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Kick</a> <a href="https://x.com/doncrossxart" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.twitch.tv/don_cross_Sutcliff" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitch</a> </div> </div> <!-- COLYCYCLE_CREDIT_CARD_START --> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">colycycle</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/colycycle" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://www.pixiv.net/en/users/30586101" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Pixiv</a> <a href="https://x.com/colycycle" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> </div> </div> <!-- COLYCYCLE_CREDIT_CARD_END --> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">yamiinkfusion</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/yamiinkfusion" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/yamiinkfusion" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.twitch.tv/yamiinkfusion" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitch</a> <a href="https://www.youtube.com/@yamiinkfusion" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Youtube</a> <a href="https://www.instagram.com/yamiinkfusion/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">1z10</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/1z10" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/1z10a/media" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.pixiv.net/en/users/51876730" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Pixiv</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Rukaez</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/rumiraikae" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/rurumirai_xoxo" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.facebook.com/rurukae.ube" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Facebook</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">MashiAka</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/MashiAka" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/Mashiart851" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">veryvance</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://www.tiktok.com/@veryvance" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">TikTok</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">SirMao_13</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/SirMao_13" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/SirMao_13" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://x.com/LB_Draw" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter (LB_Draw)</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Akinap</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Akinap" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/AkiNapsz" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://ko-fi.com/akinapsz" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Ko-fi</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Psychromaniac</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://psychart.carrd.co/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Portfolio</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">In_sans_</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/In_sans_" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://whtewolf.artstation.com/" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">ArtStation</a> <a href="https://www.instagram.com/in_sans_" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Instagram</a> </div> </div> <div style="background: rgba(224,64,251,0.08); border: 1px solid rgba(224,64,251,0.3); border-radius: 10px; padding: 12px 18px; text-align: center; min-width: 180px;"> <div style="color: #e040fb; font-weight: bold; font-size: 16px; margin-bottom: 6px;">Paharaptor</div> <div style="display: flex; gap: 8px; justify-content: center; flex-wrap: wrap;"> <a href="https://vgen.co/Paharaptor" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Vgen</a> <a href="https://x.com/PahaRaptor" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Twitter</a> <a href="https://www.pixiv.net/en/users/55211967" target="_blank" style="color: #7dd3fc; font-size: 12px; text-decoration: none; background: rgba(125,211,252,0.1); padding: 4px 10px; border-radius: 6px; border: 1px solid rgba(125,211,252,0.3);">Pixiv</a> </div> </div> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #7dd3fc; color: white; padding: 12px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(125,211,252,0.25); display: inline-block;'>← Back</div>">> <<if $lastLocation && $lastLocation !== "Credits" && $lastLocation !== "ArtGallery">> <<goto $lastLocation>> <<else>> <<goto "Start">> <</if>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "UseLaptop">> <!-- Initialize WiFi variables if not set --> <<if $wifiDaysRemaining === undefined>> <<set $wifiDaysRemaining = 0>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">💻 Your Laptop</h1> <div style="padding: 20px; background: linear-gradient(135deg, #17a2b8 0%, #138496 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> You sit at your desk and open your laptop. The screen glows softly as various applications and options become available. </p> </div> <!-- Social Media Influencer Discovery --> <<if (!$jobs || $jobs.length === 0 || $jobs[0] !== "Social Media Influencer") && setup.playerHasTrait("Social Media")>> <div style="border: 3px solid #e040fb; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #3a1a4e 0%, #2a1a3e 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e040fb; margin: 0 0 10px 0;">📱 Content Creator Opportunity</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0; line-height: 1.4;">With your social media savvy, you could start creating content and building a following. All you need is your laptop and some creativity to begin your influencer career.</p> <<link "<div style='background: #e040fb; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>📱 Start Your Influencer Career</div>">> <<if !$discoveredJobs>><<set $discoveredJobs = []>><</if>> <<if !$discoveredJobs.includes("Social Media Influencer")>><<run $discoveredJobs.push("Social Media Influencer")>><</if>> <<set $jobs = ["Social Media Influencer"]>> <<goto "UseLaptop">> <</link>> </div> <</if>> <!-- Social Media Influencer Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Social Media Influencer">> <div style="border: 3px solid #e040fb; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e040fb; margin: 0 0 10px 0;">📱 Social Media Influencer</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Create content, grow your followers, and earn ad revenue! Choose from selfies, sponsored posts, collabs, or viral challenges. (Flexible hours, max 8 hours/day)</p> <<if !$hasRouter || !$wifiSetupComplete>> <div style="background: #3a1a1a; padding: 10px; border-radius: 6px; text-align: center; color: #e74c3c; font-weight: bold;">❌ Requires Internet — Buy a router and set up WiFi at Hammerhead Tech</div> <<elseif $wifiDaysRemaining <= 0>> <div style="background: #3a1a1a; padding: 10px; border-radius: 6px; text-align: center; color: #e74c3c; font-weight: bold;">❌ Internet Expired — Renew your service at Hammerhead Tech</div> <<elseif !$bankAccount || !$bankAccount.hasAccount>> <div style="background: #3a1a1a; padding: 10px; border-radius: 6px; text-align: center; color: #e74c3c; font-weight: bold;">❌ Requires Bank Account — Open one at Downtown Bank</div> <<else>> <<link "<div style='background: #e040fb; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Content Session</div>">> <<goto "SocialMediaInfluencerWork">> <</link>> <</if>> </div> <</if>> <!-- WiFi Status Display --> <<if $hasRouter>> <<if $wifiDaysRemaining > 0>> <div style="border: 2px solid #51cf66; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #51cf66; margin: 0 0 10px 0; font-size: 16px;">✅ WiFi Connected</h3> <p style="font-size: 14px; color: #aaa; margin: 0; text-align: center;">Internet service active. Days remaining: <<print $wifiDaysRemaining>></p> </div> <<else>> <div style="border: 2px solid #dc3545; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #dc3545; margin: 0 0 10px 0; font-size: 16px;">❌ No Internet Connection</h3> <p style="font-size: 14px; color: #aaa; margin: 0; text-align: center;">Your internet service has expired. Pay for service at Hammerhead Tech.</p> </div> <</if>> <!-- Pay for WiFi from Home (Bank Account Only) --> <<if $wifiDaysRemaining > 0>> <div style="border: 2px solid #28a745; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #28a745; margin: 0 0 10px 0; font-size: 16px;">💳 Pay for Internet Service</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Add 30 days of internet service for $40. Payment is automatically deducted from your bank account.</p> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<if _hasBankAccount && $bankAccount.balance >= 40>> <p style="font-size: 12px; color: #667eea; margin: 0 0 10px 0;">Bank Balance: $<<print $bankAccount.balance>></p> <<link "<div style='background: #28a745; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>Pay $40 from Bank Account</div>">> <<set $bankAccount.balance -= 40>> <<set $wifiDaysRemaining += 30>> <<goto "UseLaptop">> <</link>> <<elseif !_hasBankAccount>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Requires Bank Account</div> <p style="font-size: 12px; color: #888; margin: 10px 0 0 0; text-align: center;">Visit Sunfish Bank to open an account.</p> <<else>> <p style="font-size: 12px; color: #667eea; margin: 0 0 10px 0;">Bank Balance: $<<print $bankAccount.balance>></p> <div style='background: #4a2a2a; color: #c9a8a8; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a;'>Insufficient Bank Funds</div> <</if>> </div> <</if>> <<else>> <div style="border: 2px solid #dc3545; border-radius: 8px; padding: 12px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h3 style="color: #dc3545; margin: 0 0 10px 0; font-size: 16px;">❌ No Router</h3> <p style="font-size: 14px; color: #aaa; margin: 0; text-align: center;">You need to buy a router and set up internet service at Hammerhead Tech.</p> </div> <</if>> <h2 style="color: #17a2b8;">What would you like to do?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Browse Internet --> <<set _internetColor = ($wifiDaysRemaining > 0) ? "#667eea" : "#666">> <<set _internetTextColor = ($wifiDaysRemaining > 0) ? "#aaa" : "#888">> <div style="border: 3px solid <<print _internetColor>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: <<print _internetColor>>; margin: 0 0 10px 0;">🌐 Browse Internet</h3> <p style="font-size: 14px; color: <<print _internetTextColor>>; margin: 0 0 auto 0; line-height: 1.4;">Surf the web, check social media, and waste time online.</p> <<if $wifiDaysRemaining > 0>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Browse Internet</div>">> <<goto "BrowseInternet">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px;'>Requires Internet</div> <</if>> </div> <!-- Check Email --> <<set _emailColor = ($wifiDaysRemaining > 0) ? "#ffc107" : "#666">> <<set _emailTextColor = ($wifiDaysRemaining > 0) ? "#aaa" : "#888">> <div style="border: 3px solid <<print _emailColor>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: <<print _emailColor>>; margin: 0 0 10px 0;">📧 Check Email</h3> <p style="font-size: 14px; color: <<print _emailTextColor>>; margin: 0 0 auto 0; line-height: 1.4;">Read your emails and respond to messages.</p> <<if $wifiDaysRemaining > 0>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px;'>Requires Internet</div> <</if>> </div> <!-- Play Games --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🎮 Play Games</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Play some video games to relax and pass time.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Work from Home --> <<set _workColor = ($wifiDaysRemaining > 0) ? "#28a745" : "#666">> <<set _workTextColor = ($wifiDaysRemaining > 0) ? "#aaa" : "#888">> <div style="border: 3px solid <<print _workColor>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: <<print _workColor>>; margin: 0 0 10px 0;">💼 Work from Home</h3> <p style="font-size: 14px; color: <<print _workTextColor>>; margin: 0 0 auto 0; line-height: 1.4;">Do some freelance work or remote tasks to earn money.</p> <<if $wifiDaysRemaining > 0>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px;'>Requires Internet</div> <</if>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Close Laptop</div>">> <<set $streamingFromStudio = false>> <<if $laptopReturnLocation>> <<goto $laptopReturnLocation>> <<else>> <<goto setup.getCurrentHome()>> <</if>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "WatchTV">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">📺 Watching TV</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0;"> You settle onto the couch and turn on the TV. The screen flickers to life, offering various channels and streaming options. </p> </div> <h2 style="color: #667eea;">What would you like to watch?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Watch News --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">📰 Watch News</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Catch up on current events and local news.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Watch Movies --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🎬 Watch Movies</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Browse streaming services for movies to watch.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Watch Sports --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">⚽ Watch Sports</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Check out live games and sports highlights.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Watch Shows --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">📺 Watch Shows</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Binge some TV series and episodes.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Turn Off TV</div>">> <<goto setup.getCurrentHome()>> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">📡 WiFi Setup Complete</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Tech Store Clerk">> You successfully set up your WiFi router at home. Your internet connection is now ready to use! <<else>> The store clerk helped you set up your WiFi router at home. Your internet connection is now ready to use! <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #51cf66; margin: 0 0 15px 0; text-align: center;">✅ Setup Successful</h2> <p style="color: #aaa; margin: 0 0 10px 0; text-align: center;">Your router has been configured and is broadcasting WiFi.</p> <p style="color: #ccc; margin: 0; text-align: center; font-size: 14px;">Remember: You need to pay $40/month for internet service to keep it active.</p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #17a2b8; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Store</div>">> <<goto "TechStore">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BrowseInternet">> <!-- Auto-register if not already registered --> <<if $streamingRegistered === undefined>> <<set $streamingRegistered = true>> <</if>> <<if $contentCreatorRegistered === undefined>> <<set $contentCreatorRegistered = true>> <</if>> <<if $prawnhubRegistered === undefined>> <<set $prawnhubRegistered = true>> <</if>> <!-- FIXED: Check for bank account using correct property --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <style> .internet-grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(2, auto); gap: 15px; margin-bottom: 25px; } .internet-card { border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; } /* Explicit grid positions */ .grid-pos-1 { grid-column: 1; grid-row: 1; } .grid-pos-2 { grid-column: 2; grid-row: 1; } .grid-pos-3 { grid-column: 3; grid-row: 1; } .grid-pos-4 { grid-column: 1; grid-row: 2; } .grid-pos-5 { grid-column: 2; grid-row: 2; } .grid-pos-6 { grid-column: 3; grid-row: 2; } .card-title { margin: 0 0 10px 0; } .card-description { font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1; } .card-button { padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; color: white; } .card-button-disabled { background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px; } .card-button-coming-soon { background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; } </style> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">🌐 Browsing the Internet</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0;"> You're connected to the internet. Various websites and platforms are available for you to explore. </p> </div> <h2 style="color: #667eea;">What would you like to do?</h2> <div class="internet-grid"> <!-- Position 1: Social Media --> <div class="internet-card grid-pos-1" style="border: 3px solid #3498db;"> <h3 class="card-title" style="color: #3498db;">📱 Social Media</h3> <p class="card-description">Browse social media feeds and interact with posts.</p> <div class="card-button-coming-soon">Coming Soon</div> </div> <!-- Position 2: News & Articles --> <div class="internet-card grid-pos-2" style="border: 3px solid #f39c12;"> <h3 class="card-title" style="color: #f39c12;">📰 News & Articles</h3> <p class="card-description">Read the latest news and trending articles.</p> <div class="card-button-coming-soon">Coming Soon</div> </div> <!-- Position 3: Content Creation Platform --> <div class="internet-card grid-pos-3" style="border: 3px solid #e74c3c;"> <h3 class="card-title" style="color: #e74c3c;">🎬 Post Content</h3> <p class="card-description">Create and post videos or photos to earn money.</p> <<if $hasWebcam>> <<link "<div class='card-button' style='background: #e74c3c;'>Create Content</div>">> <<goto "PostContent">> <</link>> <<else>> <div class="card-button-disabled">Requires Webcam</div> <</if>> </div> <!-- Position 4: Streaming Platform --> <div class="internet-card grid-pos-4" style="border: 3px solid #9b59b6;"> <h3 class="card-title" style="color: #9b59b6;">📹 Streaming Platform</h3> <p class="card-description"> Followers: <strong style="color: #e74c3c;"><<= $streamingData ? $streamingData.followers : 0>></strong><br> Total Streams: <<= $streamingData ? $streamingData.totalStreams : 0>> </p> <<if !$hasWebcam>> <div class="card-button-disabled">Requires Webcam</div> <<elseif !_hasBankAccount>> <div class="card-button-disabled">Requires Bank Account</div> <<elseif $jobs && $jobs.includes("Criminal")>> <<link "<div class='card-button' style='background: #9b59b6;'>Go Live</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "streaming">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div class='card-button' style='background: #9b59b6;'>Go Live</div>">> <<goto "SelectStreamCategory">> <</link>> <</if>> </div> <!-- Position 5: Stream Analytics --> <div class="internet-card grid-pos-5" style="border: 3px solid #27ae60;"> <h3 class="card-title" style="color: #27ae60;">📊 Stream Analytics</h3> <p class="card-description">View your streaming statistics, growth trends, and performance metrics.</p> <<link "<div class='card-button' style='background: #27ae60;'>View Analytics</div>">> <<goto "StreamAnalytics">> <</link>> </div> <!-- Position 6: PrawnHub --> <div class="internet-card grid-pos-6" style="border: 3px solid #ff1493;"> <h3 class="card-title" style="color: #ff1493;">🔞 PrawnHub</h3> <p class="card-description">Adult entertainment platform for browsing and streaming adult content.</p> <<link "<div class='card-button' style='background: #ff1493;'>Enter Site</div>">> <<goto "PrawnHub">> <</link>> </div> </div> <!-- Bank Account Requirement Notice (for streaming platforms) --> <<if !_hasBankAccount && $hasWebcam>> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #667eea; box-shadow: 0 4px 8px rgba(102,126,234,0.4);"> <h3 style="color: white; margin: 0 0 10px 0; text-align: center;">💳 Bank Account Required for Streaming</h3> <p style="color: white; margin: 0; text-align: center; font-size: 15px;"> Digital streaming platforms require a bank account to receive donations, tips, and revenue payments.<br><br> Open a bank account at the Sunfish City Bank in Downtown. </p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Laptop</div>">> <<goto "UseLaptop">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StreamingRegistration">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">📹 Streaming Registration Complete</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> You've successfully registered for a streaming platform! You can now go live and broadcast content to viewers who can tip you or subscribe to your channel. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #51cf66; margin: 0 0 15px 0; text-align: center;">✅ Account Created</h2> <p style="color: #aaa; margin: 0 0 10px 0; text-align: center;">Your streaming profile has been set up and verified.</p> <p style="color: #ccc; margin: 0; text-align: center; font-size: 14px;">You can now start streaming from the Browse Internet menu.</p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <</nobr>>
<!-- Browse Internet --> <<set _internetColor = ($wifiDaysRemaining > 0) ? "#667eea" : "#666">> <<set _internetTextColor = ($wifiDaysRemaining > 0) ? "#aaa" : "#888">> <div style="border: 3px solid <<print _internetColor>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: <<print _internetColor>>; margin: 0 0 10px 0;">🌐 Browse Internet</h3> <p style="font-size: 14px; color: <<print _internetTextColor>>; margin: 0 0 auto 0; line-height: 1.4;">Surf the web, check social media, and waste time online.</p> <<if $wifiDaysRemaining > 0>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Browse Internet</div>">> <<goto "BrowseInternet">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px;'>Requires Internet</div> <</if>> </div>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e74c3c; text-align: center;">🎬 Content Creation</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e74c3c;"> <p style="color: white; font-size: 18px; margin: 0;"> Create and upload photos or videos to your content platform. Your earnings depend on views, likes, and subscriber count. </p> </div> <h2 style="color: #e74c3c;">What type of content would you like to create?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">📸 Photo Content</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Take and upload photos for your followers.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🎥 Video Content</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Record and upload videos for your audience.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">📹 Live Streaming</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> Go live and interact with your audience in real-time. Earn money through tips, subscriptions, and donations from viewers. </p> </div> <h2 style="color: #9b59b6;">What would you like to stream?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">💬 Just Chatting</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Chat with your viewers and hang out.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🎮 Gaming Stream</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Stream yourself playing games.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🎨 Creative Stream</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Stream art, music, or other creative work.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Check for exhaustion and force end stream --> <<if setup.hasDebuff("exhaustion") && $streamingData.currentStream>> <<goto "StreamResults">> <</if>> <<if !$streamingData.currentStream>> <<run setup.startStream("asmr")>> <</if>> <<set _stream = $streamingData.currentStream>> <<set _canContinue = _stream.hoursStreamed < _stream.maxHours>> <div class="streaming-container"> <!-- Header --> <div class="stream-header"> <h1> <span class="live-indicator"></span> ASMR Stream - LIVE </h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Relaxing ASMR content for your viewers </p> </div> <!-- Stats Bar --> <div class="stream-stats-bar"> <div class="stat-card followers"> <div class="stat-icon">👥</div> <div class="stat-label">Followers</div> <div class="stat-value"><<= $streamingData.followers>></div> </div> <div class="stat-card viewers"> <div class="stat-icon">👁️</div> <div class="stat-label">Current Viewers</div> <div class="stat-value"><<= _stream.viewerData.current>></div> <div style="font-size: 12px; color: #aaa; margin-top: 5px;"> Peak: <<= _stream.viewerData.peak>> </div> </div> <div class="stat-card money"> <div class="stat-icon">💰</div> <div class="stat-label">Earnings</div> <div class="stat-value">$<<= _stream.incomeData.total>></div> </div> <div class="stat-card time"> <div class="stat-icon">⏱️</div> <div class="stat-label">Stream Time</div> <div class="stat-value"><<= _stream.hoursStreamed>> / <<= _stream.maxHours>> hrs</div> </div> </div> <!-- Show recent event if any --> <<if _stream.events.length > 0>> <<set _lastEvent = _stream.events[_stream.events.length - 1]>> <div class="event-notification"> <h3>🎉 <<= _lastEvent.event>></h3> <p><<= _lastEvent.description>></p> </div> <</if>> <!-- Trait Effects Display (Collapsible) --> <<if _stream.modifiers.traits.length > 0>> <<if !$hideTraitEffects>><<set $hideTraitEffects = false>><</if>> <div class="trait-effects"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h2 style="margin: 0;">✨ Active Trait Effects</h2> <<link "<<if $hideTraitEffects>>▼ Show<<else>>▲ Hide<</if>>">> <<set $hideTraitEffects = !$hideTraitEffects>> <<replace "#traitEffectsSection">> <<include "StreamTraitEffectsDisplay">> <</replace>> <</link>> </div> <span id="traitEffectsSection"> <<include "StreamTraitEffectsDisplay">> </span> </div> <</if>> <<if _canContinue>> <!-- Random special request (20% chance if 2+ hours streamed) --> <<if _stream.hoursStreamed >= 2 && Math.random() < 0.20 && !_stream.pendingRequest>> <<set _stream.pendingRequest = setup.streamSpecialRequests("asmr")>> <</if>> <<if _stream.pendingRequest>> <div class="special-request"> <h3>💵 Special Request!</h3> <p><<= _stream.pendingRequest.description>></p> <p style="color: white; font-weight: bold; margin-top: 10px;"> Payment: $<<= _stream.pendingRequest.payment>> </p> <div class="request-buttons"> <<link "<div class='request-button accept'>✓ Accept Request</div>">> <<set $money += _stream.pendingRequest.payment>> <<set _stream.incomeData.total += _stream.pendingRequest.payment>> <<set _stream.viewerData.current += _stream.pendingRequest.viewers>> <<run _stream.events.push({ event: "Special Request Completed", hour: _stream.hoursStreamed + 1, description: "You fulfilled a special viewer request for $" + _stream.pendingRequest.payment + "!" })>> <<set _stream.pendingRequest = null>> <<goto "StartASMRStream">> <</link>> <<link "<div class='request-button decline'>✗ Decline</div>">> <<set _stream.pendingRequest = null>> <<goto "StartASMRStream">> <</link>> </div> </div> <</if>> <<include "StreamTrendingDisplay">> <!-- Action Selection --> <div class="action-selection"> <h2>🎬 Choose Your Next Action (Hour <<= _stream.hoursStreamed + 1>>)</h2> <p style="color: #aaa; margin-bottom: 20px;"> Select what you want to do for the next hour of your stream. </p> <!-- Get trend info for this category --> <<set _trendInfo = (typeof setup.getTrendDisplay === "function") ? setup.getTrendDisplay("asmr") : { actions: {} }>> <div class="action-grid"> <<set _actions = setup.streamActions.asmr>> <<for _actionName, _actionData range _actions>> <<capture _actionName, _actionData>> <!-- Check if this action is trending --> <<set _isTrending = _trendInfo.actions && _trendInfo.actions[_actionName]>> <<set _trendBoost = _isTrending ? Math.round((_trendInfo.actions[_actionName].boost - 1) * 100) : 0>> <<set _cardBorder = _isTrending ? "#e94560" : "#9b59b6">> <<set _cardGlow = _isTrending ? "box-shadow: 0 0 15px rgba(233, 69, 96, 0.4);" : "">> <div class="action-card" style="border: 3px solid <<= _cardBorder>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: all 0.3s ease; position: relative; <<= _cardGlow>>"> <<if _isTrending>> <div style="position: absolute; top: -10px; right: 10px; background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: bold; color: white;"> 🔥 +<<= _trendBoost>>% </div> <</if>> <<link _actionName>> <<set $streamActionResult = setup.processStreamHour(_actionName)>> <<advancetime 60>> <<goto "StreamActionResult">> <</link>> <p style="color: #aaa; font-size: 14px; margin: 10px 0;"><<= _actionData.description>></p> <div style="display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px;"> <span>👁️</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">+<<print _actionData.baseViewerGain>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>💰</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">~$<<print _actionData.baseMoney>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>📊</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>"><<print _actionData.baseEngagement>>%<<if _isTrending>> ↑<</if>></span> </div> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <!-- Stream time limit reached --> <div style="text-align: center; padding: 40px;"> <h2 style="color: #e74c3c;"> ⏰ Stream Time Limit Reached </h2> <p style="color: #aaa; font-size: 16px; margin: 20px 0;"> You've reached your maximum stream time for today. <<if _stream.maxHours === 4>> (Limited to 4 hours due to having another job) <</if>> </p> </div> <</if>> <!-- Stream Controls --> <div style="text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px solid #333;"> <<if _stream.hoursStreamed >= 1>> <<link "<div class='stream-button end'>📴 End Stream</div>">> <<goto "StreamResults">> <</link>> <<else>> <p style="color: #888; font-style: italic;"> Must stream for at least 1 hour before ending </p> <</if>> <div style="margin-top: 15px;"> <<link "<div class='stream-button' style='background: #7f8c8d;'>← Back to Laptop</div>">> <<if _stream.hoursStreamed >= 1>> <<goto "StreamResults">> <<else>> <<set $streamingData.currentStream = null>> <<goto "UseLaptop">> <</if>> <</link>> </div> </div> </div> <</nobr>> <style> <<include "StreamingStyles">> </style>
<<nobr>> <<if setup.hasDebuff("exhaustion")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #ff6b6b;"> <div style="font-size: 64px; margin-bottom: 20px;">📺</div> <h2 style="color: #ff6b6b; margin: 0 0 15px 0;">Too Exhausted to Stream</h2> <p style="color: #aaa; margin: 0 0 20px 0;">You're too tired to focus on streaming. Get some sleep first!</p> <<link "<div style='background: #667eea; color: white; padding: 15px 30px; border-radius: 10px; font-weight: bold;'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <h1 style="color: white; text-align: center; margin: 0;">🔹 Choose Stream Category</h1> <p style="color: #ffd; text-align: center; margin: 10px 0 0 0;"> Select what type of content you want to stream </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- ASMR --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🎧 ASMR</h3> <p style="color: #aaa; font-size: 14px; line-height: 1.4; margin: 0 0 15px 0;"> Relaxing content with whispers, tapping, and soothing sounds. Perfect for viewers seeking calm. </p> <<link "<div style='background: #9b59b6; color: white; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: pointer;'>Start ASMR Stream</div>">> <<goto "StartASMRStream">> <</link>> </div> <!-- Styling & Makeup --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💄 Styling & Makeup</h3> <p style="color: #aaa; font-size: 14px; line-height: 1.4; margin: 0 0 15px 0;"> Beauty tutorials and styling tips. Perfect for makeup artists and beauty enthusiasts. </p> <<link "<div style='background: #e91e63; color: white; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: pointer;'>Start Beauty Stream</div>">> <<goto "StartStylingStream">> <</link>> </div> <!-- Gaming --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🎮 Gaming</h3> <p style="color: #aaa; font-size: 14px; line-height: 1.4; margin: 0 0 15px 0;"> Video game streams and playthroughs. Perfect for gamers and entertaining personalities. </p> <<link "<div style='background: #3498db; color: white; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: pointer;'>Start Gaming Stream</div>">> <<goto "StartGamingStream">> <</link>> </div> <!-- Music --> <div style="border: 3px solid #ff6347; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🎵 Music</h3> <p style="color: #aaa; font-size: 14px; line-height: 1.4; margin: 0 0 15px 0;"> Live musical performances. Perfect for musicians and singers. </p> <<link "<div style='background: #ff6347; color: white; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: pointer;'>Start Music Stream</div>">> <<goto "StartMusicStream">> <</link>> </div> <!-- Cooking --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🍳 Cooking</h3> <p style="color: #aaa; font-size: 14px; line-height: 1.4; margin: 0 0 15px 0;"> Culinary streams and recipe sharing. Perfect for chefs and food enthusiasts. </p> <<link "<div style='background: #f39c12; color: white; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold; cursor: pointer;'>Start Cooking Stream</div>">> <<goto "StartCookingStream">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set _stream = $streamingData.currentStream>> <<set _result = $streamActionResult>> <!-- Safety check - if no result, show error and return option --> <<if !_result>> <div class="streaming-container"> <div style="background: #3a2020; padding: 25px; border-radius: 12px; border: 3px solid #e74c3c; text-align: center;"> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">⚠️ Stream Error</h2> <p style="color: #aaa;">Something went wrong with this streaming hour.</p> <<link "<div class='stream-button'>← Return to Stream</div>">> <<if _stream && _stream.category === "asmr">> <<goto "StartASMRStream">> <<elseif _stream && _stream.category === "styling">> <<goto "StartStylingStream">> <<elseif _stream && _stream.category === "gaming">> <<goto "StartGamingStream">> <<elseif _stream && _stream.category === "music">> <<goto "StartMusicStream">> <<elseif _stream && _stream.category === "cooking">> <<goto "StartCookingStream">> <<else>> <<goto "BrowseInternet">> <</if>> <</link>> </div> </div> <<else>> <div class="streaming-container"> <!-- Trending Indicator --> <<if _result.wasTrending>> <div style="background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center; animation: pulse-trend 2s infinite;"> <span style="color: white; font-size: 18px; font-weight: bold;"> 🔥 TRENDING BONUS ACTIVE! +<<= Math.round((_result.trendBonus - 1) * 100)>>% boost </span> </div> <</if>> <!-- Result Summary --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(81, 207, 102, 0.3); margin-bottom: 25px;"> <h2 style="color: #51cf66; margin: 0 0 20px 0; text-align: center;"> 📊 Hour <<= _stream.hoursStreamed>> Complete! </h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #3498db; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">VIEWERS</div> <div style="font-size: 28px; font-weight: bold; color: #3498db;"><<= _result.viewers>></div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">ENGAGEMENT</div> <div style="font-size: 28px; font-weight: bold; color: #9b59b6;"><<= _result.engagement>>%</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #f39c12; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">EARNED</div> <div style="font-size: 28px; font-weight: bold; color: #f39c12;">$<<= _result.money>></div> </div> </div> <!-- Big Donation Alert --> <<if _result.donations && _result.donations.bigDonation>> <div style="margin-top: 20px; padding: 15px; background: linear-gradient(135deg, #ffd700 0%, #ff8c00 100%); border-radius: 8px; border: 2px solid #ffd700; text-align: center; animation: glow-donation 1.5s infinite;"> <div style="color: #1a1a1a; font-weight: bold; font-size: 20px;"> <<= _result.donations.bigDonation.message>> </div> <div style="color: #333; font-size: 24px; font-weight: bold; margin-top: 5px;"> +$<<= _result.donations.bigDonation.amount>> </div> </div> <</if>> <!-- Tip Rain Alert --> <<if _result.donations && _result.donations.tipRain && _result.donations.tipRain.occurred>> <div style="margin-top: 15px; padding: 15px; background: linear-gradient(135deg, #74b9ff 0%, #0984e3 100%); border-radius: 8px; border: 2px solid #74b9ff; text-align: center;"> <div style="color: white; font-weight: bold; font-size: 18px;"> <<= _result.donations.tipRain.message>> </div> <div style="color: #ffd; font-size: 16px; margin-top: 5px;"> +$<<= _result.donations.tipRain.total>> total </div> </div> <</if>> <!-- Donation Summary --> <<if _result.donations && _result.donations.count > 0>> <div style="margin-top: 15px; padding: 12px; background: #0a0a0a; border-radius: 8px; border: 1px solid #333; text-align: center;"> <span style="color: #aaa;"><<= _result.donations.count>> donation<<if _result.donations.count !== 1>>s<</if>></span> <span style="color: #f39c12; margin-left: 10px;">Total: $<<= _result.donations.total>></span> <span style="color: #888; margin-left: 10px;">(avg $<<= _result.donations.avgDonation>>)</span> </div> <<else>> <div style="margin-top: 15px; padding: 12px; background: #0a0a0a; border-radius: 8px; border: 1px solid #333; text-align: center;"> <span style="color: #666; font-style: italic;">No donations this hour</span> </div> <</if>> <!-- Random Event --> <<if _result.randomEvent>> <div style="margin-top: 20px; padding: 15px; background: #ffd43b; border-radius: 8px; border: 2px solid #f39c12;"> <div style="color: #1a1a1a; font-weight: bold; font-size: 16px; margin-bottom: 5px;"> 🎉 <<= _result.randomEvent.name>> </div> <div style="color: #2d2d2d; font-size: 14px;"> <<= _result.randomEvent.description>> </div> </div> <</if>> </div> <!-- Continue/End Options --> <div style="text-align: center;"> <<if _stream.hoursStreamed < _stream.maxHours>> <<if _stream.category === "asmr">> <<link "<div class='stream-button'>▶️ Continue Streaming</div>">> <<goto "StartASMRStream">> <</link>> <<elseif _stream.category === "styling">> <<link "<div class='stream-button'>▶️ Continue Streaming</div>">> <<goto "StartStylingStream">> <</link>> <<elseif _stream.category === "gaming">> <<link "<div class='stream-button'>▶️ Continue Streaming</div>">> <<goto "StartGamingStream">> <</link>> <<elseif _stream.category === "music">> <<link "<div class='stream-button'>▶️ Continue Streaming</div>">> <<goto "StartMusicStream">> <</link>> <<elseif _stream.category === "cooking">> <<link "<div class='stream-button'>▶️ Continue Streaming</div>">> <<goto "StartCookingStream">> <</link>> <</if>> <div style="margin-top: 15px;"> <<link "<div class='stream-button end'>📴 End Stream Now</div>">> <<goto "StreamResults">> <</link>> </div> <<else>> <p style="color: #e74c3c; font-size: 18px; margin-bottom: 20px;"> ⏰ Maximum stream time reached! </p> <<link "<div class='stream-button'>📊 View Final Results</div>">> <<goto "StreamResults">> <</link>> <</if>> </div> </div> <</if>> <</nobr>> <style> .streaming-container { background: #1a1a1a; min-height: 100vh; padding: 20px; color: #e0e0e0; } .stream-button { display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: pointer; transition: all 0.3s ease; } .stream-button:hover { transform: translateY(-2px); box-shadow: 0 5px 10px rgba(0,0,0,0.4); } .stream-button.end { background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); } @keyframes pulse-trend { 0%, 100% { box-shadow: 0 0 10px rgba(233, 69, 96, 0.5); } 50% { box-shadow: 0 0 20px rgba(233, 69, 96, 0.8); } } @keyframes glow-donation { 0%, 100% { box-shadow: 0 0 10px rgba(255, 215, 0, 0.5); } 50% { box-shadow: 0 0 25px rgba(255, 215, 0, 0.9); } } </style>
<<if !$streamingData>> <<set $streamingData = { followers: 0, totalStreams: 0, categoryUnlocked: { asmr: true, stylingMakeup: false, music: false, cooking: false, gaming: false }, streamHistory: [], currentStream: null }>> <</if>> <<if !$adultStreamingData>> <<set $adultStreamingData = { followers: 0, totalStreams: 0, streamHistory: [], currentStream: null }>> <</if>> <<if !$adultStreamingRegistered>> <<set $adultStreamingRegistered = false>> <</if>>
<<nobr>> <!-- SAVE CASH TO PREVENT ACCIDENTAL ADDITIONS --> <<set _savedMoney = $money>> <<set _stream = $streamingData.currentStream>> <!-- Safety: ensure followers exists --> <<if typeof $streamingData.followers !== "number">> <<set $streamingData.followers = 0>> <</if>> <<set _followersBefore = $streamingData.followers>> <<set _endResults = setup.endStream()>> <!-- MANUALLY APPLY FOLLOWERS if endStream didn't work --> <<if $streamingData.followers === _followersBefore && _endResults.newFollowers > 0>> <<set $streamingData.followers += _endResults.newFollowers>> <</if>> <!-- Apply Crowd's Eye multiplier (2x followers gained) --> <<if ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _bonusFollowers = _endResults.newFollowers>> <<set $streamingData.followers += _bonusFollowers>> <<set _stream.newFollowers = _endResults.newFollowers * 2>> <<else>> <<set _stream.newFollowers = _endResults.newFollowers>> <</if>> <!-- Pyrow +25% streaming followers on clear weather days --> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowFollowerBonus = Math.floor(_stream.newFollowers * 0.25)>> <<set $streamingData.followers += _pyrowFollowerBonus>> <<set _stream.newFollowers += _pyrowFollowerBonus>> <</if>> <!-- ===== SKILL TREE: Get streaming bonuses ===== --> <<set _streamingBonus = 0>> <<set _normalStreamBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _streamingBonus = setup.skillTree.getEffect("streamingBonus") || 0>> <<set _normalStreamBonus = setup.skillTree.getEffect("normalStreamBonus") || 0>> <</if>> <<set _totalStreamingBonus = _streamingBonus + _normalStreamBonus>> <!-- Calculate base net earnings --> <<set _baseNetEarnings = $streamingData.lastStream.netEarnings>> <!-- ===== SKILL TREE: Apply streaming bonuses ===== --> <<set _skillTreeBonus = 0>> <<if _totalStreamingBonus > 0>> <<set _skillTreeBonus = Math.round(_baseNetEarnings * (_totalStreamingBonus / 100))>> <<set _baseNetEarnings = _baseNetEarnings + _skillTreeBonus>> <<set $streamingData.lastStream.netEarnings = _baseNetEarnings>> <</if>> <!-- Pyrow +25% streaming earnings on clear weather days --> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowStreamBonus = Math.round(_baseNetEarnings * 0.25)>> <<set _baseNetEarnings += _pyrowStreamBonus>> <<set $streamingData.lastStream.netEarnings = _baseNetEarnings>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) - AFTER skill tree --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_baseNetEarnings * 0.5)>> <<set $streamingData.lastStream.netEarnings = _baseNetEarnings + _pearlBonus>> <<if _stream && _stream.incomeData>> <<set _stream.incomeData.total = _stream.incomeData.total + _skillTreeBonus + _pearlBonus>> <</if>> <</if>> <!-- Deposit to bank account (streaming revenue is digital - BANK ONLY, NO CASH) --> <<set $money = _savedMoney>> <<set _finalEarnings = Math.ceil($streamingData.lastStream.netEarnings)>> <<set $bankAccount.balance += _finalEarnings>> <!-- ========== ACHIEVEMENT TRACKING ========== --> <!-- Track total regular streaming hours --> <<if !$regularStreamTotalHours>> <<set $regularStreamTotalHours = 0>> <</if>> <<if _stream>> <<set $regularStreamTotalHours += _stream.hoursStreamed>> <</if>> <!-- Check for 8 hour regular stream achievement --> <<if _stream && _stream.hoursStreamed >= 8>> <<run setup.achievements.unlock("stream_8_hours")>> <</if>> <!-- Track regular streaming categories for Category Master achievement --> <<if !$regularCategoriesStreamed>> <<set $regularCategoriesStreamed = []>> <</if>> <<if _stream && _stream.category>> <<if !$regularCategoriesStreamed.includes(_stream.category)>> <<run $regularCategoriesStreamed.push(_stream.category)>> <</if>> <</if>> <!-- Check for Category Master achievement (all categories on both platforms) --> <!-- Regular categories: asmr, styling, gaming, music, cooking (5 total) --> <!-- PrawnHub actions: STRIP_CLOTHING, SIMULATE_SEX, BREASTS_CLAP, ASS_CLAP, MASSAGE_BREASTS, MASTURBATE, SIMULATE_ORAL, POSE_NUDE, MOAN (9 total) --> <<set _allRegularCategories = ["asmr", "styling", "gaming", "music", "cooking"]>> <<set _allPrawnhubActions = ["STRIP_CLOTHING", "SIMULATE_SEX", "BREASTS_CLAP", "ASS_CLAP", "MASSAGE_BREASTS", "MASTURBATE", "SIMULATE_ORAL", "POSE_NUDE", "MOAN"]>> <<set _hasAllRegular = true>> <<for _cat range _allRegularCategories>> <<if !$regularCategoriesStreamed || !$regularCategoriesStreamed.includes(_cat)>> <<set _hasAllRegular = false>> <<break>> <</if>> <</for>> <<set _hasAllPrawnhub = true>> <<for _action range _allPrawnhubActions>> <<if !$prawnhubActionsEverPerformed || !$prawnhubActionsEverPerformed.includes(_action)>> <<set _hasAllPrawnhub = false>> <<break>> <</if>> <</for>> <<if _hasAllRegular && _hasAllPrawnhub>> <<run setup.achievements.unlock("all_stream_categories")>> <</if>> <!-- Check for follower milestone achievements --> <<if $streamingData.followers >= 500>> <<run setup.achievements.unlock("regular_500_followers")>> <</if>> <<if $streamingData.followers >= 10000>> <<run setup.achievements.unlock("regular_10k_followers")>> <</if>> <!-- Track Streamer job for work_every_job achievement --> <!-- Only counts if player has Streamer job (0% platform cut = 100% earnings) --> <<if $streamingData.lastStream.platformCut === 0>> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Streamer")>> <<run $jobsWorked.push("Streamer")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <</if>> <!-- ========== END ACHIEVEMENT TRACKING ========== --> <div class="streaming-container"> <!-- Header --> <div class="stream-header"> <h1>📊 Stream Complete!</h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Great work! Here are your results. </p> </div> <!-- Big Donations Alert --> <<if _stream && _stream.incomeData && _stream.incomeData.bigDonations && _stream.incomeData.bigDonations.length > 0>> <div style="background: linear-gradient(135deg, #ffd700 0%, #ff8c00 100%); padding: 20px; border-radius: 12px; border: 3px solid #ffd700; box-shadow: 0 0 25px rgba(255, 215, 0, 0.5); margin-bottom: 25px; animation: glow-donation 2s infinite;"> <h2 style="color: #1a1a1a; margin: 0 0 15px 0; text-align: center;">💎 BIG DONATIONS THIS STREAM! 💎</h2> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<for _i = 0; _i < _stream.incomeData.bigDonations.length; _i++>> <<set _bigDono = _stream.incomeData.bigDonations[_i]>> <div style="background: rgba(0,0,0,0.2); padding: 12px 20px; border-radius: 8px; text-align: center;"> <div style="color: #1a1a1a; font-weight: bold; font-size: 14px;">Hour <<= _bigDono.hour>></div> <div style="color: #1a1a1a; font-size: 24px; font-weight: bold;">$<<= _bigDono.amount>></div> <<if _bigDono.type === "whale">> <div style="color: #4a0080; font-size: 12px; font-weight: bold;">🐋 WHALE</div> <</if>> </div> <</for>> </div> </div> <style> @keyframes glow-donation { 0%, 100% { box-shadow: 0 0 25px rgba(255, 215, 0, 0.5); } 50% { box-shadow: 0 0 40px rgba(255, 215, 0, 0.8); } } </style> <</if>> <!-- Trending Performance --> <<if _stream && _stream.trendingActionsUsed && _stream.trendingActionsUsed > 0>> <div style="background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 20px; border-radius: 12px; border: 3px solid #e94560; box-shadow: 0 0 20px rgba(233, 69, 96, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: white; margin: 0 0 10px 0;">🔥 You Rode the Trends!</h2> <p style="color: white; margin: 0; font-size: 18px;"> You performed <strong><<= _stream.trendingActionsUsed>></strong> trending action<<if _stream.trendingActionsUsed !== 1>>s<</if>> for bonus followers! </p> </div> <</if>> <!-- ===== STREAMING STUDIO: Display bonus notification ===== --> <<if $streamingData.lastStream && $streamingData.lastStream.studioBonus>> <div style="background: linear-gradient(135deg, #9146ff 0%, #7c3aed 100%); padding: 20px; border-radius: 12px; border: 3px solid #a78bfa; box-shadow: 0 0 20px rgba(145, 70, 255, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: #a78bfa; margin: 0 0 10px 0;">📺 Streaming Studio Bonus Active 📺</h2> <p style="color: #ddd6fe; margin: 0; font-size: 16px;"> +15% to all stream results (viewers, engagement, earnings, followers) </p> </div> <</if>> <<if setup.hasCrowdsEye()>> <div style="background: linear-gradient(135deg, #9d4edd 0%, #6a00b3 100%); padding: 20px; border-radius: 12px; border: 3px solid #b388ff; box-shadow: 0 0 20px rgba(157, 78, 221, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: #b388ff; margin: 0 0 10px 0;">👁️ The Crowd's Eye 👁️</h2> <p style="color: #e0c3fc; margin: 0; font-size: 16px;">Doubled your streaming income this stream!</p> </div> <</if>> <!-- ===== SKILL TREE: Display bonus notification ===== --> <<if _totalStreamingBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 20px; border-radius: 12px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: #CE93D8; margin: 0 0 10px 0;">⭐ Skill Tree Bonuses Active ⭐</h2> <p style="color: #E1BEE7; margin: 0; font-size: 16px;"> <<if _streamingBonus > 0>> Streaming Bonus: +<<print _streamingBonus>>% <</if>> <<if _streamingBonus > 0 && _normalStreamBonus > 0>> | <</if>> <<if _normalStreamBonus > 0>> Regular Stream Bonus: +<<print _normalStreamBonus>>% <</if>> </p> <p style="color: #CE93D8; margin: 10px 0 0 0; font-size: 18px; font-weight: bold;"> Extra Earnings: +$<<print _skillTreeBonus>> </p> </div> <</if>> <!-- Overall Summary --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #f39c12; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(243, 156, 18, 0.3); margin-bottom: 25px;"> <h2 style="color: #f39c12; margin: 0 0 20px 0;">📈 Stream Summary</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #3498db;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 5px;">Hours Streamed</div> <div style="color: white; font-size: 20px; font-weight: bold;"><<= _stream ? _stream.hoursStreamed : 0>></div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #e74c3c;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 5px;">New Followers</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">+<<= _stream ? _stream.newFollowers : _endResults.newFollowers>></div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #f39c12;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 5px;">Total Earnings</div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;">$<<= _finalEarnings>></div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #9b59b6;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 5px;">Avg Engagement</div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<= _stream && _stream.engagementData ? _stream.engagementData.average : 0>>%</div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #3498db;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 5px;">Peak Viewers</div> <div style="color: white; font-size: 20px; font-weight: bold;"><<= _stream && _stream.viewerData ? _stream.viewerData.peak : 0>></div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #e74c3c;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 5px;">Total Followers</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;"><<= $streamingData.followers>></div> </div> </div> </div> <!-- Job Update Messages --> <<if _endResults.becameStreamer>> <div style="background: linear-gradient(135deg, #27ae60 0%, #229954 100%); padding: 25px; border-radius: 12px; border: 3px solid #27ae60; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(39, 174, 96, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: white; margin: 0 0 15px 0;">🎉 Congratulations!</h2> <p style="color: #ffd; font-size: 18px; margin: 0;"> You've reached 500 followers! Your job is now <strong>Streamer</strong>!<br> You can now stream for up to 8 hours per day and keep 100% of your earnings! </p> </div> <<elseif _endResults.hasOtherJob && $streamingData.followers >= 500>> <div style="background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); padding: 25px; border-radius: 12px; border: 3px solid #f39c12; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: white; margin: 0 0 15px 0;">💼 Job Opportunity</h2> <p style="color: #ffd; font-size: 16px; margin: 0 0 15px 0;"> You've reached 500 followers! Would you like to quit your current job and become a full-time Streamer? </p> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='display: inline-block; background: #27ae60; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>✓ Become Streamer (8 hrs/day, 100% earnings)</div>">> <<set $jobs = ["Streamer"]>> <<goto "UseLaptop">> <</link>> <<link "<div style='display: inline-block; background: #7f8c8d; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>✗ Keep Current Job (4 hrs/day, 45% earnings)</div>">> <<goto "UseLaptop">> <</link>> </div> </div> <</if>> <!-- Milestone Progress (for under 500 followers) --> <<if $streamingData.followers < 500>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #667eea; margin-bottom: 25px;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">🎯 Progress to Streamer Status</h3> <<set _progress = Math.round(($streamingData.followers / 500) * 100)>> <div style="background: #0a0a0a; border-radius: 10px; height: 30px; overflow: hidden; border: 2px solid #333;"> <div style="background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); height: 100%; width: <<= _progress>>%; transition: width 0.5s;"></div> </div> <p style="color: #aaa; text-align: center; margin: 10px 0 0 0;"> <<= $streamingData.followers>> / 500 followers (<<= _progress>>%) </p> <p style="color: #888; text-align: center; margin: 5px 0 0 0; font-size: 14px;"> Reach 500 followers to unlock: Full earnings, special requests, big donations, and tip rain! </p> </div> <</if>> <!-- Crowd's Eye Notification --> <<if ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: linear-gradient(135deg, #a78bfa 0%, #7c3aed 100%); padding: 20px; border-radius: 12px; border: 3px solid #a78bfa; box-shadow: 0 0 20px rgba(167, 139, 250, 0.4); margin-bottom: 25px; text-align: center; animation: pulse-eye 2s infinite;"> <h2 style="color: white; margin: 0 0 10px 0;">👁️ The Crowd's Eye 👁️</h2> <p style="color: white; margin: 0; font-size: 16px; font-weight: bold;"> Your magnetic presence has doubled your follower gains! </p> </div> <style> @keyframes pulse-eye { 0%, 100% { box-shadow: 0 0 20px rgba(167, 139, 250, 0.4); } 50% { box-shadow: 0 0 30px rgba(167, 139, 250, 0.7); } } </style> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 20px; border-radius: 12px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); margin-bottom: 25px; text-align: center; animation: pulse-pearl 2s infinite;"> <h2 style="color: white; margin: 0 0 10px 0;">🐚 The Pearl of Abundance 🐚</h2> <p style="color: white; margin: 0; font-size: 16px; font-weight: bold;"> Your streaming earnings have been increased by 50%! </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Hourly Breakdown --> <<if _stream && _stream.actions && _stream.actions.length > 0>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #4dabf7; margin: 0 0 15px 0;">⏱️ Hourly Breakdown</h2> <<for _i = 0; _i < _stream.actions.length; _i++>> <<set _action = _stream.actions[_i]>> <<set _trendBorder = _action.wasTrending ? "border-left: 4px solid #e94560;" : "">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 10px; border: 2px solid #333; <<= _trendBorder>>"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;"> <div> <strong style="color: #4dabf7;">Hour <<= _action.hour>>:</strong> <span style="color: #aaa; margin-left: 10px;"><<= _action.action>></span> <<if _action.wasTrending>> <span style="background: #e94560; color: white; padding: 2px 8px; border-radius: 10px; font-size: 11px; margin-left: 8px;">🔥 TRENDING</span> <</if>> </div> <div style="display: flex; gap: 15px; font-size: 14px;"> <span style="color: #3498db;">👁️ <<= _action.viewers>></span> <span style="color: #9b59b6;">📊 <<= _action.engagement>>%</span> <span style="color: #f39c12;">💰 $<<= _action.money>></span> </div> </div> </div> <</for>> </div> <</if>> <!-- Earnings Breakdown --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #f39c12;"> <h3 style="color: #f39c12; margin: 0 0 15px 0;">💰 Earnings Breakdown</h3> <div style="color: #aaa; line-height: 1.8;"> <p style="margin: 5px 0;"><strong>Gross Earnings:</strong> <span style="color: #51cf66;">$<<= $streamingData.lastStream.grossEarnings>></span></p> <<if $streamingData.lastStream.platformCut > 0>> <<set _platformPercent = Math.round(($streamingData.lastStream.platformCut / Math.max(1, $streamingData.lastStream.grossEarnings)) * 100)>> <p style="margin: 5px 0;"><strong>Platform Cut (<<= _platformPercent>>%):</strong> <span style="color: #e74c3c;">-$<<= $streamingData.lastStream.platformCut>></span></p> <<else>> <p style="margin: 5px 0;"><strong>Platform Cut:</strong> <span style="color: #51cf66;">$0 (Streamer Perk!)</span></p> <</if>> <!-- ===== SKILL TREE: Show bonus in breakdown ===== --> <<if _skillTreeBonus > 0>> <p style="margin: 5px 0;"><strong>Skill Tree Bonus (+<<print _totalStreamingBonus>>%):</strong> <span style="color: #CE93D8;">+$<<= _skillTreeBonus>></span></p> <</if>> <<if _pearlActive>> <p style="margin: 5px 0;"><strong>Pearl Bonus (+50%):</strong> <span style="color: #7dd3fc;">+$<<= _pearlBonus>></span></p> <</if>> <p style="margin: 5px 0; padding-top: 10px; border-top: 2px solid #444;"><strong>Net Earnings:</strong> <span style="color: #ffd43b; font-size: 18px;">$<<= _finalEarnings>></span> <<if _pearlActive || _skillTreeBonus > 0>> <span style="color: <<if _pearlActive>>#7dd3fc<<else>>#CE93D8<</if>>; font-size: 14px;"> ✨</span> <</if>> </p> </div> <!-- Bank Deposit Notice --> <div style="background: #2a2a4a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #667eea;"> <p style="color: #667eea; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> 💳 All earnings deposited directly to your bank account </p> </div> <<if !$jobs || !$jobs.includes("Streamer")>> <div style="background: #3a2020; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #e74c3c;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px;"> ⚠️ <strong>High Platform Fee!</strong> Get the Streamer job (500 followers) to keep 100% of your earnings instead of 45%. </p> </div> <</if>> </div> <!-- Current Balance Display --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #667eea;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">💼 Account Summary</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Cash on Hand:</p> <p style="color: #51cf66; margin: 0; font-size: 20px; font-weight: bold;"><<print setup.formatMoney ? setup.formatMoney($money) : "$" + $money>></p> </div> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Bank Balance:</p> <p style="color: #667eea; margin: 0; font-size: 20px; font-weight: bold;"><<print setup.formatMoney ? setup.formatMoney($bankAccount.balance) : "$" + $bankAccount.balance>></p> </div> </div> <div style="text-align: center; margin-top: 10px; padding-top: 10px; border-top: 1px solid #666;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Total Funds:</p> <p style="color: #ffd43b; margin: 0; font-size: 24px; font-weight: bold;"><<print setup.formatMoney ? setup.formatMoney($money + $bankAccount.balance) : "$" + ($money + $bankAccount.balance)>></p> </div> </div> <!-- Notable Events --> <<if _stream && _stream.events && _stream.events.length > 0>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #ffd43b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #ffd43b; margin: 0 0 15px 0;">🎬 Notable Events</h2> <div style="display: flex; flex-direction: column; gap: 12px;"> <<for _i = 0; _i < _stream.events.length; _i++>> <<set _event = _stream.events[_i]>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ffd43b;"> <div style="color: white; font-weight: bold; margin-bottom: 5px;"> Hour <<= _event.hour>>: <<= _event.event>> </div> <div style="color: #aaa; font-size: 14px;"> <<= _event.description>> </div> </div> <</for>> </div> </div> <</if>> <!-- Return Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div class='stream-button'>← Return to Internet</div>">> <<set $streamingData.currentStream = null>> <<goto "BrowseInternet">> <</link>> </div> </div> <</nobr>> <style> .streaming-container { background: #1a1a1a; min-height: 100vh; padding: 20px; color: #e0e0e0; } .stream-header { padding: 25px; background: linear-gradient(135deg, #9b59b6 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 0 30px rgba(155, 89, 182, 0.4); text-align: center; } .stream-header h1 { color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5); font-size: 32px; } .stream-button { display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 30px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); cursor: pointer; transition: all 0.3s ease; } .stream-button:hover { transform: translateY(-2px); box-shadow: 0 5px 10px rgba(0,0,0,0.4); } </style>
<<nobr>> <<set $lastLocation = "BrowseInternet">> <!-- Initialize streaming data if needed --> <<if !$streamingData>> <<set $streamingData = { followers: 0, totalStreams: 0, streamHistory: [] }>> <</if>> <<if typeof $streamingData.totalStreams === "undefined">> <<set $streamingData.totalStreams = 0>> <</if>> <<if !$streamingData.streamHistory>> <<set $streamingData.streamHistory = []>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 25px; background: linear-gradient(135deg, #27ae60 0%, #229954 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #27ae60; box-shadow: 0 0 30px rgba(39, 174, 96, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">📊 Stream Analytics Dashboard</h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Track your streaming performance and growth </p> </div> <!-- Overall Stats --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #27ae60; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #27ae60; margin: 0 0 20px 0;">🎯 Channel Overview</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #e74c3c; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL FOLLOWERS</div> <div style="font-size: 32px; font-weight: bold; color: #e74c3c;"><<= $streamingData.followers || 0>></div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #3498db; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL STREAMS</div> <div style="font-size: 32px; font-weight: bold; color: #3498db;"><<= $streamingData.totalStreams || 0>></div> </div> <<if $streamingData.streamHistory && $streamingData.streamHistory.length > 0>> <<set _totalHours = 0>> <<set _totalIncome = 0>> <<for _i = 0; _i < $streamingData.streamHistory.length; _i++>> <<set _totalHours += $streamingData.streamHistory[_i].hours || 0>> <<set _totalIncome += $streamingData.streamHistory[_i].income || 0>> <</for>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">HOURS STREAMED</div> <div style="font-size: 32px; font-weight: bold; color: #9b59b6;"><<= _totalHours>></div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #f39c12; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL EARNINGS</div> <div style="font-size: 32px; font-weight: bold; color: #f39c12;">$<<= _totalIncome>></div> </div> <<else>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">HOURS STREAMED</div> <div style="font-size: 32px; font-weight: bold; color: #9b59b6;">0</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #f39c12; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL EARNINGS</div> <div style="font-size: 32px; font-weight: bold; color: #f39c12;">$0</div> </div> <</if>> </div> </div> <!-- Milestone Progress (for under 500 followers) --> <<if $streamingData.followers < 500>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #667eea; margin-bottom: 25px;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">🎯 Progress to Streamer Status</h3> <<set _progress = Math.round(($streamingData.followers / 500) * 100)>> <div style="background: #0a0a0a; border-radius: 10px; height: 30px; overflow: hidden; border: 2px solid #333;"> <div style="background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); height: 100%; width: <<= _progress>>%; transition: width 0.5s;"></div> </div> <p style="color: #aaa; text-align: center; margin: 10px 0 0 0;"> <<= $streamingData.followers>> / 500 followers (<<= _progress>>%) </p> <p style="color: #888; text-align: center; margin: 5px 0 0 0; font-size: 14px;"> Reach 500 followers to unlock: Full earnings (100%), special requests, big donations, and tip rain! </p> </div> <</if>> <!-- Stream History --> <<if $streamingData.streamHistory && $streamingData.streamHistory.length > 0>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #4dabf7; margin: 0 0 20px 0;">📅 Recent Stream History (Last 7)</h2> <<set _historyLength = $streamingData.streamHistory.length>> <<set _displayCount = Math.min(7, _historyLength)>> <<for _i = 0; _i < _displayCount; _i++>> <<set _stream = $streamingData.streamHistory[_i]>> <<if _stream>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #333;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; flex-wrap: wrap; gap: 10px;"> <div> <strong style="color: #4dabf7; font-size: 18px;"><<= _stream.date || "Unknown">></strong> <span style="color: #aaa; margin-left: 15px;"><<= _stream.category ? _stream.category.toUpperCase() : "STREAM">></span> </div> <div style="color: #aaa;"><<= _stream.hours || 0>> hour<<if _stream.hours !== 1>>s<</if>></div> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 15px;"> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">NEW FOLLOWERS</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">+<<= _stream.newFollowers || 0>></div> </div> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">PEAK VIEWERS</div> <<if _stream.viewers && typeof _stream.viewers === "object">> <div style="color: #3498db; font-size: 20px; font-weight: bold;"><<= _stream.viewers.peak || 0>></div> <<elseif typeof _stream.viewers === "number">> <div style="color: #3498db; font-size: 20px; font-weight: bold;"><<= _stream.viewers>></div> <<else>> <div style="color: #3498db; font-size: 20px; font-weight: bold;">0</div> <</if>> </div> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">AVG ENGAGEMENT</div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<= _stream.engagement || 0>>%</div> </div> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">EARNED</div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;">$<<= _stream.income || 0>></div> </div> </div> </div> <</if>> <</for>> </div> <!-- Last 7 Streams Statistics --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #e74c3c; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #e74c3c; margin: 0 0 20px 0;">📈 Recent Performance Summary</h2> <<set _historyLength = $streamingData.streamHistory.length>> <<set _statsCount = Math.min(7, _historyLength)>> <<set _last7TotalFollowers = 0>> <<set _last7TotalIncome = 0>> <<set _last7TotalHours = 0>> <<set _last7TotalViewers = 0>> <<set _last7TotalEngagement = 0>> <<for _j = 0; _j < _statsCount; _j++>> <<set _histStream = $streamingData.streamHistory[_j]>> <<if _histStream>> <<set _last7TotalFollowers += _histStream.newFollowers || 0>> <<set _last7TotalIncome += _histStream.income || 0>> <<set _last7TotalHours += _histStream.hours || 0>> <<if _histStream.viewers && typeof _histStream.viewers === "object">> <<set _last7TotalViewers += _histStream.viewers.peak || 0>> <<elseif typeof _histStream.viewers === "number">> <<set _last7TotalViewers += _histStream.viewers>> <</if>> <<set _last7TotalEngagement += _histStream.engagement || 0>> <</if>> <</for>> <<set _avgViewers = _statsCount > 0 ? Math.round(_last7TotalViewers / _statsCount) : 0>> <<set _avgEngagement = _statsCount > 0 ? Math.round(_last7TotalEngagement / _statsCount) : 0>> <<set _avgIncomePerStream = _statsCount > 0 ? Math.round(_last7TotalIncome / _statsCount) : 0>> <<set _avgFollowersPerStream = _statsCount > 0 ? Math.round(_last7TotalFollowers / _statsCount) : 0>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #e74c3c; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL NEW FOLLOWERS</div> <div style="font-size: 28px; font-weight: bold; color: #e74c3c;">+<<= _last7TotalFollowers>></div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Avg: <<= _avgFollowersPerStream>> per stream</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #f39c12; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL EARNINGS</div> <div style="font-size: 28px; font-weight: bold; color: #f39c12;">$<<= _last7TotalIncome>></div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Avg: $<<= _avgIncomePerStream>> per stream</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #3498db; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">AVG PEAK VIEWERS</div> <div style="font-size: 28px; font-weight: bold; color: #3498db;"><<= _avgViewers>></div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Across <<= _statsCount>> streams</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">AVG ENGAGEMENT</div> <div style="font-size: 28px; font-weight: bold; color: #9b59b6;"><<= _avgEngagement>>%</div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Across <<= _statsCount>> streams</div> </div> </div> </div> <<else>> <!-- No Stream History --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 40px; border-radius: 12px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4); text-align: center; margin-bottom: 25px;"> <div style="font-size: 48px; margin-bottom: 20px;">📊</div> <h2 style="color: #aaa; margin: 0 0 15px 0;">No Stream Data Yet</h2> <p style="color: #888; font-size: 16px; margin: 0;"> Start streaming to see your analytics and performance metrics here! </p> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Check for exhaustion and force end stream --> <<if setup.hasDebuff("exhaustion") && $streamingData.currentStream>> <<goto "StreamResults">> <</if>> <!-- Check if player has Makeup skill --> <<if !$skills.includes("Makeup")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="padding: 25px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e74c3c; box-shadow: 0 0 30px rgba(231, 76, 60, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5); font-size: 32px;"> 🚫 Skill Required </h1> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; border: 2px solid #e74c3c; text-align: center;"> <p style="color: #aaa; font-size: 18px; line-height: 1.6; margin: 0 0 25px 0;"> You need the <strong style="color: #e91e63;">Makeup</strong> skill to stream Styling & Makeup content. </p> <p style="color: #888; font-size: 16px; margin: 0 0 25px 0;"> Without professional makeup skills, you won't be able to create quality beauty tutorials. </p> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Categories</div>">> <<goto "SelectStreamCategory">> <</link>> </div> </div> <<else>> <<if !$streamingData.currentStream>> <<run setup.startStream("styling")>> <</if>> <<set _stream = $streamingData.currentStream>> <<set _canContinue = _stream.hoursStreamed < _stream.maxHours>> <div class="streaming-container"> <!-- Header --> <div style="padding: 25px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 0 30px rgba(233, 30, 99, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5); font-size: 32px;"> <span class="live-indicator"></span> Styling & Makeup Stream - LIVE </h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Beauty tutorials and styling tips for your viewers </p> </div> <!-- Stats Bar --> <div class="stream-stats-bar"> <div class="stat-card followers"> <div class="stat-icon">👥</div> <div class="stat-label">Followers</div> <div class="stat-value"><<= $streamingData.followers>></div> </div> <div class="stat-card viewers"> <div class="stat-icon">👁️</div> <div class="stat-label">Current Viewers</div> <div class="stat-value"><<= _stream.viewerData.current>></div> <div style="font-size: 12px; color: #aaa; margin-top: 5px;"> Peak: <<= _stream.viewerData.peak>> </div> </div> <div class="stat-card money"> <div class="stat-icon">💰</div> <div class="stat-label">Earnings</div> <div class="stat-value">$<<= _stream.incomeData.total>></div> </div> <div class="stat-card time"> <div class="stat-icon">⏱️</div> <div class="stat-label">Stream Time</div> <div class="stat-value"><<= _stream.hoursStreamed>> / <<= _stream.maxHours>> hrs</div> </div> </div> <!-- Show recent event if any --> <<if _stream.events.length > 0>> <<set _lastEvent = _stream.events[_stream.events.length - 1]>> <div class="event-notification"> <h3>🎉 <<= _lastEvent.event>></h3> <p><<= _lastEvent.description>></p> </div> <</if>> <!-- Trait Effects Display (Collapsible) --> <<if _stream.modifiers.traits.length > 0>> <<if !$hideTraitEffects>><<set $hideTraitEffects = false>><</if>> <div class="trait-effects"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h2 style="margin: 0;">✨ Active Trait Effects</h2> <<link "<<if $hideTraitEffects>>▼ Show<<else>>▲ Hide<</if>>">> <<set $hideTraitEffects = !$hideTraitEffects>> <<replace "#traitEffectsSection">> <<include "StreamTraitEffectsDisplay">> <</replace>> <</link>> </div> <span id="traitEffectsSection"> <<include "StreamTraitEffectsDisplay">> </span> </div> <</if>> <<if _canContinue>> <!-- Random special request (20% chance if 2+ hours streamed) --> <<if _stream.hoursStreamed >= 2 && Math.random() < 0.20 && !_stream.pendingRequest>> <<set _stream.pendingRequest = setup.streamSpecialRequests("styling")>> <</if>> <<if _stream.pendingRequest>> <div class="special-request"> <h3>💵 Special Request!</h3> <p><<= _stream.pendingRequest.description>></p> <p style="color: white; font-weight: bold; margin-top: 10px;"> Payment: $<<= _stream.pendingRequest.payment>> </p> <div class="request-buttons"> <<link "<div class='request-button accept'>✓ Accept Request</div>">> <<set $money += _stream.pendingRequest.payment>> <<set _stream.incomeData.total += _stream.pendingRequest.payment>> <<set _stream.viewerData.current += _stream.pendingRequest.viewers>> <<run _stream.events.push({ event: "Special Request Completed", hour: _stream.hoursStreamed + 1, description: "You fulfilled a special viewer request for $" + _stream.pendingRequest.payment + "!" })>> <<set _stream.pendingRequest = null>> <<goto "StartStylingStream">> <</link>> <<link "<div class='request-button decline'>✗ Decline</div>">> <<set _stream.pendingRequest = null>> <<goto "StartStylingStream">> <</link>> </div> </div> <</if>> <<include "StreamTrendingDisplay">> <!-- Action Selection --> <div class="action-selection"> <h2>🎬 Choose Your Next Action (Hour <<= _stream.hoursStreamed + 1>>)</h2> <p style="color: #aaa; margin-bottom: 20px;"> Select what you want to do for the next hour of your stream. </p> <<set _trendInfo = (typeof setup.getTrendDisplay === "function") ? setup.getTrendDisplay("styling") : { actions: {} }>> <div class="action-grid"> <<set _actions = setup.streamActions.styling>> <<for _actionName, _actionData range _actions>> <<capture _actionName, _actionData>> <<set _isTrending = _trendInfo.actions && _trendInfo.actions[_actionName]>> <<set _trendBoost = _isTrending ? Math.round((_trendInfo.actions[_actionName].boost - 1) * 100) : 0>> <<set _cardBorder = _isTrending ? "#e94560" : "#e91e63">> <<set _cardGlow = _isTrending ? "box-shadow: 0 0 15px rgba(233, 69, 96, 0.4);" : "">> <div class="action-card" style="border: 3px solid <<= _cardBorder>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: all 0.3s ease; position: relative; <<= _cardGlow>>"> <<if _isTrending>> <div style="position: absolute; top: -10px; right: 10px; background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: bold; color: white;"> 🔥 +<<= _trendBoost>>% </div> <</if>> <<link _actionName>> <<set $streamActionResult = setup.processStreamHour(_actionName)>> <<advancetime 60>> <<goto "StreamActionResult">> <</link>> <p style="color: #aaa; font-size: 14px; margin: 10px 0;"><<print _actionData.description>></p> <div style="display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px;"> <span>👁️</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">+<<print _actionData.baseViewerGain>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>💰</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">~$<<print _actionData.baseMoney>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>📊</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>"><<print _actionData.baseEngagement>>%<<if _isTrending>> ↑<</if>></span> </div> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <!-- Stream time limit reached --> <div style="text-align: center; padding: 40px;"> <h2 style="color: #e74c3c;"> ⏰ Stream Time Limit Reached </h2> <p style="color: #aaa; font-size: 16px; margin: 20px 0;"> You've reached your maximum stream time for today. <<if _stream.maxHours === 4>> (Limited to 4 hours due to having another job) <</if>> </p> </div> <</if>> <!-- Stream Controls --> <div style="text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px solid #333;"> <<if _stream.hoursStreamed >= 1>> <<link "<div class='stream-button end'>📴 End Stream</div>">> <<goto "StreamResults">> <</link>> <<else>> <p style="color: #888; font-style: italic;"> Must stream for at least 1 hour before ending </p> <</if>> <div style="margin-top: 15px;"> <<link "<div class='stream-button' style='background: #7f8c8d;'>← Back to Laptop</div>">> <<if _stream.hoursStreamed >= 1>> <<goto "StreamResults">> <<else>> <<set $streamingData.currentStream = null>> <<goto "UseLaptop">> <</if>> <</link>> </div> </div> </div> <</if>> <</nobr>> <style> <<include "StreamingStyles">> </style>
<<nobr>> <!-- Check for exhaustion and force end stream --> <<if setup.hasDebuff("exhaustion") && $streamingData.currentStream>> <<goto "StreamResults">> <</if>> <<if !$streamingData.currentStream>> <<run setup.startStream("gaming")>> <</if>> <<set _stream = $streamingData.currentStream>> <<set _canContinue = _stream.hoursStreamed < _stream.maxHours>> <div class="streaming-container"> <!-- Header --> <div style="padding: 25px; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #3498db; box-shadow: 0 0 30px rgba(52, 152, 219, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5); font-size: 32px;"> <span class="live-indicator"></span> Gaming Stream - LIVE </h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Epic gameplay and entertainment for your viewers </p> </div> <!-- Stats Bar --> <div class="stream-stats-bar"> <div class="stat-card followers"> <div class="stat-icon">👥</div> <div class="stat-label">Followers</div> <div class="stat-value"><<= $streamingData.followers>></div> </div> <div class="stat-card viewers"> <div class="stat-icon">👁️</div> <div class="stat-label">Current Viewers</div> <div class="stat-value"><<= _stream.viewerData.current>></div> <div style="font-size: 12px; color: #aaa; margin-top: 5px;"> Peak: <<= _stream.viewerData.peak>> </div> </div> <div class="stat-card money"> <div class="stat-icon">💰</div> <div class="stat-label">Earnings</div> <div class="stat-value">$<<= _stream.incomeData.total>></div> </div> <div class="stat-card time"> <div class="stat-icon">⏱️</div> <div class="stat-label">Stream Time</div> <div class="stat-value"><<= _stream.hoursStreamed>> / <<= _stream.maxHours>> hrs</div> </div> </div> <!-- Show recent event if any --> <<if _stream.events.length > 0>> <<set _lastEvent = _stream.events[_stream.events.length - 1]>> <div class="event-notification"> <h3>🎉 <<= _lastEvent.event>></h3> <p><<= _lastEvent.description>></p> </div> <</if>> <!-- Trait Effects Display (Collapsible) --> <<if _stream.modifiers.traits.length > 0>> <<if !$hideTraitEffects>><<set $hideTraitEffects = false>><</if>> <div class="trait-effects"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h2 style="margin: 0;">✨ Active Trait Effects</h2> <<link "<<if $hideTraitEffects>>▼ Show<<else>>▲ Hide<</if>>">> <<set $hideTraitEffects = !$hideTraitEffects>> <<replace "#traitEffectsSection">> <<include "StreamTraitEffectsDisplay">> <</replace>> <</link>> </div> <span id="traitEffectsSection"> <<include "StreamTraitEffectsDisplay">> </span> </div> <</if>> <<if _canContinue>> <!-- Random special request (20% chance if 2+ hours streamed) --> <<if _stream.hoursStreamed >= 2 && Math.random() < 0.20 && !_stream.pendingRequest>> <<set _stream.pendingRequest = setup.streamSpecialRequests("gaming")>> <</if>> <<if _stream.pendingRequest>> <div class="special-request"> <h3>💵 Special Request!</h3> <p><<= _stream.pendingRequest.description>></p> <p style="color: white; font-weight: bold; margin-top: 10px;"> Payment: $<<= _stream.pendingRequest.payment>> </p> <div class="request-buttons"> <<link "<div class='request-button accept'>✓ Accept Request</div>">> <<set $money += _stream.pendingRequest.payment>> <<set _stream.incomeData.total += _stream.pendingRequest.payment>> <<set _stream.viewerData.current += _stream.pendingRequest.viewers>> <<run _stream.events.push({ event: "Special Request Completed", hour: _stream.hoursStreamed + 1, description: "You fulfilled a special viewer request for $" + _stream.pendingRequest.payment + "!" })>> <<set _stream.pendingRequest = null>> <<goto "StartGamingStream">> <</link>> <<link "<div class='request-button decline'>✗ Decline</div>">> <<set _stream.pendingRequest = null>> <<goto "StartGamingStream">> <</link>> </div> </div> <</if>> <<include "StreamTrendingDisplay">> <!-- Action Selection --> <div class="action-selection"> <h2>🎬 Choose Your Next Action (Hour <<= _stream.hoursStreamed + 1>>)</h2> <p style="color: #aaa; margin-bottom: 20px;"> Select what you want to do for the next hour of your stream. </p> <<set _trendInfo = (typeof setup.getTrendDisplay === "function") ? setup.getTrendDisplay("gaming") : { actions: {} }>> <div class="action-grid"> <<set _actions = setup.streamActions.gaming>> <<for _actionName, _actionData range _actions>> <<capture _actionName, _actionData>> <<set _isTrending = _trendInfo.actions && _trendInfo.actions[_actionName]>> <<set _trendBoost = _isTrending ? Math.round((_trendInfo.actions[_actionName].boost - 1) * 100) : 0>> <<set _cardBorder = _isTrending ? "#e94560" : "#3498db">> <<set _cardGlow = _isTrending ? "box-shadow: 0 0 15px rgba(233, 69, 96, 0.4);" : "">> <div class="action-card" style="border: 3px solid <<= _cardBorder>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: all 0.3s ease; position: relative; <<= _cardGlow>>"> <<if _isTrending>> <div style="position: absolute; top: -10px; right: 10px; background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: bold; color: white;"> 🔥 +<<= _trendBoost>>% </div> <</if>> <<link _actionName>> <<set $streamActionResult = setup.processStreamHour(_actionName)>> <<advancetime 60>> <<goto "StreamActionResult">> <</link>> <p style="color: #aaa; font-size: 14px; margin: 10px 0;"><<print _actionData.description>></p> <div style="display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px;"> <span>👁️</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">+<<print _actionData.baseViewerGain>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>💰</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">~$<<print _actionData.baseMoney>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>📊</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>"><<print _actionData.baseEngagement>>%<<if _isTrending>> ↑<</if>></span> </div> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <!-- Stream time limit reached --> <div style="text-align: center; padding: 40px;"> <h2 style="color: #e74c3c;"> ⏰ Stream Time Limit Reached </h2> <p style="color: #aaa; font-size: 16px; margin: 20px 0;"> You've reached your maximum stream time for today. <<if _stream.maxHours === 4>> (Limited to 4 hours due to having another job) <</if>> </p> </div> <</if>> <!-- Stream Controls --> <div style="text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px solid #333;"> <<if _stream.hoursStreamed >= 1>> <<link "<div class='stream-button end'>📴 End Stream</div>">> <<goto "StreamResults">> <</link>> <<else>> <p style="color: #888; font-style: italic;"> Must stream for at least 1 hour before ending </p> <</if>> <div style="margin-top: 15px;"> <<link "<div class='stream-button' style='background: #7f8c8d;'>← Back to Laptop</div>">> <<if _stream.hoursStreamed >= 1>> <<goto "StreamResults">> <<else>> <<set $streamingData.currentStream = null>> <<goto "UseLaptop">> <</if>> <</link>> </div> </div> </div> <</nobr>> <style> <<include "StreamingStyles">> </style>
<<nobr>> <!-- Check for exhaustion and force end stream --> <<if setup.hasDebuff("exhaustion") && $streamingData.currentStream>> <<goto "StreamResults">> <</if>> <!-- Check if player has required music skills (Siren transformation includes Singing) --> <<set _hasSinging = $skills.includes("Singing") || $physicalTraits.includes("Siren")>> <<set _hasGuitar = $skills.includes("Guitar")>> <<set _hasPiano = $skills.includes("Piano")>> <<if !_hasSinging && !_hasGuitar && !_hasPiano>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="padding: 25px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e74c3c; box-shadow: 0 0 30px rgba(231, 76, 60, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5); font-size: 32px;"> 🚫 Skill Required </h1> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; border: 2px solid #e74c3c; text-align: center;"> <p style="color: #aaa; font-size: 18px; line-height: 1.6; margin: 0 0 25px 0;"> You need at least one of these skills to stream music: <strong style="color: #ff6347;">Singing</strong>, <strong style="color: #ff6347;">Guitar</strong>, or <strong style="color: #ff6347;">Piano</strong>. </p> <p style="color: #888; font-size: 16px; margin: 0 0 25px 0;"> Without musical skills, you won't be able to create quality music content. </p> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Categories</div>">> <<goto "SelectStreamCategory">> <</link>> </div> </div> <<else>> <<if !$streamingData.currentStream>> <<run setup.startStream("music")>> <</if>> <<set _stream = $streamingData.currentStream>> <<set _canContinue = _stream.hoursStreamed < _stream.maxHours>> <div class="streaming-container"> <!-- Header --> <div class="stream-header" style="background: linear-gradient(135deg, #ff6347 0%, #ff4500 100%);"> <h1> <span class="live-indicator"></span> Music Stream - LIVE </h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Live musical performance for your viewers </p> </div> <!-- Stats Bar --> <div class="stream-stats-bar"> <div class="stat-card followers"> <div class="stat-icon">👥</div> <div class="stat-label">Followers</div> <div class="stat-value"><<= $streamingData.followers>></div> </div> <div class="stat-card viewers"> <div class="stat-icon">👁️</div> <div class="stat-label">Current Viewers</div> <div class="stat-value"><<= _stream.viewerData.current>></div> <div style="font-size: 12px; color: #aaa; margin-top: 5px;"> Peak: <<= _stream.viewerData.peak>> </div> </div> <div class="stat-card money"> <div class="stat-icon">💰</div> <div class="stat-label">Earnings</div> <div class="stat-value">$<<= _stream.incomeData.total>></div> </div> <div class="stat-card time"> <div class="stat-icon">⏱️</div> <div class="stat-label">Stream Time</div> <div class="stat-value"><<= _stream.hoursStreamed>> / <<= _stream.maxHours>> hrs</div> </div> </div> <!-- Show recent event if any --> <<if _stream.events.length > 0>> <<set _lastEvent = _stream.events[_stream.events.length - 1]>> <div class="event-notification"> <h3>🎉 <<= _lastEvent.event>></h3> <p><<= _lastEvent.description>></p> </div> <</if>> <!-- Trait Effects Display (Collapsible) --> <<if _stream.modifiers.traits.length > 0>> <<if !$hideTraitEffects>><<set $hideTraitEffects = false>><</if>> <div class="trait-effects"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h2 style="margin: 0;">✨ Active Trait Effects</h2> <<link "<<if $hideTraitEffects>>▼ Show<<else>>▲ Hide<</if>>">> <<set $hideTraitEffects = !$hideTraitEffects>> <<replace "#traitEffectsSection">> <<include "StreamTraitEffectsDisplay">> <</replace>> <</link>> </div> <span id="traitEffectsSection"> <<include "StreamTraitEffectsDisplay">> </span> </div> <</if>> <<if _canContinue>> <<include "StreamTrendingDisplay">> <!-- Action Selection --> <div class="action-selection"> <h2 style="color: #ff6347;">🎬 Choose Your Next Action (Hour <<= _stream.hoursStreamed + 1>>)</h2> <p style="color: #aaa; margin-bottom: 20px;"> Select what you want to do for the next hour of your stream. </p> <<set _trendInfo = (typeof setup.getTrendDisplay === "function") ? setup.getTrendDisplay("music") : { actions: {} }>> <div class="action-grid"> <<set _actions = setup.streamActions.music>> <<for _actionName, _actionData range _actions>> <<capture _actionName, _actionData>> <<set _isTrending = _trendInfo.actions && _trendInfo.actions[_actionName]>> <<set _trendBoost = _isTrending ? Math.round((_trendInfo.actions[_actionName].boost - 1) * 100) : 0>> <<set _cardBorder = _isTrending ? "#e94560" : "#ff6347">> <<set _cardGlow = _isTrending ? "box-shadow: 0 0 15px rgba(233, 69, 96, 0.4);" : "">> <div class="action-card" style="border: 3px solid <<= _cardBorder>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: all 0.3s ease; position: relative; <<= _cardGlow>>"> <<if _isTrending>> <div style="position: absolute; top: -10px; right: 10px; background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: bold; color: white;"> 🔥 +<<= _trendBoost>>% </div> <</if>> <<link _actionName>> <<set $streamActionResult = setup.processStreamHour(_actionName)>> <<advancetime 60>> <<goto "StreamActionResult">> <</link>> <p style="color: #aaa; font-size: 14px; margin: 10px 0;"><<print _actionData.description>></p> <div style="display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px;"> <span>👁️</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">+<<print _actionData.baseViewerGain>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>💰</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">~$<<print _actionData.baseMoney>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>📊</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>"><<print _actionData.baseEngagement>>%<<if _isTrending>> ↑<</if>></span> </div> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <!-- Stream time limit reached --> <div style="text-align: center; padding: 40px;"> <h2 style="color: #e74c3c;"> ⏰ Stream Time Limit Reached </h2> <p style="color: #aaa; font-size: 16px; margin: 20px 0;"> You've reached your maximum stream time for today. <<if _stream.maxHours === 4>> (Limited to 4 hours due to having another job) <</if>> </p> </div> <</if>> <!-- Stream Controls --> <div style="text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px solid #333;"> <<if _stream.hoursStreamed >= 1>> <<link "<div class='stream-button end'>📴 End Stream</div>">> <<goto "StreamResults">> <</link>> <<else>> <p style="color: #888; font-style: italic;"> Must stream for at least 1 hour before ending </p> <</if>> <div style="margin-top: 15px;"> <<link "<div class='stream-button' style='background: #7f8c8d;'>← Back to Laptop</div>">> <<if _stream.hoursStreamed >= 1>> <<goto "StreamResults">> <<else>> <<set $streamingData.currentStream = null>> <<goto "UseLaptop">> <</if>> <</link>> </div> </div> </div> <</if>> <</nobr>> <style> <<include "StreamingStyles">> </style>
<<nobr>> <!-- Check for exhaustion and force end stream --> <<if setup.hasDebuff("exhaustion") && $streamingData.currentStream>> <<goto "StreamResults">> <</if>> <!-- Check if player has required cooking skills --> <<set _hasCooking = $skills.includes("Cooking")>> <<set _hasBaking = $skills.includes("Baking")>> <<if !_hasCooking && !_hasBaking>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="padding: 25px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e74c3c; box-shadow: 0 0 30px rgba(231, 76, 60, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5); font-size: 32px;"> 🚫 Skill Required </h1> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; border: 2px solid #e74c3c; text-align: center;"> <p style="color: #aaa; font-size: 18px; line-height: 1.6; margin: 0 0 25px 0;"> You need at least one of these skills to stream cooking: <strong style="color: #f39c12;">Cooking</strong> or <strong style="color: #f39c12;">Baking</strong>. </p> <p style="color: #888; font-size: 16px; margin: 0 0 25px 0;"> Without culinary skills, you won't be able to create quality cooking content. </p> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Categories</div>">> <<goto "SelectStreamCategory">> <</link>> </div> </div> <<else>> <<if !$streamingData.currentStream>> <<run setup.startStream("cooking")>> <</if>> <<set _stream = $streamingData.currentStream>> <<set _canContinue = _stream.hoursStreamed < _stream.maxHours>> <div class="streaming-container"> <!-- Header --> <div class="stream-header" style="background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);"> <h1> <span class="live-indicator"></span> Cooking Stream - LIVE </h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Delicious cooking content for your viewers </p> </div> <!-- Stats Bar --> <div class="stream-stats-bar"> <div class="stat-card followers"> <div class="stat-icon">👥</div> <div class="stat-label">Followers</div> <div class="stat-value"><<= $streamingData.followers>></div> </div> <div class="stat-card viewers"> <div class="stat-icon">👁️</div> <div class="stat-label">Current Viewers</div> <div class="stat-value"><<= _stream.viewerData.current>></div> <div style="font-size: 12px; color: #aaa; margin-top: 5px;"> Peak: <<= _stream.viewerData.peak>> </div> </div> <div class="stat-card money"> <div class="stat-icon">💰</div> <div class="stat-label">Earnings</div> <div class="stat-value">$<<= _stream.incomeData.total>></div> </div> <div class="stat-card time"> <div class="stat-icon">⏱️</div> <div class="stat-label">Stream Time</div> <div class="stat-value"><<= _stream.hoursStreamed>> / <<= _stream.maxHours>> hrs</div> </div> </div> <!-- Show recent event if any --> <<if _stream.events.length > 0>> <<set _lastEvent = _stream.events[_stream.events.length - 1]>> <div class="event-notification"> <h3>🎉 <<= _lastEvent.event>></h3> <p><<= _lastEvent.description>></p> </div> <</if>> <!-- Trait Effects Display (Collapsible) --> <<if _stream.modifiers.traits.length > 0>> <<if !$hideTraitEffects>><<set $hideTraitEffects = false>><</if>> <div class="trait-effects"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h2 style="margin: 0;">✨ Active Trait Effects</h2> <<link "<<if $hideTraitEffects>>▼ Show<<else>>▲ Hide<</if>>">> <<set $hideTraitEffects = !$hideTraitEffects>> <<replace "#traitEffectsSection">> <<include "StreamTraitEffectsDisplay">> <</replace>> <</link>> </div> <span id="traitEffectsSection"> <<include "StreamTraitEffectsDisplay">> </span> </div> <</if>> <<if _canContinue>> <<include "StreamTrendingDisplay">> <!-- Action Selection --> <div class="action-selection"> <h2 style="color: #f39c12;">🎬 Choose Your Next Action (Hour <<= _stream.hoursStreamed + 1>>)</h2> <p style="color: #aaa; margin-bottom: 20px;"> Select what you want to cook for the next hour of your stream. </p> <<set _trendInfo = (typeof setup.getTrendDisplay === "function") ? setup.getTrendDisplay("cooking") : { actions: {} }>> <div class="action-grid"> <<set _actions = setup.streamActions.cooking>> <<for _actionName, _actionData range _actions>> <<capture _actionName, _actionData>> <<set _isTrending = _trendInfo.actions && _trendInfo.actions[_actionName]>> <<set _trendBoost = _isTrending ? Math.round((_trendInfo.actions[_actionName].boost - 1) * 100) : 0>> <<set _cardBorder = _isTrending ? "#e94560" : "#f39c12">> <<set _cardGlow = _isTrending ? "box-shadow: 0 0 15px rgba(233, 69, 96, 0.4);" : "">> <div class="action-card" style="border: 3px solid <<= _cardBorder>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); cursor: pointer; transition: all 0.3s ease; position: relative; <<= _cardGlow>>"> <<if _isTrending>> <div style="position: absolute; top: -10px; right: 10px; background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: bold; color: white;"> 🔥 +<<= _trendBoost>>% </div> <</if>> <<link _actionName>> <<set $streamActionResult = setup.processStreamHour(_actionName)>> <<advancetime 60>> <<goto "StreamActionResult">> <</link>> <p style="color: #aaa; font-size: 14px; margin: 10px 0;"><<print _actionData.description>></p> <div style="display: flex; justify-content: space-between; font-size: 12px; color: #888; margin-top: 10px;"> <div style="display: flex; align-items: center; gap: 5px;"> <span>👁️</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">+<<print _actionData.baseViewerGain>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>💰</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>">~$<<print _actionData.baseMoney>><<if _isTrending>> ↑<</if>></span> </div> <div style="display: flex; align-items: center; gap: 5px;"> <span>📊</span> <span style="<<if _isTrending>>color: #e94560; font-weight: bold;<</if>>"><<print _actionData.baseEngagement>>%<<if _isTrending>> ↑<</if>></span> </div> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <!-- Stream time limit reached --> <div style="text-align: center; padding: 40px;"> <h2 style="color: #e74c3c;"> ⏰ Stream Time Limit Reached </h2> <p style="color: #aaa; font-size: 16px; margin: 20px 0;"> You've reached your maximum stream time for today. <<if _stream.maxHours === 4>> (Limited to 4 hours due to having another job) <</if>> </p> </div> <</if>> <!-- Stream Controls --> <div style="text-align: center; margin-top: 30px; padding-top: 20px; border-top: 2px solid #333;"> <<if _stream.hoursStreamed >= 1>> <<link "<div class='stream-button end'>📴 End Stream</div>">> <<goto "StreamResults">> <</link>> <<else>> <p style="color: #888; font-style: italic;"> Must stream for at least 1 hour before ending </p> <</if>> <div style="margin-top: 15px;"> <<link "<div class='stream-button' style='background: #7f8c8d;'>← Back to Laptop</div>">> <<if _stream.hoursStreamed >= 1>> <<goto "StreamResults">> <<else>> <<set $streamingData.currentStream = null>> <<goto "UseLaptop">> <</if>> <</link>> </div> </div> </div> <</if>> <</nobr>> <style> <<include "StreamingStyles">> </style>
<<nobr>> <<if !setup.isMallOpen()>> <<goto "MallClosed">> <</if>> <<set $lastLocation = "MallFloor2">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("MallFloor2")>> <<run $visitedLocations.push("MallFloor2")>> <</if>> <!-- Check if player has bank account --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">🛍️ Sunfish City Mall - Floor 2</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> The second floor features specialty shops and music stores. The sound of distant music drifts through the corridors. </p> </div> <h2 style="color: #9b59b6;">Floor 2 Directory</h2> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Turbo Tuna Athletics --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; opacity: 0.6;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">⚡ Turbo Tuna Athletics</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">High-performance sportswear and athletic gear.</p> <div style='background: #555; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Neon Tetra Temptations --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; opacity: 0.6;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">💋 Neon Tetra Temptations</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Seductive lingerie and intimate apparel.</p> <div style='background: #555; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Puffers and Pockets --> <div style="border: 3px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; opacity: 0.6;"> <h3 style="color: #95a5a6; margin: 0 0 10px 0;">👕 Puffers and Pockets</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Comfortable everyday wear and casual fashion.</p> <div style='background: #555; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Koi Crown --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; opacity: 0.6;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">👑 Koi Crown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Premium designer fashion and luxury apparel.</p> <div style='background: #555; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Chromis Tunes --> <div style="border: 3px solid #ff6347; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🎸 Chromis Tunes</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Musical instruments, gear, and recording equipment.</p> <<link "<div style='background: #ff6347; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Store</div>">> <<goto "ChromisTunes">> <</link>> </div> <!-- Jewelry Store --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💎 Starfish Jewelers</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Fine jewelry, accessories, and fragrances.</p> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Store</div>">> <<goto "JewelryStore">> <</link>> </div> <!-- Coral Furnishings (Closed) --> <div style="border: 3px solid #555; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px; opacity: 0.6;"> <h3 style="color: #888; margin: 0 0 10px 0;">🏠 Coral Furnishings</h3> <p style="font-size: 14px; color: #666; margin: 0 0 auto 0; line-height: 1.4;">The storefront is dark and the doors are locked. A sign hangs in the window.</p> <div style="background: #333; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;">Closed</div> </div> <!-- ATM - 6th Slot --> <div style="border: 3px solid <<if _hasBankAccount>>#4dabf7<<else>>#555<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: <<if _hasBankAccount>>#4dabf7<<else>>#888<</if>>; margin: 0 0 10px 0;">🏧 ATM</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;"> <<if _hasBankAccount>> Quick cash withdrawals. FREE - no fees! $30,000/day limit. <<else>> Requires bank account. Open one at Sunfish City Bank for $250. <</if>> </p> <<if _hasBankAccount>> <<link "<div style='background: #4dabf7; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Use ATM</div>" "ATM">><</link>> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed; border: 1px solid #555;'> No Account </div> <</if>> </div> </div> <br> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #9b59b6; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Go to Floor 1 ⬇️</div>">> <<goto "Mall">> <</link>> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Mall</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ChromisTunes">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ChromisTunes")>> <<run $visitedLocations.push("ChromisTunes")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6347; text-align: center;">🎸 Chromis Tunes</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6347 0%, #ff4500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6347;"> <p style="color: white; font-size: 18px; margin: 0;"> The walls are lined with guitars, keyboards, and audio equipment. The faint hum of amplifiers fills the air, and you can hear someone testing a drum kit in the back room. </p> </div> <h2 style="color: #ff6347;">Available Equipment</h2> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Guitar --> <<set _canAffordGuitar = setup.canAffordTotal(500)>> <div style="border: 3px solid <<if $ownsGuitar>>#2ecc71<<else>>#ff6347<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🎸 Guitar</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">A quality acoustic-electric guitar perfect for streaming.</p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 10px 0;">Price: $500</p> <<if $ownsGuitar>> <div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>✓ Owned</div> <<elseif _canAffordGuitar>> <<link "<div style='background: #ff6347; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase</div>">> <<set _payment = setup.payAmount(500)>> <<if _payment.success>> <<set $ownsGuitar = true>> <</if>> <<goto "ChromisTunes">> <</link>> <<else>> <div style='background: #555; color: #aaa; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>Not Enough Money</div> <</if>> </div> <!-- Electric Piano --> <<set _canAffordPiano = setup.canAffordTotal(800)>> <div style="border: 3px solid <<if $ownsElectricPiano>>#2ecc71<<else>>#ff6347<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🎹 Electric Piano</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">A professional 88-key digital piano with weighted keys.</p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 10px 0;">Price: $800</p> <<if $ownsElectricPiano>> <div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>✓ Owned</div> <<elseif _canAffordPiano>> <<link "<div style='background: #ff6347; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase</div>">> <<set _payment = setup.payAmount(800)>> <<if _payment.success>> <<set $ownsElectricPiano = true>> <</if>> <<goto "ChromisTunes">> <</link>> <<else>> <div style='background: #555; color: #aaa; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>Not Enough Money</div> <</if>> </div> <!-- Microphone --> <<set _canAffordMic = setup.canAffordTotal(300)>> <div style="border: 3px solid <<if $ownsMicrophone>>#2ecc71<<else>>#ff6347<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🎤 Microphone</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">A studio-quality condenser microphone with stand.</p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 10px 0;">Price: $300</p> <<if $ownsMicrophone>> <div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>✓ Owned</div> <<elseif _canAffordMic>> <<link "<div style='background: #ff6347; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase</div>">> <<set _payment = setup.payAmount(300)>> <<if _payment.success>> <<set $ownsMicrophone = true>> <</if>> <<goto "ChromisTunes">> <</link>> <<else>> <div style='background: #555; color: #aaa; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>Not Enough Money</div> <</if>> </div> <!-- Speakers --> <<set _canAffordSpeakers = setup.canAffordTotal(600)>> <div style="border: 3px solid <<if $ownsSpeakers>>#2ecc71<<else>>#ff6347<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🔊 Speakers</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">High-quality studio monitor speakers (pair).</p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 10px 0;">Price: $600</p> <<if $ownsSpeakers>> <div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>✓ Owned</div> <<elseif _canAffordSpeakers>> <<link "<div style='background: #ff6347; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Purchase</div>">> <<set _payment = setup.payAmount(600)>> <<if _payment.success>> <<set $ownsSpeakers = true>> <</if>> <<goto "ChromisTunes">> <</link>> <<else>> <div style='background: #555; color: #aaa; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold;'>Not Enough Money</div> <</if>> </div> </div> <br> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Back to Floor 2</div>">> <<goto "MallFloor2">> <</link>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("ChromisTunes")>> <h2 style="color: #ff6347;">🎸 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6347; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ff6347; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #ff6347; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The music store is quiet right now. Just the hum of amplifiers in the background. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<if !$hideTraitEffects>> <div class="trait-list"> <<for _i = 0; _i < _stream.modifiers.traits.length; _i++>> <<set _trait = _stream.modifiers.traits[_i]>> <div @class="'trait-item ' + _trait.type"> <div class="trait-icon"><<if _trait.type === "positive">>✅<<else>>❌<</if>></div> <div class="trait-info"> <div class="trait-name"><<= _trait.name>></div> <div class="trait-description"><<= _trait.description>></div> </div> </div> <</for>> </div> <div style="margin-top: 15px; padding: 12px; background: #0a0a0a; border-radius: 8px; border: 1px solid #333;"> <strong style="color: #51cf66;">Total Modifiers:</strong> <span style="color: white; margin-left: 10px;"> Viewers: <<if _stream.modifiers.viewerMultiplier > 1>>+<</if>><<= Math.floor((_stream.modifiers.viewerMultiplier - 1) * 100)>>% </span> <span style="color: white; margin-left: 20px;"> Engagement: <<if _stream.modifiers.engagementMultiplier > 1>>+<</if>><<= Math.floor((_stream.modifiers.engagementMultiplier - 1) * 100)>>% </span> </div> <</if>> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("MeetNeighbors")>> <<run $visitedLocations.push("MeetNeighbors")>> <</if>> <<set $lastLocation = "MeetNeighbors">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">👥 Apartment Common Area</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> A cozy common area with comfortable seating and a large TV. Several of your neighbors are here, chatting and relaxing. </p> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("MeetNeighbors")>> <h2 style="color: #9b59b6;">Lounge</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 20px 0;">Some of your neighbors are also content creators!</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<if setup.isNPCAvailable(_npc.name)>> <<capture _npc>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</if>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin: 0; text-align: center; font-style: italic;"> The common area is empty right now. No streamers are around. </p> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Apartments</div>">> <<goto "Apartments">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub">> <!-- Check for bank account using correct property --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔞 PrawnHub</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1493;"> <p style="color: white; font-size: 18px; margin: 0;"> Welcome to PrawnHub - the internet's premier adult entertainment platform. Browse content or stream your own. </p> </div> <h2 style="color: #ff1493;">Adult Entertainment Options</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Browse Content --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff69b4; margin: 0 0 10px 0;">👀 Browse Content</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Watch adult videos and explore various categories.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Coming Soon</div> </div> <!-- Stream Yourself --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff1493; margin: 0 0 10px 0;">📹 Stream Yourself</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Go live and earn money from viewers watching your stream.</p> <<if !$hasWebcam>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px;'>Requires Webcam</div> <<elseif !_hasBankAccount>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 14px; border: 1px solid #6b4a4a; margin-top: 10px;'>Requires Bank Account</div> <<elseif $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Go Live</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "adultStreaming">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Go Live</div>">> <<goto "PrawnHubStream">> <</link>> <</if>> </div> <!-- Adult Stream Analytics --> <<if $prawnhubRegistered>> <div style="border: 3px solid #ff6347; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">📊 PrawnHub Analytics</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">View your adult streaming statistics, earnings, and viewer metrics.</p> <<link "<div style='background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>View Analytics</div>">> <<goto "PrawnHubAnalytics">> <</link>> </div> <</if>> </div> <!-- Bank Account Requirement Notice (for adult streaming) --> <<if !_hasBankAccount && $hasWebcam>> <div style="background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #ff1493; box-shadow: 0 4px 8px rgba(255,20,147,0.4);"> <h3 style="color: white; margin: 0 0 10px 0; text-align: center;">💳 Bank Account Required for Adult Streaming</h3> <p style="color: white; margin: 0; text-align: center; font-size: 15px;"> Adult streaming platforms require a bank account to receive tips, donations, and revenue payments from viewers.<br><br> Open a bank account at the Sunfish City Bank in Downtown. </p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Internet</div>">> <<goto "BrowseInternet">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHubStream">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔞 PrawnHub Streaming</h1> <!-- Registration Check --> <<if !$prawnhubRegistered>> <div style="padding: 30px; background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1493; text-align: center;"> <h2 style="color: #ff1493; margin-bottom: 20px;">Welcome to PrawnHub Streaming!</h2> <p style="color: #ccc; font-size: 16px; margin-bottom: 25px;"> Ready to start your adult streaming career? Create your performer profile to begin earning from live streams. </p> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 1px solid #ff69b4; margin-bottom: 20px;"> <h3 style="color: #ff69b4; margin-top: 0;">How It Works:</h3> <ul style="color: #aaa; text-align: left; line-height: 1.8;"> <li>Go live and perform for viewers</li> <li>Earn tips and donations during streams</li> <li>Build your follower base</li> <li>70% revenue share (you keep $0.70 per dollar earned)</li> <li>Stream up to 8 hours per session</li> </ul> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Register as Performer</div>">> <<set $prawnhubRegistered = true>> <<goto "PrawnHubStream">> <</link>> </div> <<else>> <!-- Check for bank account --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <!-- Streaming Interface --> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1493;"> <!-- Stats Display --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="background: #333; padding: 15px; border-radius: 8px; border: 1px solid #ff69b4;"> <div style="color: #ff69b4; font-size: 14px; margin-bottom: 5px;">👥 Followers</div> <div style="color: white; font-size: 24px; font-weight: bold;"><<print $prawnhubFollowers.toLocaleString()>></div> </div> <div style="background: #333; padding: 15px; border-radius: 8px; border: 1px solid #4ade80;"> <div style="color: #4ade80; font-size: 14px; margin-bottom: 5px;">💰 Total Earnings</div> <div style="color: white; font-size: 24px; font-weight: bold;">$<<print Math.ceil($prawnhubTotalEarnings)>></div> </div> <div style="background: #333; padding: 15px; border-radius: 8px; border: 1px solid #fbbf24;"> <div style="color: #fbbf24; font-size: 14px; margin-bottom: 5px;">⏱️ Session Limit</div> <div style="color: white; font-size: 24px; font-weight: bold;">8 Hours</div> </div> </div> <!-- Bank Account Requirement Notice --> <<if !_hasBankAccount>> <div style="background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #dc3545; box-shadow: 0 4px 8px rgba(220,53,69,0.4);"> <h3 style="color: white; margin: 0 0 10px 0; text-align: center;">🏦 Bank Account Required</h3> <p style="color: white; margin: 0 0 15px 0; text-align: center; font-size: 15px;"> PrawnHub requires all performers to have a bank account for receiving digital payments and tips. </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: white; color: #dc3545; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>Open Bank Account</div>">> <<goto "Bank">> <</link>> </div> </div> <</if>> <!-- Go Live Button --> <div style="text-align: center; margin: 30px 0;"> <<if _hasBankAccount>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 20px 50px; border-radius: 10px; font-weight: bold; font-size: 20px; box-shadow: 0 6px 12px rgba(255,20,147,0.4);'>🔴 GO LIVE</div>">> <<goto "PrawnHubLiveStream">> <</link>> <<else>> <div style='display: inline-block; background: #4a2a2a; color: #c9a8a8; padding: 20px 50px; border-radius: 10px; font-weight: bold; font-size: 20px; border: 2px solid #6b4a4a; cursor: not-allowed;'>🔴 GO LIVE (Bank Account Required)</div> <</if>> </div> <!-- Recent Streams --> <<if $prawnhubStreamHistory.length > 0>> <h3 style="color: #ff1493; margin-top: 30px;">Recent Streams</h3> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 1px solid #444;"> <<for _i = 0; _i < Math.min(5, $prawnhubStreamHistory.length); _i++>> <<set _stream = $prawnhubStreamHistory[$prawnhubStreamHistory.length - 1 - _i]>> <div style="padding: 10px; background: #333; margin-bottom: 10px; border-radius: 6px; border-left: 3px solid #ff1493;"> <div style="color: #ff69b4; font-weight: bold;">Day <<print _stream.day>></div> <div style="color: #aaa; font-size: 14px;"> Viewers: <<print _stream.viewers || 0>> | Earnings: $<<print Math.ceil(_stream.netEarnings || 0)>> | New Followers: +<<print _stream.newFollowers>> </div> </div> <</for>> </div> <</if>> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to PrawnHub</div>">> <<goto "PrawnHub">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHubLiveStream">> <!-- Initialize streaming session if not already started --> <<if !$currentPrawnStream>> <!-- Calculate base viewers --> <<set _baseViewers = Math.max(10, Math.floor($prawnhubFollowers * 0.15) + random(5, 20))>> <<set $currentPrawnStream = { active: true, startTime: $gameTime, totalMinutes: 0, maxMinutes: 480, viewers: _baseViewers, peakViewers: 0, baseEngagement: 45, currentEngagement: 45, earnings: 0, tips: 0, currentAction: null, actionTimeLeft: 0, actionsPerformed: [], clothingLayers: 3, specialAccessoryActive: false, startingFollowers: $prawnhubFollowers }>> <<set $currentPrawnStream.peakViewers = $currentPrawnStream.viewers>> <</if>> <!-- Action is running - advance time by 30 minutes --> <<if $currentPrawnStream.actionTimeLeft > 0>> <<set $currentPrawnStream.actionTimeLeft -= 30>> <<set $currentPrawnStream.totalMinutes += 30>> <<advancetime 30>> <!-- Calculate earnings for this 30-minute segment --> <<set _engagementMultiplier = $currentPrawnStream.currentEngagement / 100>> <<set _viewerTips = $currentPrawnStream.viewers * random(0.5, 2.5) * _engagementMultiplier>> <<set _playerShare = _viewerTips * 0.70>> <<set $currentPrawnStream.earnings += _playerShare>> <<set $currentPrawnStream.tips += Math.floor(random(1, 4))>> <!-- Viewer fluctuation --> <<set _viewerChange = random(-3, 8)>> <<set $currentPrawnStream.viewers = Math.max(5, $currentPrawnStream.viewers + _viewerChange)>> <<if $currentPrawnStream.viewers > $currentPrawnStream.peakViewers>> <<set $currentPrawnStream.peakViewers = $currentPrawnStream.viewers>> <</if>> <!-- Reset action if time is up --> <<if $currentPrawnStream.actionTimeLeft <= 0>> <<set $currentPrawnStream.currentAction = null>> <</if>> <</if>> <!-- Check chest and butt sizes --> <<set _hasChestSize = false>> <<if $bodyParts && $bodyParts.chest>> <<if ["medium", "large", "huge", "giant", "gigantic"].includes($bodyParts.chest)>> <<set _hasChestSize = true>> <</if>> <</if>> <<set _hasButtSize = false>> <<if $bodyParts && $bodyParts.butt>> <<if ["medium", "large", "huge", "giant", "gigantic"].includes($bodyParts.butt)>> <<set _hasButtSize = true>> <</if>> <</if>> <<set _hasBreasts = false>> <<if $bodyParts && $bodyParts.chest>> <<if ["small", "medium", "large", "huge", "giant", "gigantic"].includes($bodyParts.chest)>> <<set _hasBreasts = true>> <</if>> <</if>> <!-- Check for adult toys --> <<set _hasToy = false>> <<if $ownsFleshlight || $ownsDildo>> <<set _hasToy = true>> <</if>> <<set _hasOralToy = false>> <<if $ownsFleshlight || $ownsDildo>> <<set _hasOralToy = true>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 LIVE on PrawnHub</h1> <!-- Stream Stats Bar --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 20px;"> <div style="background: #2a2a2a; padding: 12px; border-radius: 8px; border: 2px solid #ff69b4;"> <div style="color: #ff69b4; font-size: 12px;">👥 VIEWERS</div> <div style="color: white; font-size: 20px; font-weight: bold;"><<print $currentPrawnStream.viewers>></div> </div> <div style="background: #2a2a2a; padding: 12px; border-radius: 8px; border: 2px solid #4ade80;"> <div style="color: #4ade80; font-size: 12px;">📊 ENGAGEMENT</div> <div style="color: white; font-size: 20px; font-weight: bold;"><<print Math.round($currentPrawnStream.currentEngagement)>>%</div> </div> <div style="background: #2a2a2a; padding: 12px; border-radius: 8px; border: 2px solid #fbbf24;"> <div style="color: #fbbf24; font-size: 12px;">💰 EARNINGS</div> <div style="color: white; font-size: 20px; font-weight: bold;">$<<print Math.ceil($currentPrawnStream.earnings)>></div> </div> <div style="background: #2a2a2a; padding: 12px; border-radius: 8px; border: 2px solid #c71585;"> <div style="color: #c71585; font-size: 12px;">⏱️ TIME LEFT</div> <div style="color: white; font-size: 20px; font-weight: bold;"> <<print Math.floor(($currentPrawnStream.maxMinutes - $currentPrawnStream.totalMinutes) / 60)>>h <<print ($currentPrawnStream.maxMinutes - $currentPrawnStream.totalMinutes) % 60>>m </div> </div> </div> <!-- Current Action Display --> <<if $currentPrawnStream.currentAction !== null>> <div style="background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); padding: 20px; border-radius: 10px; margin-bottom: 20px; text-align: center; border: 2px solid #ff69b4;"> <div style="color: white; font-size: 18px; font-weight: bold; margin-bottom: 10px;"> <<print $currentPrawnStream.currentAction.message>> </div> <div style="color: #ffe6f0; font-size: 16px;"> ⏰ Time Remaining: <<print $currentPrawnStream.actionTimeLeft>> minutes </div> </div> <</if>> <!-- Performance Actions Grid --> <<if $currentPrawnStream.totalMinutes < $currentPrawnStream.maxMinutes>> <h2 style="color: #ff1493; margin-bottom: 15px;">Performance Actions</h2> <div class="prawn-actions-grid"> <!-- STRIP CLOTHING --> <<set _hasStripped = $currentPrawnStream.actionsPerformed.includes("STRIP_CLOTHING")>> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && !_hasStripped>> <<link "<div class='prawn-action-btn'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>STRIP CLOTHING</div><div style='color: #aaa; font-size: 13px;'>Slowly remove each piece</div></div>">> <<goto "PrawnHub_Action01">> <</link>> <<elseif _hasStripped>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>STRIP CLOTHING ✓</div><div style='color: #8a6a6a; font-size: 13px;'>Already Used</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>STRIP CLOTHING</div><div style='color: #555; font-size: 13px;'>Slowly remove each piece</div></div> <</if>> </div> <!-- SIMULATE SEX --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && _hasToy>> <<link "<div class='prawn-action-btn'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>SIMULATE SEX</div><div style='color: #aaa; font-size: 13px;'>Simulate sex with an adult toy</div></div>">> <<goto "PrawnHub_Action02">> <</link>> <<elseif !_hasToy>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>SIMULATE SEX 🔒</div><div style='color: #8a6a6a; font-size: 13px;'>Requires: Fleshlight or Dildo</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>SIMULATE SEX</div><div style='color: #555; font-size: 13px;'>Simulate sex with an adult toy</div></div> <</if>> </div> <!-- BREASTS CLAP --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && _hasChestSize>> <<link "<div class='prawn-action-chest'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>BREASTS CLAP</div><div style='color: #aaa; font-size: 13px;'>Bounce them rhythmically</div></div>">> <<goto "PrawnHub_Action03">> <</link>> <<elseif !_hasChestSize>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>BREASTS CLAP 🔒</div><div style='color: #8a6a6a; font-size: 13px;'>Requires: Medium+ Chest</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>BREASTS CLAP</div><div style='color: #555; font-size: 13px;'>Bounce them rhythmically</div></div> <</if>> </div> <!-- ASS CLAP --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && _hasButtSize>> <<link "<div class='prawn-action-butt'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>ASS CLAP</div><div style='color: #aaa; font-size: 13px;'>Make those cheeks jiggle</div></div>">> <<goto "PrawnHub_Action04">> <</link>> <<elseif !_hasButtSize>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>ASS CLAP 🔒</div><div style='color: #8a6a6a; font-size: 13px;'>Requires: Medium+ Butt</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>ASS CLAP</div><div style='color: #555; font-size: 13px;'>Make those cheeks jiggle</div></div> <</if>> </div> <!-- MASSAGE BREASTS --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && _hasBreasts>> <<link "<div class='prawn-action-chest'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>MASSAGE BREASTS</div><div style='color: #aaa; font-size: 13px;'>Squeeze and caress them</div></div>">> <<goto "PrawnHub_Action05">> <</link>> <<elseif !_hasBreasts>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>MASSAGE BREASTS 🔒</div><div style='color: #8a6a6a; font-size: 13px;'>Requires: Small+ Chest</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>MASSAGE BREASTS</div><div style='color: #555; font-size: 13px;'>Squeeze and caress them</div></div> <</if>> </div> <!-- MASTURBATE --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null>> <<link "<div class='prawn-action-btn'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>MASTURBATE</div><div style='color: #aaa; font-size: 13px;'>Touch yourself intimately</div></div>">> <<goto "PrawnHub_Action06">> <</link>> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>MASTURBATE</div><div style='color: #555; font-size: 13px;'>Touch yourself intimately</div></div> <</if>> </div> <!-- SIMULATE ORAL --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && _hasOralToy>> <<link "<div class='prawn-action-btn'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>SIMULATE ORAL</div><div style='color: #aaa; font-size: 13px;'>Lick or suck a toy</div></div>">> <<goto "PrawnHub_Action07">> <</link>> <<elseif !_hasOralToy>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>SIMULATE ORAL 🔒</div><div style='color: #8a6a6a; font-size: 13px;'>Requires: Fleshlight or Dildo</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>SIMULATE ORAL</div><div style='color: #555; font-size: 13px;'>Lick or suck a toy</div></div> <</if>> </div> <!-- POSE NUDE --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null && _hasStripped>> <<link "<div class='prawn-action-btn'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>POSE NUDE</div><div style='color: #aaa; font-size: 13px;'>Display your naked body</div></div>">> <<goto "PrawnHub_Action08">> <</link>> <<elseif !_hasStripped>> <div class='prawn-action-locked'><div style='color: #c9a8a8; font-weight: bold; margin-bottom: 5px;'>POSE NUDE 🔒</div><div style='color: #8a6a6a; font-size: 13px;'>Requires: Strip First</div></div> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>POSE NUDE</div><div style='color: #555; font-size: 13px;'>Display your naked body</div></div> <</if>> </div> <!-- MOAN --> <div class="prawn-action-container"> <<if $currentPrawnStream.currentAction === null>> <<link "<div class='prawn-action-btn'><div style='color: #ff1493; font-weight: bold; margin-bottom: 5px;'>MOAN</div><div style='color: #aaa; font-size: 13px;'>Let out sexy sounds</div></div>">> <<goto "PrawnHub_Action11">> <</link>> <<else>> <div class='prawn-action-disabled'><div style='color: #666; font-weight: bold; margin-bottom: 5px;'>MOAN</div><div style='color: #555; font-size: 13px;'>Let out sexy sounds</div></div> <</if>> </div> <!-- Empty slot for alignment --> <div class="prawn-action-container"></div> </div> <</if>> <!-- End Stream Button --> <div style="text-align: center; margin-top: 80px;"> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 15px 40px; border-radius: 8px; border: 3px solid #dc2626; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>❌ End Stream</div>">> <<goto "PrawnHubStreamEnd">> <</link>> </div> </div> <<timed 50ms>> <<script>> setupPrawnActionButtons(); <</script>> <</timed>> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHubStreamEnd">> <!-- ONLY PROCESS STREAM DATA IF WE HAVE AN ACTIVE STREAM --> <<if $currentPrawnStream !== null>> <!-- SAVE CASH TO PREVENT ACCIDENTAL ADDITIONS --> <<set _savedMoney = $money>> <!-- Track total PrawnHub hours streamed --> <<if !$prawnhubTotalMinutesStreamed>> <<set $prawnhubTotalMinutesStreamed = 0>> <</if>> <<set $prawnhubTotalMinutesStreamed += $currentPrawnStream.totalMinutes>> <!-- Check for 8 hour PrawnHub stream achievement (480 minutes in one session) --> <<if $currentPrawnStream.totalMinutes >= 480>> <<run setup.achievements.unlock("prawnhub_8_hours")>> <</if>> <!-- Track PrawnHub actions for Category Master achievement --> <<if !$prawnhubActionsEverPerformed>> <<set $prawnhubActionsEverPerformed = []>> <</if>> <<for _action range $currentPrawnStream.actionsPerformed>> <<if !$prawnhubActionsEverPerformed.includes(_action)>> <<run $prawnhubActionsEverPerformed.push(_action)>> <</if>> <</for>> <!-- Calculate final stats and STORE IN STORY VARIABLES for persistence --> <!-- Apply streaming studio bonus (15%) if applicable --> <<set _studioBonus = $streamingFromStudio ? 1.15 : 1.0>> <<set _hasStudioBonus = $streamingFromStudio || false>> <<set $lastStreamResults = {}>> <<set $lastStreamResults.sessionEarnings = Math.floor($currentPrawnStream.earnings * _studioBonus)>> <<set $lastStreamResults.avgEngagement = Math.floor($currentPrawnStream.currentEngagement * _studioBonus)>> <<set $lastStreamResults.peakViewers = Math.floor($currentPrawnStream.peakViewers * _studioBonus)>> <<set $lastStreamResults.actionsPerformed = $currentPrawnStream.actionsPerformed.slice()>> <<set $lastStreamResults.actionScores = $currentPrawnStream.actionScores || {}>> <<set $lastStreamResults.totalActions = $lastStreamResults.actionsPerformed.length>> <<set $lastStreamResults.totalMinutes = $currentPrawnStream.totalMinutes>> <<set $lastStreamResults.studioBonus = _hasStudioBonus>> <!-- Initialize sexual skills if needed --> <<if ($skills.includes("Sexually Skilled") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju")) && !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Sexual Skill XP Gain System --> <<set $lastStreamResults.sexualXPGains = []>> <<if $skills.includes("Sexually Skilled") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju")>> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <!-- Check for small or bigger chest --> <<set _hasBreasts = false>> <<set _chestSizes = ["small", "medium", "large", "huge", "gigantic"]>> <<for _size range _chestSizes>> <<if $bodyParts.chest.includes(_size)>> <<set _hasBreasts = true>> <<break>> <</if>> <</for>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set $lastStreamResults.sexSkillXPBonus = _sexSkillXPBonus>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <!-- Process each action with score >= 85 --> <<for _action range $lastStreamResults.actionsPerformed>> <<set _score = $lastStreamResults.actionScores[_action] || 0>> <<if _score >= 85>> <<if _action === "STRIP_CLOTHING">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<elseif _action === "SIMULATE_SEX">> <<run setup.addSexualSkillExp("vaginal", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Vaginal", amount: _finalXP})>> <<run setup.addSexualSkillExp("anal", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Anal", amount: _finalXP})>> <<elseif _action === "BREASTS_CLAP">> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<elseif _action === "ASS_CLAP">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<elseif _action === "MASSAGE_BREASTS">> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Sensual", amount: _finalXP})>> <<elseif _action === "MASTURBATE">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<if _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <<elseif _hasPenis>> <<run setup.addSexualSkillExp("handjobs", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Handjobs", amount: _finalXP})>> <</if>> <<elseif _action === "SIMULATE_ORAL">> <<run setup.addSexualSkillExp("oralGiving", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Oral (Giving)", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<elseif _action === "POSE_NUDE">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<elseif _action === "MOAN">> <<run setup.addSexualSkillExp("dirtyTalk", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Dirty Talk", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run $lastStreamResults.sexualXPGains.push({skill: "Sensual", amount: _finalXP})>> <</if>> <</if>> <</for>> <</if>> <!-- Calculate new followers gained this session --> <<set $lastStreamResults.newFollowersThisSession = ($prawnhubFollowers || 0) - ($currentPrawnStream.startingFollowers || 0)>> <!-- Apply streaming studio bonus to followers (15%) --> <<if _hasStudioBonus>> <<set _studioFollowerBonus = Math.floor($lastStreamResults.newFollowersThisSession * 0.15)>> <<set $prawnhubFollowers += _studioFollowerBonus>> <<set $lastStreamResults.newFollowersThisSession += _studioFollowerBonus>> <</if>> <!-- Apply Crowd's Eye multiplier (2x followers gained) --> <<if ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _bonusFollowers = $lastStreamResults.newFollowersThisSession>> <<set $prawnhubFollowers += _bonusFollowers>> <<set $lastStreamResults.newFollowersThisSession = $lastStreamResults.newFollowersThisSession * 2>> <</if>> <!-- Check for follower milestone achievements --> <<if $prawnhubFollowers >= 500>> <<run setup.achievements.unlock("prawnhub_500_followers")>> <</if>> <<if $prawnhubFollowers >= 10000>> <<run setup.achievements.unlock("prawnhub_10k_followers")>> <</if>> <!-- Calculate platform cut based on job --> <<set _hasAdultStreamerJob = $jobs && $jobs.includes("Adult Streamer")>> <<set $lastStreamResults.platformCutPercent = _hasAdultStreamerJob ? 0.30 : 0.70>> <<set $lastStreamResults.grossEarnings = $lastStreamResults.sessionEarnings>> <<set $lastStreamResults.platformCut = Math.floor($lastStreamResults.grossEarnings * $lastStreamResults.platformCutPercent)>> <<set $lastStreamResults.netEarnings = $lastStreamResults.grossEarnings - $lastStreamResults.platformCut>> <!-- ===== SKILL TREE: Get streaming bonuses ===== --> <<set _streamingBonus = setup.skillTree.getEffect("streamingBonus")>> <<set _prawnhubStreamBonus = setup.skillTree.getEffect("prawnhubStreamBonus")>> <<set $lastStreamResults.totalStreamingBonus = _streamingBonus + _prawnhubStreamBonus>> <!-- ===== SKILL TREE: Apply streaming bonuses (after platform cut, before Pearl) ===== --> <<set $lastStreamResults.skillTreeBonus = 0>> <<set _baseNetEarnings = $lastStreamResults.netEarnings>> <<if $lastStreamResults.totalStreamingBonus > 0>> <<set $lastStreamResults.skillTreeBonus = Math.ceil($lastStreamResults.netEarnings * ($lastStreamResults.totalStreamingBonus / 100))>> <<set $lastStreamResults.netEarnings = $lastStreamResults.netEarnings + $lastStreamResults.skillTreeBonus>> <<set _baseNetEarnings = $lastStreamResults.netEarnings>> <</if>> <!-- Slut 2x cash bonus for PrawnHub --> <<set $lastStreamResults.slutActive = $physicalTraits.includes("Slut")>> <<set $lastStreamResults.slutBonus = 0>> <<if $lastStreamResults.slutActive>> <<set $lastStreamResults.slutBonus = _baseNetEarnings>> <<set $lastStreamResults.netEarnings = _baseNetEarnings + $lastStreamResults.slutBonus>> <<set _baseNetEarnings = $lastStreamResults.netEarnings>> <</if>> <!-- Pyrow +25% PrawnHub earnings on clear weather days --> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set $lastStreamResults.pyrowBonus = Math.ceil(_baseNetEarnings * 0.25)>> <<set $lastStreamResults.netEarnings = _baseNetEarnings + $lastStreamResults.pyrowBonus>> <<set _baseNetEarnings = $lastStreamResults.netEarnings>> <</if>> <!-- Honeybee +50% PrawnHub earnings with lustful buff --> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set $lastStreamResults.honeybeeBonus = Math.ceil(_baseNetEarnings * 0.5)>> <<set $lastStreamResults.netEarnings = _baseNetEarnings + $lastStreamResults.honeybeeBonus>> <<set _baseNetEarnings = $lastStreamResults.netEarnings>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) - AFTER skill tree --> <<set $lastStreamResults.pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set $lastStreamResults.pearlBonus = 0>> <<if $lastStreamResults.pearlActive>> <<set $lastStreamResults.pearlBonus = Math.ceil(_baseNetEarnings * 0.5)>> <<set $lastStreamResults.netEarnings = _baseNetEarnings + $lastStreamResults.pearlBonus>> <</if>> <!-- Crowd's Eye (and Naiad): doubles PrawnHub earnings --> <<if setup.hasCrowdsEye()>><<set $lastStreamResults.netEarnings = $lastStreamResults.netEarnings * 2>><</if>> <!-- Deposit to bank account (streaming revenue is digital - BANK ONLY, NO CASH) --> <<set $money = _savedMoney>> <<set $lastStreamResults.netEarnings = Math.ceil($lastStreamResults.netEarnings)>> <<set $bankAccount.balance += $lastStreamResults.netEarnings>> <!-- Update streaming stats --> <<set $prawnhubTotalEarnings += $lastStreamResults.netEarnings>> <<set $prawnhubSessionsToday += 1>> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <!-- Track Adult Streamer job for work_every_job achievement --> <<if $lastStreamResults.platformCutPercent === 0.30>> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Adult Streamer")>> <<run $jobsWorked.push("Adult Streamer")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <</if>> <!-- Save to history --> <<if !$prawnhubStreamHistory>> <<set $prawnhubStreamHistory = []>> <</if>> <<set $prawnhubStreamHistory.push({ day: $dayNumber, viewers: $lastStreamResults.peakViewers, grossEarnings: $lastStreamResults.grossEarnings, platformCut: $lastStreamResults.platformCut, netEarnings: $lastStreamResults.netEarnings, newFollowers: $lastStreamResults.newFollowersThisSession, engagement: $lastStreamResults.avgEngagement, duration: $lastStreamResults.totalMinutes, actionsPerformed: $lastStreamResults.actionsPerformed })>> <!-- Clean up stream - but KEEP lastStreamResults for display --> <<set $currentPrawnStream = null>> <</if>> <!-- END OF STREAM PROCESSING - Now we use $lastStreamResults for display --> <!-- Check for job transition (runs every time, uses current state) --> <<set _hasAdultStreamerJob = $jobs && $jobs.includes("Adult Streamer")>> <<set _becameAdultStreamer = false>> <<set _canBecomeAdultStreamer = false>> <<set _hasOtherJob = $jobs && $jobs.length > 0 && !$jobs.includes("Unemployed") && !$jobs.includes("Adult Streamer")>> <<if $prawnhubFollowers >= 500 && !_hasAdultStreamerJob>> <<if !$jobs || $jobs.length === 0 || $jobs.includes("Unemployed")>> <!-- Auto-assign Adult Streamer job if unemployed --> <<set $jobs = ["Adult Streamer"]>> <<set _becameAdultStreamer = true>> <<else>> <!-- Has other job, give choice --> <<set _canBecomeAdultStreamer = true>> <</if>> <</if>> <!-- Safety check: make sure we have lastStreamResults --> <<if !$lastStreamResults>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">⚠️ Stream Data Error</h1> <p style="color: white; text-align: center;">No stream data found. Please return to PrawnHub.</p> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px;'>Back to PrawnHub</div>">> <<goto "PrawnHub">> <</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">📊 Stream Summary</h1> <div style="max-width: 800px; margin: 0 auto;"> <!-- Job Transition Messages --> <<if _becameAdultStreamer>> <div style="background: linear-gradient(135deg, #27ae60 0%, #229954 100%); padding: 25px; border-radius: 12px; border: 3px solid #27ae60; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(39, 174, 96, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: white; margin: 0 0 15px 0;">🎉 Congratulations!</h2> <p style="color: #ffd; font-size: 18px; margin: 0;"> You've reached 500 followers! Your job is now <strong>Adult Streamer</strong>!<br> Platform cut reduced from 70% to 30%! </p> </div> <<elseif _canBecomeAdultStreamer>> <div style="background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); padding: 25px; border-radius: 12px; border: 3px solid #f39c12; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: white; margin: 0 0 15px 0;">💼 Job Opportunity</h2> <p style="color: #ffd; font-size: 16px; margin: 0 0 15px 0;"> You've reached 500 followers! Would you like to quit your current job (<<print $jobs.join(", ")>>) and become a full-time Adult Streamer?<br> <span style="font-size: 14px;">(Platform cut will be reduced from 70% to 30%)</span> </p> <div style="display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='display: inline-block; background: #27ae60; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>✓ Become Adult Streamer</div>">> <<set $jobs = ["Adult Streamer"]>> <<goto "PrawnHubStreamEnd">> <</link>> <<link "<div style='display: inline-block; background: #7f8c8d; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>✗ Keep Current Job</div>">> <<goto "PrawnHubStreamEnd">> <</link>> </div> </div> <</if>> <!-- ===== STREAMING STUDIO: Display bonus notification ===== --> <<if $lastStreamResults.studioBonus>> <div style="background: linear-gradient(135deg, #9146ff 0%, #7c3aed 100%); padding: 20px; border-radius: 12px; border: 3px solid #a78bfa; box-shadow: 0 0 20px rgba(145, 70, 255, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: #a78bfa; margin: 0 0 10px 0;">📺 Streaming Studio Bonus Active 📺</h2> <p style="color: #ddd6fe; margin: 0; font-size: 16px;"> +15% to all stream results (viewers, engagement, earnings, followers) </p> </div> <</if>> <!-- ===== SKILL TREE: Display bonus notification ===== --> <<if $lastStreamResults.totalStreamingBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 20px; border-radius: 12px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: #CE93D8; margin: 0 0 10px 0;">⭐ Skill Tree Bonuses Active ⭐</h2> <p style="color: #E1BEE7; margin: 0; font-size: 16px;"> <<set _streamingBonus = setup.skillTree.getEffect("streamingBonus")>> <<set _prawnhubStreamBonus = setup.skillTree.getEffect("prawnhubStreamBonus")>> <<if _streamingBonus > 0>> Streaming Bonus: +<<print _streamingBonus>>% <</if>> <<if _streamingBonus > 0 && _prawnhubStreamBonus > 0>> | <</if>> <<if _prawnhubStreamBonus > 0>> PrawnHub Bonus: +<<print _prawnhubStreamBonus>>% <</if>> </p> <p style="color: #CE93D8; margin: 10px 0 0 0; font-size: 18px; font-weight: bold;"> Extra Earnings: +$<<print Math.ceil($lastStreamResults.skillTreeBonus)>> </p> </div> <</if>> <!-- Crowd's Eye Notification --> <<if ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: linear-gradient(135deg, #a78bfa 0%, #7c3aed 100%); padding: 20px; border-radius: 12px; border: 3px solid #a78bfa; box-shadow: 0 0 20px rgba(167, 139, 250, 0.4); margin-bottom: 25px; text-align: center; animation: pulse-eye 2s infinite;"> <h2 style="color: white; margin: 0 0 10px 0;">👁️ The Crowd's Eye 👁️</h2> <p style="color: white; margin: 0; font-size: 16px; font-weight: bold;"> Your magnetic presence has doubled your follower gains! </p> </div> <style> @keyframes pulse-eye { 0%, 100% { box-shadow: 0 0 20px rgba(167, 139, 250, 0.4); } 50% { box-shadow: 0 0 30px rgba(167, 139, 250, 0.7); } } </style> <</if>> <!-- Pearl of Abundance Notification --> <<if $lastStreamResults.pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 20px; border-radius: 12px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); margin-bottom: 25px; text-align: center; animation: pulse-pearl 2s infinite;"> <h2 style="color: white; margin: 0 0 10px 0;">🐚 The Pearl of Abundance 🐚</h2> <p style="color: white; margin: 0; font-size: 16px; font-weight: bold;"> Your streaming earnings have been increased by 50%! </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Sexual XP Gained Event --> <<if $lastStreamResults.sexualXPGains && $lastStreamResults.sexualXPGains.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h2 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if $lastStreamResults.sexSkillXPBonus > 0>> <span style="color: #CE93D8;">⭐ +<<print $lastStreamResults.sexSkillXPBonus>></span> <</if>> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h2> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <<for _i, _xp range $lastStreamResults.sexualXPGains>> <span style="color: #ff69b4; font-weight: bold;"><<print _xp.skill>></span> <span style="color: #51cf66;">+<<print _xp.amount>> XP</span><<if _i < $lastStreamResults.sexualXPGains.length - 1>> | <</if>> <</for>> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- Summary Card --> <div style="background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%); padding: 30px; border-radius: 15px; border: 2px solid #ff1493; margin-bottom: 25px;"> <h2 style="color: #ff1493; text-align: center; margin-bottom: 25px;">Stream Complete!</h2> <!-- Stats Grid --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="background: #333; padding: 20px; border-radius: 10px; text-align: center; border: 2px solid #4ade80;"> <div style="color: #4ade80; font-size: 14px; margin-bottom: 8px;">💰 NET EARNINGS</div> <div style="color: white; font-size: 28px; font-weight: bold;">$<<print $lastStreamResults.netEarnings>></div> <div style="color: #aaa; font-size: 12px; margin-top: 5px;">(Deposited to bank)</div> </div> <div style="background: #333; padding: 20px; border-radius: 10px; text-align: center; border: 2px solid #ff69b4;"> <div style="color: #ff69b4; font-size: 14px; margin-bottom: 8px;">👥 PEAK VIEWERS</div> <div style="color: white; font-size: 28px; font-weight: bold;"><<print $lastStreamResults.peakViewers>></div> </div> <div style="background: #333; padding: 20px; border-radius: 10px; text-align: center; border: 2px solid #fbbf24;"> <div style="color: #fbbf24; font-size: 14px; margin-bottom: 8px;">📊 AVG ENGAGEMENT</div> <div style="color: white; font-size: 28px; font-weight: bold;"><<print Math.round($lastStreamResults.avgEngagement)>>%</div> </div> <div style="background: #333; padding: 20px; border-radius: 10px; text-align: center; border: 2px solid #60a5fa;"> <div style="color: #60a5fa; font-size: 14px; margin-bottom: 8px;">➕ NEW FOLLOWERS</div> <div style="color: white; font-size: 28px; font-weight: bold;">+<<print $lastStreamResults.newFollowersThisSession>></div> </div> </div> <!-- Earnings Breakdown --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 1px solid #444; margin-bottom: 20px;"> <h3 style="color: #f39c12; margin: 0 0 15px 0;">💰 Earnings Breakdown</h3> <div style="color: #aaa; line-height: 1.8;"> <p style="margin: 5px 0;"><strong>Gross Tips:</strong> <span style="color: #51cf66;">$<<print $lastStreamResults.grossEarnings>></span></p> <p style="margin: 5px 0;"><strong>Platform Cut (<<print Math.round($lastStreamResults.platformCutPercent * 100)>>%):</strong> <span style="color: #e74c3c;">-$<<print $lastStreamResults.platformCut>></span></p> <!-- ===== SKILL TREE: Show bonus in breakdown ===== --> <<if $lastStreamResults.skillTreeBonus > 0>> <p style="margin: 5px 0;"><strong>Skill Tree Bonus (+<<print $lastStreamResults.totalStreamingBonus>>%):</strong> <span style="color: #CE93D8;">+$<<print $lastStreamResults.skillTreeBonus>></span></p> <</if>> <<if $lastStreamResults.pearlActive>> <p style="margin: 5px 0;"><strong>Pearl Bonus (+50%):</strong> <span style="color: #7dd3fc;">+$<<print $lastStreamResults.pearlBonus>></span></p> <</if>> <<if setup.hasCrowdsEye()>><p style="margin: 5px 0;"><strong>👁️ The Crowd's Eye (2×):</strong> <span style="color: #b388ff;">+$<<print Math.floor($lastStreamResults.netEarnings / 2)>></span></p><</if>> <p style="margin: 5px 0; padding-top: 10px; border-top: 2px solid #444;"><strong>Net Earnings:</strong> <span style="color: #ffd43b; font-size: 18px;">$<<print $lastStreamResults.netEarnings>></span> <<if $lastStreamResults.pearlActive || $lastStreamResults.skillTreeBonus > 0>> <span style="color: <<if $lastStreamResults.pearlActive>>#7dd3fc<<else>>#CE93D8<</if>>; font-size: 14px;"> ✨</span> <</if>> </p> </div> <!-- Bank Deposit Notice --> <div style="background: #2a2a4a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #667eea;"> <p style="color: #667eea; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> 💳 All earnings deposited directly to your bank account </p> </div> <<set _hasAdultStreamerJob = $jobs && $jobs.includes("Adult Streamer")>> <<if !_hasAdultStreamerJob>> <div style="background: #3a2020; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #e74c3c;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px;"> ⚠️ <strong>High Platform Fee!</strong> Get the Adult Streamer job to reduce the platform cut from 70% to 30%. </p> </div> <</if>> </div> <!-- Actions Performed --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 1px solid #444;"> <h3 style="color: #ff69b4; margin-top: 0;">Actions Performed: <<print $lastStreamResults.totalActions>></h3> <div style="color: #aaa; line-height: 1.8;"> <<if $lastStreamResults.totalActions > 0>> <<for _i = 0; _i < $lastStreamResults.totalActions; _i++>> <<set _actionName = $lastStreamResults.actionsPerformed[_i]>> <<set _actionScore = $lastStreamResults.actionScores[_actionName] || 0>> <<set _displayName = _actionName.replace(/_/g, " ")>> <<set _scoreColor = _actionScore >= 85 ? "#FFD700" : (_actionScore >= 50 ? "#51cf66" : "#ff6b6b")>> <span style="background: #333; padding: 5px 10px; border-radius: 5px; margin: 3px; display: inline-block; border: 1px solid <<print _scoreColor>>;"> <<print _displayName>> <span style="color: <<print _scoreColor>>; font-size: 12px;">(<<print Math.round(_actionScore)>>)</span> </span> <</for>> <<else>> <span style="color: #666;">No actions performed</span> <</if>> </div> <<if $lastStreamResults.totalActions > 0>> <p style="color: #888; font-size: 13px; margin: 15px 0 0 0; font-style: italic;"> 💡 Scores of 85+ earn Sexual Expertise XP (requires Sexually Skilled trait) </p> <</if>> </div> </div> <!-- Career Progress --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 1px solid #ff69b4; margin-bottom: 25px;"> <h3 style="color: #ff69b4; margin-top: 0;">Career Stats</h3> <div style="color: #aaa;"> <p>💰 Total Career Earnings: <span style="color: #4ade80; font-weight: bold;">$<<print Math.ceil($prawnhubTotalEarnings)>></span></p> <p>👥 Total Followers: <span style="color: #ff69b4; font-weight: bold;"><<print ($prawnhubFollowers || 0).toLocaleString()>></span></p> <p>📹 Streams Today: <span style="color: #fbbf24; font-weight: bold;"><<print $prawnhubSessionsToday>> / <<print $prawnhubMaxSessions>></span></p> <p>🏦 Bank Balance: <span style="color: #667eea; font-weight: bold;"><<print setup.formatMoney($bankAccount.balance)>></span></p> <<set _hasAdultStreamerJob = $jobs && $jobs.includes("Adult Streamer")>> <<if _hasAdultStreamerJob>> <p>💼 Current Job: <span style="color: #27ae60; font-weight: bold;">Adult Streamer</span> (30% platform cut)</p> <<else>> <p>💼 Current Job: <span style="color: #e74c3c; font-weight: bold;"><<if $jobs && $jobs.length > 0>><<print $jobs.join(", ")>><<else>>Unemployed<</if>></span> (70% platform cut)</p> <</if>> </div> </div> </div> <!-- Navigation --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin: 0 10px;'>Back to Streaming</div>">> <<goto "PrawnHubStream">> <</link>> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin: 0 10px;'>Back to PrawnHub</div>">> <<goto "PrawnHub">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action02">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {dexterity: 20, strength: 20}>> <<set _positiveTraits = { positive: ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <<if !$action02Choice>> <<set $action02Choice = null>> <<set $action02Result = null>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 SIMULATE SEX: Use Handheld Prop</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 20>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 20 Required </div> <div class="stat-requirement <<if _effectiveStr >= 20>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 20 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action02Choice>> <div class="action-choice-container"> <<link "<div class='action-choice-btn'>🎮 Play Timing Game</div>">> <<set $action02Choice = "game">> <<goto "PrawnHub_Action02">> <</link>> <<link "<div class='action-choice-btn'>🎲 Roll d100</div>">> <<set $action02Choice = "roll">> <<set $action02Result = random(1, 100) + _bonus>> <<goto "PrawnHub_Action02">> <</link>> </div> <<elseif $action02Choice == "game" && !$action02Result>> <!-- Oscillating Bar Game --> <<set _meetsRequirements = _effectiveDex >= 20 && _effectiveStr >= 20>> <<set _traitCount = 0>> <<for _i = 0; _i < _positiveTraits.positive.length; _i++>> <<set _trait = _positiveTraits.positive[_i]>> <<if ($physicalTraits && $physicalTraits.includes(_trait)) || ($mentalTraits && $mentalTraits.includes(_trait)) || ($skills && $skills.includes(_trait))>> <<set _traitCount++>> <</if>> <</for>> <<set $barSpeed = _meetsRequirements ? Math.max(2.0, 3.0 - (_traitCount * 0.1)) : 10.0>> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; margin-bottom: 20px;">Click when the bar reaches the top! (3 attempts)</p> <p style="color: #aaa; font-size: 14px; margin-bottom: 20px;">Score 75+ on each attempt for maximum effect!</p> <!-- Inline styled game container --> <div id="oscillatingGame" style="width: 300px; max-width: 300px; height: 600px; position: relative; margin: 20px auto; cursor: pointer;"> <!-- Inner game area with background --> <div style="position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 150px; height: 400px; background: #2a2a2a; border: 2px solid #ff1493; border-radius: 8px;"></div> <!-- Track --> <div class="oscillating-track" style="position: absolute; left: 50%; top: 110px; bottom: 110px; width: 30px; background: #444; transform: translateX(-50%); border-radius: 15px;"></div> <!-- Fill Bar --> <div class="oscillating-fill" style="position: absolute; left: 50%; bottom: 110px; width: 30px; height: 0px; max-height: 380px; background: rgba(255, 255, 255, 0.9); transform: translateX(-50%); transition: height 0.3s ease; border-radius: 15px; z-index: 1;"></div> <!-- Target Zone --> <div class="target-zone" style="position: absolute; left: 50%; top: 110px; width: 30px; height: 50px; background: rgba(74, 222, 128, 0.3); transform: translateX(-50%); border: 2px solid #4ade80; border-radius: 15px 15px 0 0; z-index: 2;"></div> <!-- Moving Bar --> <div class="oscillating-bar" style="position: absolute; left: 50%; bottom: 110px; width: 30px; height: 40px; background: #e8a5bc; transform: translateX(-50%); box-shadow: 0 0 10px rgba(232, 165, 188, 0.7); border-radius: 20px; z-index: 3;"></div> <!-- Particle Container --> <div class="particle-container" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; z-index: 10;"></div> </div> </div> <<timed 100ms>> <<script>> setup.DEBUG && console.log("Timed script running!"); setup.DEBUG && console.log("initOscillatingBar function exists?", typeof initOscillatingBar); setup.DEBUG && console.log("Bar speed:", State.variables.barSpeed); if (typeof initOscillatingBar === 'function') { setup.DEBUG && console.log("Calling initOscillatingBar now..."); initOscillatingBar('oscillatingGame', State.variables.barSpeed, function(score) { setup.DEBUG && console.log("Callback received with score:", score); State.variables.action02Result = score; Engine.play(passage()); }); } else { console.error("initOscillatingBar function not found!"); } <</script>> <</timed>> <<else>> <!-- Show Result --> <<if $action02Choice == "roll">> <<set _success = $action02Result >= 50>> <<set _score = Math.min(100, $action02Result)>> <<else>> <<set _success = $action02Result >= 80>> <<set _score = $action02Result>> <</if>> <!-- Trophy Wife / Slut guaranteed prawnhub success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if _score < 50>><<set _score = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <<if $action02Choice == "roll">> <div style="color: #aaa; margin: 10px 0;"> d100 Roll: <<print $action02Result>> (Modified) </div> <</if>> <div class="result-score <<if !_success>>failure<</if>>"> <<print Math.round(_score)>> </div> <<if _success>> <<set _engagementGain = Math.floor(_score / 8)>> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <</if>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Excellent use of the toy! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((80 - _score) / 10)>> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <</if>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ A bit clumsy with the prop... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _viewers = $currentPrawnStream ? $currentPrawnStream.viewers : 0>> <<set _tipResult = calculatePrawnTips(_score, $prawnhubFollowers || 0, _viewers)>> <<set _followerGain = calculatePrawnFollowerGain(_score, $prawnhubFollowers || 0, _viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<if $currentPrawnStream>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <</if>> <!-- Store score for XP calculation --> <<if $currentPrawnStream && !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<if $currentPrawnStream>> <<set $currentPrawnStream.actionScores["SIMULATE_SEX"] = _score>> <</if>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer02" class="prawn-chat-container"></div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 10px; padding: 12px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 8px;"> <div style="color: #e040fb; font-weight: bold; margin-bottom: 8px;">🔥 Chat Erupts</div> <p style="color: #f3e5f5; margin: 0; font-size: 14px; line-height: 1.6;"><<print setup.getFutaFlavorText("audience_reaction")>></p> </div> <</if>> <<if (_tipResult && _tipResult.count > 0) || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult && _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = State.temporary.score || 0; var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'SIMULATE_SEX', viewers); window.displayPrawnChat('prawnChatContainer02', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "SIMULATE_SEX", message: "Simulating sex…" }>> <<set $currentPrawnStream.actionTimeLeft = 15>> <<set $currentPrawnStream.actionsPerformed.push("SIMULATE_SEX")>> <</if>> <<set $action02Choice = null>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action03">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {dexterity: 15, strength: 15}>> <<set _positiveTraits = { positive: ["Curvy", "Soft", "Smooth Skin", "Attractive", "Graceful", "Voluptuous", "Sexually Skilled", "Alluring", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <!-- Count positive traits for bar speed --> <<set _traitCount = 0>> <<if $traits>> <<for _trait range ["Curvy", "Soft", "Smooth Skin", "Attractive", "Graceful", "Voluptuous", "Sexually Skilled", "Alluring", "Seductive", "High Stamina"]>> <<if $traits[_trait]>> <<set _traitCount++>> <</if>> <</for>> <</if>> <<set _meetsRequirements = _effectiveDex >= 15 && _effectiveStr >= 15>> <<set $barSpeed = _meetsRequirements ? Math.max(2.0, 3.0 - (_traitCount * 0.1)) : 8.0>> <<if !$action03Choice>> <<set $action03Choice = null>> <<set $action03Result = null>> <<set $action03Scores = []>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 BREASTS CLAP: Upper Rhythm Display</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 15>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 15 Required </div> <div class="stat-requirement <<if _effectiveStr >= 15>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 15 Required </div> <div style="color: #aaa; margin-top: 10px;"> Positive Traits: <<print _traitCount>> (Bar Speed: <<print $barSpeed.toFixed(1)>>x) </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action03Choice>> <div class="action-choice-container"> <<link "<div class='action-choice-btn'>🎮 Play Rhythm Game (3 attempts)</div>">> <<set $action03Choice = "game">> <<goto "PrawnHub_Action03">> <</link>> <<link "<div class='action-choice-btn'>🎲 Roll d100</div>">> <<set $action03Choice = "roll">> <<set _rollResult = random(1, 100) + _bonus>> <<set $action03Result = {roll: random(1, 100), bonus: _bonus, total: _rollResult}>> <<goto "PrawnHub_Action03">> <</link>> </div> <<elseif $action03Choice == "game" && !$action03Result>> <!-- Moving Bar Game --> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; margin-bottom: 20px;"> Click when the bar is in the green zone! (3 attempts in one round) </p> <div id="movingBarGame" class="bar-game-container"> <div class="bar-track"></div> <div class="bar-indicator"></div> <div class="moving-bar"></div> </div> </div> <<timed 250ms>> <<script>> initMovingBar('movingBarGame', State.variables.barSpeed, function(avgScore) { State.variables.action03Result = {total: avgScore}; Engine.play(passage()); }); <</script>> <</timed>> <<else>> <!-- Show Result --> <<if $action03Choice == "roll">> <<set _score = $action03Result.total>> <<set _success = _score >= 50>> <<else>> <<set _score = $action03Result.total>> <<set _success = _score >= 50>> <</if>> <!-- Trophy Wife / Slut guaranteed clapping success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if _score < 50>><<set _score = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <<if $action03Choice == "roll">> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action03Result.roll>> + Bonus: <<print $action03Result.bonus>> </div> <<else>> <div style="color: #aaa; margin: 10px 0;"> Average Score from 3 attempts </div> <</if>> <div class="result-score <<if !_success>>failure<</if>>"> <<print Math.round(_score)>> </div> <<if _success>> <<set _engagementGain = Math.floor(_score / 6)>> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <</if>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Perfect rhythm! Viewers are captivated! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((50 - _score) / 8)>> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <</if>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ The rhythm was off... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips(_score, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain(_score, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["BREASTS_CLAP"] = _score>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer03" class="prawn-chat-container"></div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 10px; padding: 12px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 8px;"> <div style="color: #e040fb; font-weight: bold; margin-bottom: 8px;">🔥 Chat Erupts</div> <p style="color: #f3e5f5; margin: 0; font-size: 14px; line-height: 1.6;"><<print setup.getFutaFlavorText("audience_reaction")>></p> </div> <</if>> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = Math.round(State.temporary.score || 0); var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'BREASTS_CLAP', viewers); window.displayPrawnChat('prawnChatContainer03', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "BREASTS_CLAP", message: "Performing breast clapping motion!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("BREASTS_CLAP")>> <</if>> <<set $action03Choice = null>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action04">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {dexterity: 15, strength: 15}>> <<set _positiveTraits = { positive: ["Curvy", "Soft", "Smooth Skin", "Attractive", "Graceful", "Voluptuous", "Sexually Skilled", "Alluring", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <!-- Count positive traits for bar speed --> <<set _traitCount = 0>> <<if $traits>> <<for _trait range ["Curvy", "Soft", "Smooth Skin", "Attractive", "Graceful", "Voluptuous", "Sexually Skilled", "Alluring", "Seductive", "High Stamina"]>> <<if $traits[_trait]>> <<set _traitCount++>> <</if>> <</for>> <</if>> <<set _meetsRequirements = _effectiveDex >= 15 && _effectiveStr >= 15>> <<set $barSpeed = _meetsRequirements ? Math.max(2.0, 3.0 - (_traitCount * 0.1)) : 8.0>> <<set $action04Choice = $action04Choice || null>> <<set $action04Result = $action04Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 ASS CLAP: Lower Rhythm Display</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 15>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 15 Required </div> <div class="stat-requirement <<if _effectiveStr >= 15>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 15 Required </div> <div style="color: #aaa; margin-top: 10px;"> Positive Traits: <<print _traitCount>> (Bar Speed: <<print $barSpeed.toFixed(1)>>x) </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action04Choice>> <div class="action-choice-container"> <<link "<div class='action-choice-btn'>🎮 Play Rhythm Game (3 attempts)</div>">> <<set $action04Choice = "game">> <<goto "PrawnHub_Action04">> <</link>> <<link "<div class='action-choice-btn'>🎲 Roll d100</div>">> <<set $action04Choice = "roll">> <<set _rollValue = random(1, 100)>> <<set $action04Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<goto "PrawnHub_Action04">> <</link>> </div> <<elseif $action04Choice == "game" && !$action04Result>> <!-- Moving Bar Game --> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; margin-bottom: 20px;"> Click when the bar is in the green zone! (3 attempts in one round) </p> <div id="movingBarGame04" class="bar-game-container"> <div class="bar-track"></div> <div class="bar-indicator"></div> <div class="moving-bar"></div> </div> </div> <<timed 250ms>> <<script>> initMovingBar('movingBarGame04', State.variables.barSpeed, function(avgScore) { State.variables.action04Result = {total: avgScore}; Engine.play(passage()); }); <</script>> <</timed>> <<else>> <!-- Show Result --> <<if $action04Choice == "roll">> <<set _score = $action04Result.total>> <<set _success = _score >= 50>> <<else>> <<set _score = $action04Result.total>> <<set _success = _score >= 50>> <</if>> <!-- Trophy Wife / Slut guaranteed clapping success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if _score < 50>><<set _score = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <<if $action04Choice == "roll">> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action04Result.roll>> + Bonus: <<print $action04Result.bonus>> </div> <<else>> <div style="color: #aaa; margin: 10px 0;"> Average Score from 3 attempts </div> <</if>> <div class="result-score <<if !_success>>failure<</if>>"> <<print Math.round(_score)>> </div> <<if _success>> <<set _engagementGain = Math.floor(_score / 6)>> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <</if>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Amazing movement! Viewers can't look away! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((50 - _score) / 8)>> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <</if>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ The movement wasn't quite right... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips(_score, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain(_score, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["ASS_CLAP"] = _score>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer04" class="prawn-chat-container"></div> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = Math.round(State.temporary.score || 0); var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'ASS_CLAP', viewers); window.displayPrawnChat('prawnChatContainer04', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "ASS_CLAP", message: "Performing ass clapping motion!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("ASS_CLAP")>> <</if>> <<set $action04Choice = null>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action05">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {dexterity: 15, strength: 15}>> <<set _positiveTraits = { positive: ["Curvy", "Soft", "Smooth Skin", "Attractive", "Graceful", "Voluptuous", "Sexually Skilled", "Alluring", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <!-- Count positive traits for required score reduction --> <<set _traitCount = 0>> <<if $traits>> <<for _trait range ["Curvy", "Soft", "Smooth Skin", "Attractive", "Graceful", "Voluptuous", "Sexually Skilled", "Alluring", "Seductive", "High Stamina"]>> <<if $traits[_trait]>> <<set _traitCount++>> <</if>> <</for>> <</if>> <<set _requiredScore = Math.max(50, 80 - (_traitCount * 3))>> <<set $action05Choice = $action05Choice || null>> <<set $action05Result = $action05Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 ACTION_05: Upper Body Focus</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 15>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 15 Required </div> <div class="stat-requirement <<if _effectiveStr >= 15>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 15 Required </div> <div style="color: #aaa; margin-top: 10px;"> Positive Traits: <<print _traitCount>> (Required Score: <<print _requiredScore>>) </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action05Choice>> <div class="action-choice-container"> <<link "<div class='action-choice-btn'>🎨 Draw a Circle</div>">> <<set $action05Choice = "draw">> <<goto "PrawnHub_Action05">> <</link>> <<link "<div class='action-choice-btn'>🎲 Roll d100</div>">> <<set $action05Choice = "roll">> <<set _rollValue = random(1, 100)>> <<set $action05Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<goto "PrawnHub_Action05">> <</link>> </div> <<elseif $action05Choice == "draw" && !$action05Result>> <!-- Circle Drawing Game --> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; margin-bottom: 20px;"> Draw a smooth circle with your mouse! (Required Score: <<print _requiredScore>>) </p> <canvas id="circleCanvas" class="circle-canvas" width="400" height="400"></canvas> </div> <<timed 250ms>> <<script>> initCircleDrawing('circleCanvas', function(score) { State.variables.action05Result = {total: score}; Engine.play(passage()); }); <</script>> <</timed>> <<else>> <!-- Show Result --> <<if $action05Choice == "roll">> <<set _score = $action05Result.total>> <<else>> <<set _score = $action05Result.total>> <</if>> <<set _success = _score >= _requiredScore>> <!-- Trophy Wife / Slut guaranteed prawnhub success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if _score < _requiredScore>><<set _score = _requiredScore>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <<if $action05Choice == "roll">> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action05Result.roll>> + Bonus: <<print $action05Result.bonus>> </div> <<else>> <div style="color: #aaa; margin: 10px 0;"> Circle Quality Score </div> <</if>> <div class="result-score <<if !_success>>failure<</if>>"> <<print Math.round(_score)>> </div> <<if _success>> <<set _engagementGain = Math.floor(_score / 7)>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Beautiful movement! So graceful! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((_requiredScore - _score) / 10)>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ A bit shaky... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips(_score, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain(_score, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["MASSAGE_BREASTS"] = _score>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer05" class="prawn-chat-container"></div> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = Math.round(State.temporary.score || 0); var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'MASSAGE_BREASTS', viewers); window.displayPrawnChat('prawnChatContainer05', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "MASSAGE_BREASTS", message: "Sensually massaging and caressing breasts for viewers!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("MASSAGE_BREASTS")>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<set $action05Choice = null>> <<set $action05Result = null>> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action06">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {dexterity: 10, strength: 10}>> <<set _positiveTraits = { positive: ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <<set $action06Performed = $action06Performed || false>> <<set $action06Result = $action06Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 ACTION_06: Personal Expression Pose</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 10>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 10 Required </div> <div class="stat-requirement <<if _effectiveStr >= 10>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 10 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action06Performed>> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> Express yourself in your own unique way! </p> <<link "<div class='action-choice-btn'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $action06Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $action06Performed = true>> <<goto "PrawnHub_Action06">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $action06Result.total >= 50>> <!-- Trophy Wife / Slut guaranteed prawnhub success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if $action06Result.total < 50>><<set $action06Result.total = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action06Result.roll>> + Bonus: <<print $action06Result.bonus>> </div> <div class="result-score <<if !_success>>failure<</if>>"> <<print $action06Result.total>> </div> <<if _success>> <<set _engagementGain = Math.floor($action06Result.total / 7)>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Your personal touch is captivating! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((50 - $action06Result.total) / 8)>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ The expression felt forced... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips($action06Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain($action06Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["MASTURBATE"] = $action06Result.total>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer06" class="prawn-chat-container"></div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 10px; padding: 12px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 8px;"> <div style="color: #e040fb; font-weight: bold; margin-bottom: 8px;">🔥 Chat Erupts</div> <p style="color: #f3e5f5; margin: 0; font-size: 14px; line-height: 1.6;"><<print setup.getFutaFlavorText("prawnhub_chat")>></p> </div> <</if>> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = State.variables.action06Result ? State.variables.action06Result.total : 0; var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'MASTURBATE', viewers); window.displayPrawnChat('prawnChatContainer06', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "MASTURBATE", message: "Pleasuring myself intimately for the audience!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("MASTURBATE")>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<set $action06Performed = false>> <<set $action06Result = null>> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action07">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {strength: 20}>> <<set _positiveTraits = { positive: ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <<set $action07Performed = $action07Performed || false>> <<set $action07Result = $action07Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 ACTION_07: Prop Interaction</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveStr >= 20>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 20 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action07Performed>> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> Show the viewers how you handle your prop! </p> <<link "<div class='action-choice-btn'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $action07Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $action07Performed = true>> <<goto "PrawnHub_Action07">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $action07Result.total >= 50>> <!-- Trophy Wife / Slut guaranteed prawnhub success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if $action07Result.total < 50>><<set $action07Result.total = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action07Result.roll>> + Bonus: <<print $action07Result.bonus>> </div> <div class="result-score <<if !_success>>failure<</if>>"> <<print $action07Result.total>> </div> <<if _success>> <<set _engagementGain = Math.floor($action07Result.total / 6)>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Masterful prop work! Incredible! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((50 - $action07Result.total) / 7)>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ The prop handling was awkward... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips($action07Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain($action07Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["SIMULATE_ORAL"] = $action07Result.total>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer07" class="prawn-chat-container"></div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 10px; padding: 12px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 8px;"> <div style="color: #e040fb; font-weight: bold; margin-bottom: 8px;">🔥 Chat Erupts</div> <p style="color: #f3e5f5; margin: 0; font-size: 14px; line-height: 1.6;"><<print setup.getFutaFlavorText("prawnhub_chat")>></p> </div> <</if>> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = State.variables.action07Result ? State.variables.action07Result.total : 0; var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'SIMULATE_ORAL', viewers); window.displayPrawnChat('prawnChatContainer07', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "SIMULATE_ORAL", message: "Demonstrating skilled oral techniques with prop!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("SIMULATE_ORAL")>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<set $action07Performed = false>> <<set $action07Result = null>> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action08">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {charisma: 30}>> <<set _positiveTraits = { positive: ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set $action08Performed = $action08Performed || false>> <<set $action08Result = $action08Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 ACTION_08: Front Presentation</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveCha >= 30>>met<<else>>not-met<</if>>"> Charisma: <<print _effectiveCha>> / 30 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action08Performed>> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> Face the camera and show your charm! </p> <<link "<div class='action-choice-btn'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $action08Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $action08Performed = true>> <<goto "PrawnHub_Action08">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $action08Result.total >= 50>> <!-- Trophy Wife / Slut guaranteed prawnhub success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if $action08Result.total < 50>><<set $action08Result.total = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action08Result.roll>> + Bonus: <<print $action08Result.bonus>> </div> <div class="result-score <<if !_success>>failure<</if>>"> <<print $action08Result.total>> </div> <<if _success>> <<set _engagementGain = Math.floor($action08Result.total / 8)>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Your charisma shines through! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((50 - $action08Result.total) / 10)>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ You seemed a bit stiff... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips($action08Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain($action08Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["POSE_NUDE"] = $action08Result.total>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer08" class="prawn-chat-container"></div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 10px; padding: 12px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 8px;"> <div style="color: #e040fb; font-weight: bold; margin-bottom: 8px;">🔥 Chat Erupts</div> <p style="color: #f3e5f5; margin: 0; font-size: 14px; line-height: 1.6;"><<print setup.getFutaFlavorText("performance_reveal")>></p> </div> <</if>> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = State.variables.action08Result ? State.variables.action08Result.total : 0; var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'POSE_NUDE', viewers); window.displayPrawnChat('prawnChatContainer08', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "POSE_NUDE", message: "Displaying nude body in provocative poses!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("POSE_NUDE")>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<set $action08Performed = false>> <<set $action08Result = null>> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action11">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {charisma: 10, dexterity: 10, strength: 10}>> <!-- Check for all voice traits --> <<set _voiceBonus = 0>> <<if $traits>> <!-- Positive voice traits --> <<if $traits["Smooth Voice"]>><<set _voiceBonus += 5>><</if>> <<if $traits["Deep Voice"]>><<set _voiceBonus += 5>><</if>> <<if $traits["Melodic Voice"]>><<set _voiceBonus += 5>><</if>> <<if $traits["Sultry Voice"]>><<set _voiceBonus += 7>><</if>> <<if $traits["Commanding Voice"]>><<set _voiceBonus += 5>><</if>> <!-- Negative voice traits --> <<if $traits["Raspy Voice"]>><<set _voiceBonus -= 5>><</if>> <<if $traits["Nasally Voice"]>><<set _voiceBonus -= 5>><</if>> <<if $traits["Squeaky Voice"]>><<set _voiceBonus -= 5>><</if>> <<if $traits["Monotone Voice"]>><<set _voiceBonus -= 5>><</if>> <</if>> <<set _positiveTraits = { positive: ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits) + _voiceBonus>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <<set $action11Performed = $action11Performed || false>> <<set $action11Result = $action11Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 ACTION_11: Voice + Movement Combo</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if $stats.charisma >= 10>>met<<else>>not-met<</if>>"> Charisma: <<print $stats.charisma>> / 10 Required </div> <div class="stat-requirement <<if _effectiveDex >= 10>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 10 Required </div> <div class="stat-requirement <<if _effectiveStr >= 10>>met<<else>>not-met<</if>>"> Strength: <<print _effectiveStr>> / 10 Required </div> <<if _voiceBonus != 0>> <div style="color: <<if _voiceBonus > 0>>#4ade80<<else>>#ff6b6b<</if>>; margin-top: 10px;"> Voice Traits: <<if _voiceBonus > 0>>+<</if>><<print _voiceBonus>> </div> <</if>> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action11Performed>> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> Combine your voice and movement for maximum effect! </p> <<link "<div class='action-choice-btn'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $action11Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $action11Performed = true>> <<goto "PrawnHub_Action11">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $action11Result.total >= 50>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action11Result.roll>> + Bonus: <<print $action11Result.bonus>> </div> <div class="result-score <<if !_success>>failure<</if>>"> <<print $action11Result.total>> </div> <<if _success>> <<set _engagementGain = Math.floor($action11Result.total / 5)>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ The perfect combination! Viewers are mesmerized! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% </div> <<else>> <<set _engagementLoss = Math.floor((50 - $action11Result.total) / 8)>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ The coordination was off... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips($action11Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain($action11Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["MOAN"] = $action11Result.total>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer11" class="prawn-chat-container"></div> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = State.variables.action11Result ? State.variables.action11Result.total : 0; var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'MOAN', viewers); window.displayPrawnChat('prawnChatContainer11', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<if $currentPrawnStream>> <<set $currentPrawnStream.currentAction = { id: "MOAN", message: "Moaning seductively with sensual movements!" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("MOAN")>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<set $action11Performed = false>> <<set $action11Result = null>> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PrawnHub_Action01">> <!-- Calculate bonus/penalty --> <<set _requiredStats = {dexterity: 30}>> <<set _positiveTraits = { positive: ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"] }>> <<set _bonus = calculateActionBonus(_requiredStats, _positiveTraits)>> <!-- Calculate effective dexterity for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set $action01Performed = $action01Performed || false>> <<set $action01Result = $action01Result || null>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 STRIP CLOTHING: Change Outfit State</h1> <!-- Stat Check Display --> <div class="stat-check-display"> <h3 style="color: #fbbf24; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 30>>met<<else>>not-met<</if>>"> Dexterity: <<print _effectiveDex>> / 30 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice --> <<if !$action01Performed>> <div style="text-align: center; margin: 30px 0;"> <p style="color: #ccc; font-size: 16px; margin-bottom: 20px;"> Time to change your outfit and show the viewers something new! </p> <<link "<div class='action-choice-btn'>🎲 Roll Performance Check (d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $action01Result = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $action01Performed = true>> <<goto "PrawnHub_Action01">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $action01Result.total >= 50>> <!-- Trophy Wife / Slut guaranteed prawnhub success --> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <<set _success = true>> <<if $action01Result.total < 50>><<set $action01Result.total = 50>><</if>> <</if>> <div class="result-display <<if !_success>>failure<</if>>"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <<if $physicalTraits.includes("Trophy Wife") || $physicalTraits.includes("Slut")>> <div style="color: #51cf66; font-size: 14px; margin: 5px 0;">✓ <<if $physicalTraits.includes("Trophy Wife")>>Trophy Wife<<else>>Slut<</if>>: Guaranteed Success</div> <</if>> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $action01Result.roll>> + Bonus: <<print $action01Result.bonus>> </div> <div class="result-score <<if !_success>>failure<</if>>"> <<print $action01Result.total>> </div> <<if _success>> <<set _engagementGain = Math.floor($action01Result.total / 10)>> <<set _earningsMultiplier = 1 + ($action01Result.total / 200)>> <<set $currentPrawnStream.currentEngagement = Math.min(100, $currentPrawnStream.currentEngagement + _engagementGain)>> <div style="color: #4ade80; font-size: 18px; margin: 15px 0;"> ✓ Success! The viewers love your new look! </div> <div style="color: #aaa;"> Engagement +<<print _engagementGain>>% | Earning Multiplier: x<<print _earningsMultiplier.toFixed(2)>> </div> <<else>> <<set _engagementLoss = Math.floor((50 - $action01Result.total) / 5)>> <<set $currentPrawnStream.currentEngagement = Math.max(0, $currentPrawnStream.currentEngagement - _engagementLoss)>> <div style="color: #ff6b6b; font-size: 18px; margin: 15px 0;"> ⚠ The outfit change was awkward... </div> <div style="color: #aaa;"> Engagement -<<print _engagementLoss>>% </div> <</if>> </div> <!-- Calculate tips and follower gain --> <<set _tipResult = calculatePrawnTips($action01Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<set _followerGain = calculatePrawnFollowerGain($action01Result.total, $prawnhubFollowers || 0, $currentPrawnStream.viewers)>> <<if $physicalTraits.includes("E-Girl")>><<set _followerGain = _followerGain * 2>><</if>> <<if $physicalTraits.includes("Gyaru")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>><<set _followerGain = Math.floor(_followerGain * 1.25)>><</if>> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>><<set _followerGain = Math.floor(_followerGain * 1.5)>><</if>> <<set $prawnhubFollowers = ($prawnhubFollowers || 0) + _followerGain>> <<set $currentPrawnStream.earnings += _tipResult.amount>> <!-- Store score for XP calculation --> <<if !$currentPrawnStream.actionScores>> <<set $currentPrawnStream.actionScores = {}>> <</if>> <<set $currentPrawnStream.actionScores["STRIP_CLOTHING"] = $action01Result.total>> <!-- Viewer Response --> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; margin: 20px 0;"> <div style="color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; font-weight: bold; margin-bottom: 15px; font-size: 18px;">💬 Live Chat</div> <div id="prawnChatContainer" class="prawn-chat-container"></div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 10px; padding: 12px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 8px;"> <div style="color: #e040fb; font-weight: bold; margin-bottom: 8px;">🔥 Chat Erupts</div> <p style="color: #f3e5f5; margin: 0; font-size: 14px; line-height: 1.6;"><<print setup.getFutaFlavorText("performance_reveal")>></p> </div> <</if>> <<if _tipResult.count > 0 || _followerGain > 0>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #333;"> <<if _tipResult.count > 0>> <div style="color: #fbbf24; font-size: 16px; margin: 5px 0;"> 💰 +$<<print _tipResult.amount>> in tips! (<<print _tipResult.count>> viewers tipped) </div> <</if>> <<if _followerGain > 0>> <div style="color: #a78bfa; font-size: 16px; margin: 5px 0;"> ⭐ +<<print _followerGain>> new followers! <<if $physicalTraits.includes("E-Girl")>><span style="color: #ff69b4;"> (✓ E-Girl 2x)</span><</if>> <<if $physicalTraits.includes("Gyaru")>><span style="color: #fbbf24;"> (✓ Gyaru 1.5x)</span><</if>> </div> <</if>> </div> <</if>> </div> <<timed 100ms>> <<script>> var score = State.variables.action01Result ? State.variables.action01Result.total : 0; var viewers = State.variables.currentPrawnStream ? State.variables.currentPrawnStream.viewers : 0; var messages = window.generatePrawnChat(score, 'STRIP_CLOTHING', viewers); window.displayPrawnChat('prawnChatContainer', messages); <</script>> <</timed>> <!-- Set action and advance time --> <<set $currentPrawnStream.currentAction = { id: "STRIP_CLOTHING", message: "Stripping clothing…" }>> <<set $currentPrawnStream.actionTimeLeft = 30>> <<set $currentPrawnStream.actionsPerformed.push("STRIP_CLOTHING")>> <<set $action01Performed = false>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue Streaming</div>">> <<goto "PrawnHubLiveStream">> <</link>> </div> <</if>> </div> <</nobr>>
<<script>> /* Prawn Chat Usernames with colors */ window.prawnChatUsers = [ {name: "HornyHousewife88", color: "#ff69b4"}, {name: "OneHandDad69", color: "#4169e1"}, {name: "CuriousBiWife", color: "#ff1493"}, {name: "BrokeButStroking", color: "#32cd32"}, {name: "MilfLovesYoungCock", color: "#ff4500"}, {name: "WifeAsleepAgain", color: "#9370db"}, {name: "TouchingMyselfQuietly", color: "#ff69b4"}, {name: "SilentLurkerXX", color: "#808080"}, {name: "HubbyDoesntKnow99", color: "#ff1493"}, {name: "JustHereForGirls", color: "#da70d6"}, {name: "SneakyMomOf3", color: "#ff6347"}, {name: "EdgingInBedroom", color: "#4682b4"}, {name: "ShowFeetPrettyPls", color: "#ffa500"}, {name: "MarriedButBiCurious", color: "#ba55d3"}, {name: "CantCumButWet", color: "#ff69b4"}, {name: "OneHandTypingF", color: "#ff1493"}, {name: "HotelRoomHorny", color: "#4169e1"}, {name: "MoanForMeBaby", color: "#ff4500"}, {name: "ParentsDownstairs24F", color: "#ff69b4"}, {name: "FreeUserFapperM", color: "#696969"}, {name: "WatchingWithHubby", color: "#9370db"}, {name: "PmMeYourPussy", color: "#ff1493"}, {name: "InBathroomAtWorkF", color: "#ff6347"}, {name: "GirlfriendAsleepNextToMe", color: "#4682b4"}, {name: "TouchingUnderBlanket", color: "#ff69b4"}, {name: "BiWifeWatchingAlone", color: "#da70d6"}, {name: "OnTheToiletStroking", color: "#32cd32"}, {name: "HornyAndBoredWife", color: "#ff1493"}, {name: "ShowAssholeQueen", color: "#ff4500"}, {name: "LurkingWithVibrator", color: "#ff69b4"}, {name: "SneakyCollegeGirl", color: "#ff1493"}, {name: "WifeThinksImSleeping", color: "#4169e1"}, {name: "FingeringInDark", color: "#9370db"}, {name: "CuriousStraightGirl", color: "#ff69b4"}, {name: "EarbudsInMaxF", color: "#ff6347"}, {name: "JustWokeUpHardM", color: "#4682b4"}, {name: "PmYourSnapPretty", color: "#ff1493"}, {name: "CoupleLookingForGirl", color: "#ba55d3"}, {name: "Volume0Vibes100F", color: "#ff69b4"}, {name: "CantCumYetEdging", color: "#4169e1"}, {name: "MomMightWalkInM", color: "#32cd32"}, {name: "SecretlyBiHubby", color: "#4682b4"}, {name: "TouchingMyselfToYou", color: "#ff69b4"}, {name: "InCarWaitingForKids", color: "#ff1493"}, {name: "HornyStepMomVibes", color: "#ff4500"}, {name: "OneHandChallengeM", color: "#4169e1"}, {name: "WatchingWithGFAsleep", color: "#9370db"}, {name: "FreeAccountGangM", color: "#696969"}, {name: "BiGirlLovesTits", color: "#da70d6"}, {name: "HotelWifiWanker", color: "#4682b4"}, {name: "SneakyWifeTouching", color: "#ff69b4"}, {name: "CuriousAboutGirls19", color: "#ff1493"}, {name: "RoommateInNextRoomM", color: "#32cd32"}, {name: "FingeringToYourVoice", color: "#ff69b4"}, {name: "BrokeButLoyalM", color: "#696969"}, {name: "MarriedButWatchingF", color: "#ff6347"}, {name: "ShowToesOrBye", color: "#ffa500"}, {name: "CoupleLookingForUnicorn", color: "#ba55d3"}, {name: "OnCompanyWifiM", color: "#4682b4"}, {name: "HornyAndSingleMom", color: "#ff1493"}, {name: "TypingWithLeftHandM", color: "#4169e1"}, {name: "BiWifePmMe", color: "#da70d6"}, {name: "BananaBananaBananaBanana", color: "#f0f24e"}, {name: "SilentButSoaked", color: "#9370db"}, {name: "InPublicLibraryM", color: "#32cd32"}, {name: "PillowOverFaceF", color: "#ff69b4"}, {name: "CouplePmUs", color: "#ba55d3"}, {name: "EarbudsSavingMeM", color: "#4682b4"}, {name: "SneakyMasturbatorF", color: "#ff69b4"}, {name: "JustAnotherLurkerM", color: "#808080"}, {name: "HornyTeacherAfterClass", color: "#ff1493"}, {name: "WatchingWithBoyfriend", color: "#9370db"}, {name: "NormalGuy", color: "#696969"}, {name: "BiAndBoredTonight", color: "#da70d6"}, {name: "5MinTillHubbyHome", color: "#ff4500"}, {name: "LurkingHardM", color: "#4169e1"}, {name: "TouchingInBedF", color: "#ff69b4"}, {name: "CantCumButHardM", color: "#4682b4"}, {name: "CuriousLesbianFirstTime", color: "#ff1493"}, {name: "OnMomsPhoneM", color: "#32cd32"}, {name: "WifeWatchingWithMe", color: "#9370db"}, {name: "SneakyVibesOn", color: "#ff69b4"}, {name: "InTheDarkStrokingM", color: "#4169e1"}, {name: "HornyAndNeglectedWife", color: "#ff1493"}, {name: "ShowBobsPlsM", color: "#ffa500"}, {name: "BiGirlInLingerie", color: "#da70d6"}, {name: "HeadphonesInClassF", color: "#ff69b4"}, {name: "OneHandLegendM", color: "#4682b4"}, {name: "WatchingWhileHeSleeps", color: "#ff6347"}, {name: "FreeUserEnergyM", color: "#696969"}, {name: "SecretlyWatchingGirls", color: "#9370db"}, {name: "VibratorOnLow", color: "#ff69b4"}, {name: "MarriedButCuriousF", color: "#ff1493"}, {name: "LurkerSince2019M", color: "#808080"}, {name: "SneakyClitRubs", color: "#ff69b4"}, {name: "CantTalkTypingM", color: "#4682b4"}, {name: "HornyAuntieVibes", color: "#ff4500"}, {name: "BiWifeNeedsFriends", color: "#da70d6"}, {name: "OnLunchBreakFapM", color: "#32cd32"}, {name: "TouchingToYourCam", color: "#ff69b4"}, {name: "BrokeCollegeGirlWet", color: "#ff1493"}, {name: "SilentStrokerM", color: "#808080"}, {name: "WatchingWithWife", color: "#9370db"}, {name: "CuriousAndSingleF", color: "#ff69b4"}, {name: "EarbudsInBedM", color: "#4682b4"}, {name: "PillowHumpingTonight", color: "#ff1493"}, {name: "HornyAndHomeAloneF", color: "#ff69b4"}, {name: "FreeLoaderGang", color: "#696969"}, {name: "CoupleWatchingTogether", color: "#ba55d3"}, {name: "SneakyFingerInPanties", color: "#ff69b4"}, {name: "BiAndTipsyTonight", color: "#da70d6"}, {name: "OneHandedViewerM", color: "#4169e1"}, {name: "WatchingOnSilentF", color: "#ff69b4"}, {name: "CantCumButThrobM", color: "#4682b4"}, {name: "HornyMilfNextDoor", color: "#ff1493"}, {name: "CoupleLookingForFun", color: "#ba55d3"}, {name: "LurkingWithToy", color: "#9370db"}, {name: "InBedWithHeadphonesF", color: "#ff69b4"}, {name: "SecretBiHubby", color: "#4682b4"}, {name: "TouchingMyselfSoftly", color: "#ff69b4"}, {name: "CuriousFirstTimerF", color: "#ff1493"}, {name: "OnTheBusHornyM", color: "#32cd32"}, {name: "WifeDoesntKnowIFap", color: "#4169e1"}, {name: "VibratorUnderBlanket", color: "#ff69b4"}, {name: "FreeUserButWet", color: "#696969"}, {name: "CoupleWatchingHot", color: "#ba55d3"}, {name: "JustAnotherHornySoul", color: "#9370db"}, {name: "SneakyOfficeWankM", color: "#4682b4"}, {name: "BiGirlCravingAttention", color: "#da70d6"}, {name: "WatchingFromWorkF", color: "#ff69b4"}, {name: "MomHomeAloneHorny", color: "#ff1493"}, {name: "OneHandBathroomBreak", color: "#4169e1"}, {name: "CuriousNeighborGirl", color: "#ff69b4"}, {name: "HusbandAsleepWatching", color: "#9370db"}, {name: "FingeringInShowerF", color: "#ff69b4"}, {name: "BrokeStudentStroking", color: "#696969"}, {name: "LurkingInShadowsM", color: "#808080"}, {name: "TouchingToYourMoans", color: "#ff69b4"}, {name: "MarriedCoupleCurious", color: "#ba55d3"}, {name: "SilentVibeSessionF", color: "#9370db"}, {name: "OnBreakAtGymHorny", color: "#32cd32"}, {name: "WifeWatchingSecretly", color: "#ff1493"}, {name: "BiAndHornyTonight", color: "#da70d6"}, {name: "PillowRidingHard", color: "#ff69b4"}, {name: "FreeViewerForeverM", color: "#696969"}, {name: "SneakySisterVibes", color: "#ff69b4"}, {name: "EarbudsInPublicF", color: "#ff69b4"}, {name: "CantStopStrokingM", color: "#4682b4"}, {name: "HornyAndBoredMom", color: "#ff1493"}, {name: "CoupleGoalWatchers", color: "#ba55d3"} ]; /* Chat messages organized by action and score tier */ window.prawnChatMessages = { STRIP_CLOTHING: { tier1: [ /* 95+ */ "omg yesss", "fuck ur so good at this", "im so hard rn", "best strip ive ever seen", "holy shit dont stop", "FUCK YES", "im gonna cum watching", "this is perfect", "god damn that tease", "ur making me so wet", "i need more", "so fucking sexy", "youre incredible", "best stripper on here", "cant stop watching", "holy fuck yes", "take it all off baby", "so hot baby", "dont fucking stop", "i wish i was there", "fucking perfect body", "best strip ever", "im edging so hard", "need to see everything", "god yes strip for me", "so good at teasing", "making me throb", "cant handle this", "stroking so hard rn", "youre a goddess", "im so turned on", "fuck me please", "please show more", "best tease ever", "losing my mind", "so fucking hot", "im about to finish", "that body is perfect", "cant look away", "god tier stripper", "soaking wet watching", "touching myself hard", "need you naked", "im obsessed", "fuck that tease", "youre driving me crazy", "best show tonight", "take it off slow", "im gonna explode", "such a good tease", "youre so sexy", "loving every second" ], tier2: [ /* 85-94 */ "so fucking hot", "god i wish i was there", "youre amazing", "fuck keep going", "im so turned on", "damn thats hot", "really good strip", "love watching this", "youre doing great", "god damn that reveal", "perfect tease", "i need more of this", "incredible tease", "so sexy baby", "cant get enough", "youre so skilled at this", "this is hot af", "love your body", "making me hard", "so beautiful", "youre perfect", "damn baby", "im getting close", "love the slow reveal", "so good rn", "youre a natural stripper", "fuck thats nice", "such a tease", "im here for this", "youre gorgeous", "love every curve", "so talented", "this is amazing", "youre killing it", "im hooked", "need more strips like this", "damn youre good", "loving every second", "youre so hot", "fuck yes baby", "great tease", "love the confidence", "youre stunning", "cant wait to see more" ], tier3: [ /* 70-84 */ "nice strip", "looking good", "pretty hot", "keep going", "love it", "really good", "great moves", "not bad at all", "youre hot", "nice work", "great tease", "enjoying this", "looks great", "very nice strip", "good stuff", "keep it up", "doing well", "hot strip", "nice reveal", "pretty sexy", "good performance", "liking this", "solid strip", "looking sexy", "nice job", "decent strip", "enjoying the view", "not bad", "pretty good tease", "this is nice", "good work", "looks hot", "doing good", "nice body" ], tier4: [ /* 50-69 */ "decent effort", "its alright", "could be better", "okay i guess", "not bad", "pretty good", "decent strip", "alright", "okay tease", "its fine", "not terrible", "average strip", "meh its okay", "decent", "could be hotter", "needs work but ok", "fine i guess", "eh alright" ], tier5: [ /* 35-49 */ "bit awkward ngl", "maybe try again?", "youll get it", "keep practicing", "timing was off", "almost had it", "keep trying", "youll improve", "not quite there", "needs work", "bit rough", "try again", "almost", "needs improvement", "practice the tease more", "getting there", "awkward strip", "could be smoother", "keep working on it", "not your best" ], tier6: [ /* <35 */ "lol wat", "u ok?", "that was bad lmao", "bruh...", "yikes", "wtf was that strip", "lmaooo", "bruh really?", "nah this aint it", "💀💀💀", "lol so awkward", "bruh that was ass", "💀", "cant even strip lmao", "yikes dude", "lmaooo wtf", "nah fam", "what even is that", "lmao nah", "so stiff", "bruh those moves 💀", "nah this cringe", "lol no", "awkward af", "oof", "this aint it chief", "💀💀", "yikes bro", "lmaoooo", "wtf was that" ] }, SIMULATE_SEX: { tier1: [ /* 95+ */ "FUCK YES", "im gonna cum", "holy shit this is perfect", "best ive ever seen", "dont fucking stop", "omg that rhythm", "im cumming watching this", "so fucking hot", "god i wish that was me", "ride it baby", "fuck yes like that", "im so hard rn", "best simulation ever", "youre amazing at this", "fuck keep going", "im about to finish", "that looks so real", "god damn", "im stroking so hard", "cant handle this", "youre incredible", "im losing it", "so turned on rn", "dont stop baby", "fuck that toy", "perfect rhythm", "im edging hard", "need to see more", "god yes faster", "youre so good", "making me throb", "this is everything", "im gonna explode", "best ride ever", "holy fuck", "youre a pro", "soaking wet watching", "touching myself hard", "need you so bad", "im obsessed", "fuck me like that", "youre driving me wild", "best show tonight", "go deeper baby", "im cumming with you", "such good technique", "youre so sexy", "loving every thrust", "harder baby", "fuck yes that angle", "youre perfect", "im gonna lose it" ], tier2: [ /* 85-94 */ "so fucking hot", "god that looks good", "youre amazing", "fuck keep riding", "im so turned on", "damn thats hot", "really good", "love watching this", "youre doing great", "god damn that motion", "perfect technique", "i need more", "incredible", "so sexy baby", "cant get enough", "youre so skilled", "this is hot af", "love your rhythm", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love every movement", "so good rn", "youre a natural", "fuck thats nice", "great simulation", "im here for it", "youre gorgeous", "love your moves", "so talented", "this is amazing", "youre killing it", "im hooked", "need more of this", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great technique", "love the speed", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "nice rhythm", "looking good", "pretty hot", "keep going", "love it", "really good", "great moves", "not bad at all", "youre hot", "nice work", "great show", "enjoying this", "looks great", "very nice", "good stuff", "keep it up", "doing well", "hot show", "nice technique", "pretty sexy", "good performance", "liking this", "solid show", "looking sexy", "nice job", "decent show", "enjoying the view", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice motion" ], tier4: [ /* 50-69 */ "decent effort", "its alright", "could be better", "okay i guess", "not bad", "pretty good", "decent show", "alright", "okay", "its fine", "not terrible", "average show", "meh its okay", "decent", "could be hotter", "needs work but ok", "fine i guess", "eh alright" ], tier5: [ /* 35-49 */ "bit awkward ngl", "maybe try again?", "youll get it", "keep practicing", "rhythm was off", "almost had it", "keep trying", "youll improve", "not quite there", "needs work", "bit rough", "try again", "almost", "needs improvement", "practice more", "getting there", "off rhythm", "could be smoother", "keep working on it", "not your best" ], tier6: [ /* <35 */ "wtf was that", "lmaooo", "bruh really?", "nah this aint it", "💀💀💀", "lol so fake", "bruh that was ass", "💀", "cant even lmao", "yikes dude", "lmaooo wtf", "nah fam", "what even is that", "lmao nah", "so awkward", "bruh those moves 💀", "nah this cringe", "lol no", "looks fake af", "oof", "this aint it chief", "💀💀", "yikes bro", "lmaoooo", "wtf" ] }, BREASTS_CLAP: { tier1: [ /* 95+ */ "FUCK those tits", "im so hard watching this", "best clapping ever", "holy shit yes", "dont stop baby", "omg that bounce", "im cumming", "so fucking hot", "god damn those tits", "perfect rhythm", "fuck yes", "im stroking to this", "best tits on here", "youre incredible", "cant stop watching", "im about to cum", "that bounce is perfect", "god yes", "im so hard rn", "this is amazing", "youre a goddess", "im losing it", "so turned on", "dont fucking stop", "clap those tits baby", "hypnotizing", "im edging hard", "need more", "god those are perfect", "youre so good", "making me throb", "cant handle this", "im gonna explode", "best bounce ever", "holy fuck", "youre perfect", "soaking wet watching", "touching to this", "need to see more", "im obsessed", "fuck i love your tits", "youre driving me crazy", "best show", "keep bouncing", "im cumming with you", "such perfect tits", "youre so sexy", "loving every clap", "bounce harder", "fuck yes that jiggle", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "god damn those moves", "so fucking hot", "perfect rhythm", "i need more of this", "youre incredible", "damn thats hot", "really good clapping", "love watching", "youre doing great", "god damn that bounce", "perfect technique", "cant get enough", "this is hot af", "love your tits", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love the bounce", "so good rn", "youre a natural", "fuck thats nice", "great clapping", "im here for it", "youre gorgeous", "love the jiggle", "so talented", "this is amazing", "youre killing it", "im hooked", "need more shows", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great rhythm", "love the speed", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "nice rhythm", "looking good", "pretty hot", "keep going", "love it", "really good", "great clapping", "not bad at all", "nice tits", "nice work", "great bounce", "enjoying this", "looks great", "very nice", "good stuff", "keep it up", "doing well", "hot", "nice technique", "pretty sexy", "good show", "liking this", "solid clapping", "looking sexy", "nice job", "decent show", "enjoying the view", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice bounce" ], tier4: [ /* 50-69 */ "decent effort", "its alright", "could be better", "okay i guess", "not bad", "pretty good", "decent clapping", "alright", "okay", "its fine", "not terrible", "average", "meh its okay", "decent", "could be hotter", "needs work but ok", "fine i guess", "eh alright" ], tier5: [ /* 35-49 */ "timing was off", "almost had it", "keep trying", "youll get it", "rhythm off", "almost", "keep practicing", "youll improve", "not quite there", "needs work", "bit rough", "try again", "off timing", "needs improvement", "practice more", "getting there" ], tier6: [ /* <35 */ "lol no rhythm", "bruh that was ass", "💀", "cant even clap lmao", "yikes dude", "lmaooo wtf", "bruh...", "that aint it", "💀💀", "nah fam", "lol what", "so awkward", "💀", "bruh really", "yikes", "cant even lol", "nah this aint it", "lmao nah", "awkward af", "oof" ] }, ASS_CLAP: { tier1: [ /* 95+ */ "THAT ASS FUCK", "im gonna lose it", "best ass clapping ever", "holy shit yes", "dont stop please", "omg that ass", "im cumming", "so fucking hot", "god damn that ass", "perfect clapping", "fuck yes", "im stroking hard", "best ass on here", "youre incredible", "cant stop watching", "im about to cum", "that jiggle is perfect", "god yes", "im so hard rn", "this is amazing", "youre a goddess", "im losing it", "so turned on", "dont fucking stop", "clap that ass baby", "hypnotizing", "im edging hard", "need more", "god that ass is perfect", "youre so good", "making me throb", "cant handle this", "im gonna explode", "best ass ever", "holy fuck", "youre perfect", "soaking wet watching", "touching to this", "need to see more", "im obsessed", "fuck i love your ass", "youre driving me crazy", "best show", "keep clapping", "im cumming with you", "such a perfect ass", "youre so sexy", "loving every clap", "clap harder", "fuck yes that bounce", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "god damn that ass", "so fucking hot", "perfect clapping", "i cant handle this", "youre amazing", "damn thats hot", "really good", "love watching", "youre doing great", "god damn that bounce", "perfect technique", "cant get enough", "this is hot af", "love your ass", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love the jiggle", "so good rn", "youre a natural", "fuck thats nice", "great clapping", "im here for it", "youre gorgeous", "love that ass", "so talented", "this is amazing", "youre killing it", "im hooked", "need more shows", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great rhythm", "love the bounce", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "nice clapping", "great moves", "really hot", "keep it up", "love it", "really good", "great ass", "not bad at all", "nice", "nice work", "great bounce", "enjoying this", "looks great", "very nice", "good stuff", "keep going", "doing well", "hot", "nice technique", "pretty sexy", "good show", "liking this", "solid clapping", "looking sexy", "nice job", "decent show", "enjoying the view", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice jiggle" ], tier4: [ /* 50-69 */ "decent show", "not bad", "its okay", "alright", "pretty good", "decent clapping", "fine", "okay i guess", "its fine", "not terrible", "average", "meh", "decent" ], tier5: [ /* 35-49 */ "timing off", "almost there", "keep trying", "youll improve", "not quite", "almost", "needs work", "try again", "off rhythm", "getting there", "practice more", "keep at it" ], tier6: [ /* <35 */ "lmaooo wtf", "bruh...", "that aint it", "💀💀", "nah fam", "lol what", "so awkward", "💀", "bruh really", "yikes", "cant even lol", "nah this aint it", "lmao nah", "awkward af", "oof" ] }, MASSAGE_BREASTS: { tier1: [ /* 95+ */ "FUCK those circles", "so perfect", "im losing my mind", "best technique ever", "dont stop baby", "omg so smooth", "im cumming", "so fucking hot", "god those are perfect", "hypnotic movement", "fuck yes", "im stroking to this", "best massage ever", "youre incredible", "cant stop watching", "im about to cum", "so smooth baby", "god yes", "im so hard rn", "this is perfect", "youre a goddess", "im losing it", "so turned on", "dont fucking stop", "massage them baby", "hypnotizing", "im edging hard", "need more", "god your technique", "youre so good", "making me throb", "cant handle this", "im gonna explode", "best hands ever", "holy fuck", "youre perfect", "soaking wet watching", "touching to this", "need to see more", "im obsessed", "fuck i love watching", "youre driving me crazy", "best show", "keep going", "im cumming with you", "such perfect technique", "youre so sexy", "loving every second", "go slower baby", "fuck yes those circles", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "god those are perfect", "so fucking hot", "i love watching this", "youre so good", "more please", "damn thats hot", "really smooth", "love watching", "youre doing great", "god damn that technique", "perfect circles", "cant get enough", "this is hot af", "love your hands", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love the motion", "so good rn", "youre a natural", "fuck thats nice", "great technique", "im here for it", "youre gorgeous", "love watching this", "so talented", "this is amazing", "youre killing it", "im hooked", "need more shows", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great circles", "love the smoothness", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "nice technique", "pretty smooth", "looks good", "keep going", "hot", "really good", "great circles", "not bad", "nice", "nice work", "great movement", "enjoying this", "looks great", "very nice", "good stuff", "keep it up", "doing well", "hot", "nice", "pretty sexy", "good show", "liking this", "solid technique", "looking good", "nice job", "decent show", "enjoying this", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice motion" ], tier4: [ /* 50-69 */ "decent effort", "not bad", "its alright", "okay", "pretty good", "decent", "fine", "okay i guess", "its fine", "not terrible", "average", "meh", "decent" ], tier5: [ /* 35-49 */ "bit shaky", "almost there", "keep trying", "youll improve", "not quite", "almost", "needs work", "try again", "circles off", "getting there", "practice more", "keep at it" ], tier6: [ /* <35 */ "bruh those circles lol", "💀", "what even is that", "lmao nah", "yikes", "lol so shaky", "bruh...", "that aint it", "💀💀", "nah fam", "lol what", "so awkward", "cant even lol", "bruh really", "oof" ] }, MASTURBATE: { tier1: [ /* 95+ */ "FUCK YES", "im cumming watching this", "so fucking hot", "best show ever", "dont stop baby please", "omg yes", "im cumming too", "this is perfect", "holy shit youre hot", "god i wish i was there", "fuck keep going", "im stroking hard", "best masturbation ever", "youre amazing", "cant stop watching", "im about to finish", "so turned on rn", "god yes", "im so hard rn", "this is everything", "youre incredible", "im losing it", "so fucking sexy", "dont fucking stop", "touch yourself baby", "so hot", "im edging hard", "need to see you cum", "god your technique", "youre so good", "making me throb", "cant handle this", "im gonna explode", "best show tonight", "holy fuck", "youre perfect", "soaking wet watching", "touching with you", "need more", "im obsessed", "fuck i love this", "youre driving me crazy", "cum for me", "keep going baby", "im cumming with you", "so fucking hot", "youre so sexy", "loving every second", "faster baby", "fuck yes like that", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "holy shit youre hot", "god i wish i was there", "so turned on rn", "youre amazing", "fuck keep going", "damn thats hot", "really good", "love watching you", "youre doing great", "god damn", "perfect technique", "cant get enough", "this is hot af", "love watching this", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love every move", "so good rn", "youre a natural", "fuck thats nice", "great show", "im here for it", "youre gorgeous", "love your body", "so talented", "this is amazing", "youre killing it", "im hooked", "need more shows", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great technique", "love watching you", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "really hot", "loving this", "great show", "keep it up", "so good", "really good", "great moves", "not bad", "nice", "nice work", "hot show", "enjoying this", "looks great", "very nice", "good stuff", "keep going", "doing well", "hot", "nice", "pretty sexy", "good show", "liking this", "solid", "looking good", "nice job", "decent show", "enjoying this", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice" ], tier4: [ /* 50-69 */ "pretty good", "not bad", "decent show", "alright", "okay", "decent", "fine", "okay i guess", "its fine", "not terrible", "average", "meh", "decent" ], tier5: [ /* 35-49 */ "seems forced", "try to relax", "almost there", "keep trying", "not quite", "almost", "needs work", "try again", "bit stiff", "getting there", "practice more", "keep at it" ], tier6: [ /* <35 */ "lol fake af", "bruh really?", "💀💀💀", "nah this aint it", "yikes", "lol so fake", "bruh...", "that aint it", "💀💀", "nah fam", "looks fake", "so awkward", "cant even lol", "bruh really", "oof" ] }, SIMULATE_ORAL: { tier1: [ /* 95+ */ "HOLY FUCK", "im so hard rn", "best technique ive seen", "god yes", "i need this so bad", "omg that looks good", "im cumming", "so fucking hot", "god i wish that was me", "perfect technique", "fuck yes", "im stroking hard", "best oral ever", "youre so skilled", "cant stop watching", "im about to finish", "that looks so real", "god yes", "im so hard", "this is perfect", "youre incredible", "im losing it", "so turned on", "dont fucking stop", "suck it baby", "so hot", "im edging hard", "need to see more", "god your mouth", "youre amazing", "making me throb", "cant handle this", "im gonna explode", "best bj simulation", "holy fuck", "youre perfect", "soaking wet watching", "touching to this", "need you so bad", "im obsessed", "fuck that looks good", "youre driving me wild", "best show", "keep sucking baby", "im cumming with you", "such good technique", "youre so sexy", "loving every second", "deeper baby", "fuck yes like that", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "fuck that looks good", "youre so skilled", "i wish that was me", "so hot", "dont stop", "damn thats hot", "really good technique", "love watching", "youre doing great", "god damn", "perfect motion", "cant get enough", "this is hot af", "love your technique", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love every movement", "so good rn", "youre a natural", "fuck thats nice", "great technique", "im here for it", "youre gorgeous", "love watching this", "so talented", "this is amazing", "youre killing it", "im hooked", "need more shows", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great motion", "love the speed", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "really good", "nice technique", "pretty hot", "keep going", "love it", "really good", "great motion", "not bad", "nice", "nice work", "hot show", "enjoying this", "looks great", "very nice", "good stuff", "keep it up", "doing well", "hot", "nice", "pretty sexy", "good show", "liking this", "solid", "looking good", "nice job", "decent show", "enjoying this", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice" ], tier4: [ /* 50-69 */ "decent work", "not bad", "its alright", "okay", "pretty good", "decent", "fine", "okay i guess", "its fine", "not terrible", "average", "meh", "decent" ], tier5: [ /* 35-49 */ "bit awkward", "needs practice", "almost there", "keep trying", "not quite", "almost", "needs work", "try again", "off motion", "getting there", "practice more", "keep at it" ], tier6: [ /* <35 */ "lmaooo bruh", "wtf was that", "💀", "nah fam", "yikes dude", "lol so fake", "bruh...", "that aint it", "💀💀", "nah", "looks fake af", "so awkward", "cant even lol", "bruh really", "oof" ] }, POSE_NUDE: { tier1: [ /* 95+ */ "FUCK youre gorgeous", "perfect body", "im so turned on", "goddess", "i cant stop staring", "omg that body", "im cumming", "so fucking hot", "god youre beautiful", "perfect curves", "fuck yes", "im stroking hard", "best body on here", "youre stunning", "cant stop watching", "im about to cum", "so beautiful", "god yes", "im so hard rn", "this is perfect", "youre a goddess", "im losing it", "so turned on", "dont move", "pose for me baby", "so hot", "im edging hard", "need more poses", "god your body", "youre perfect", "making me throb", "cant handle this", "im gonna explode", "best pose ever", "holy fuck", "youre flawless", "soaking wet watching", "touching to you", "need to see more", "im obsessed", "fuck that body", "youre driving me crazy", "best view", "stay like that", "im cumming to you", "such a perfect body", "youre so sexy", "loving every curve", "turn around baby", "fuck yes that angle", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "god youre beautiful", "so fucking hot", "amazing body", "youre perfect", "i need more", "damn thats hot", "really gorgeous", "love your body", "youre doing great", "god damn", "perfect figure", "cant get enough", "this is hot af", "love your curves", "making me hard", "so beautiful", "youre perfect", "damn baby", "im getting close", "love every angle", "so good rn", "youre stunning", "fuck thats nice", "great pose", "im here for it", "youre gorgeous", "love your body", "so hot", "this is amazing", "youre killing it", "im hooked", "need more poses", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great pose", "love the confidence", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "looking great", "really hot", "nice body", "beautiful", "keep it up", "really good", "great pose", "not bad", "nice", "nice work", "hot", "enjoying this", "looks great", "very nice", "good stuff", "keep posing", "doing well", "hot", "nice", "pretty sexy", "good show", "liking this", "solid", "looking good", "nice job", "decent show", "enjoying the view", "not bad", "pretty good", "this is nice", "good work", "looks hot", "doing good", "nice body" ], tier4: [ /* 50-69 */ "pretty good", "not bad", "decent", "alright", "okay", "decent pose", "fine", "okay i guess", "its fine", "not terrible", "average", "meh", "decent" ], tier5: [ /* 35-49 */ "bit stiff", "try to relax", "almost there", "keep trying", "not quite", "almost", "needs work", "try again", "awkward pose", "getting there", "practice more", "keep at it" ], tier6: [ /* <35 */ "bruh u look stiff af", "lol awkward", "💀💀", "nah man", "yikes", "lol so stiff", "bruh...", "that aint it", "💀💀", "nah fam", "looks awkward", "so stiff", "cant even lol", "bruh really", "oof" ] }, MOAN: { tier1: [ /* 95+ */ "THOSE SOUNDS FUCK", "im cumming", "holy shit your voice", "best moans ever", "dont stop baby", "omg that voice", "im cumming to this", "so fucking hot", "god your moans", "perfect sounds", "fuck yes", "im stroking to this", "best moans on here", "youre incredible", "cant stop listening", "im about to finish", "so sexy", "god yes", "im so hard rn", "this is perfect", "youre amazing", "im losing it", "so turned on", "dont fucking stop", "moan for me baby", "so hot", "im edging hard", "need to hear more", "god your voice", "youre perfect", "making me throb", "cant handle this", "im gonna explode", "best sounds ever", "holy fuck", "youre perfect", "soaking wet listening", "touching to your moans", "need more", "im obsessed", "fuck those moans", "youre driving me wild", "best audio", "keep moaning baby", "im cumming with you", "such sexy sounds", "youre so hot", "loving every moan", "louder baby", "fuck yes like that", "youre amazing", "im gonna lose it" ], tier2: [ /* 85-94 */ "god your moans", "so fucking sexy", "i love your voice", "youre amazing", "keep making those sounds", "damn thats hot", "really sexy", "love listening", "youre doing great", "god damn", "perfect sounds", "cant get enough", "this is hot af", "love your moans", "making me hard", "so good", "youre perfect", "damn baby", "im getting close", "love every sound", "so good rn", "youre a natural", "fuck thats nice", "great moans", "im here for it", "youre gorgeous", "love your voice", "so talented", "this is amazing", "youre killing it", "im hooked", "need more audio", "damn youre good", "loving every second", "youre so hot", "fuck yes", "great sounds", "love the moaning", "youre stunning", "cant wait for more" ], tier3: [ /* 70-84 */ "nice sounds", "really hot", "love your voice", "keep going", "great", "really good", "great moans", "not bad", "nice", "nice work", "hot sounds", "enjoying this", "sounds great", "very nice", "good stuff", "keep it up", "doing well", "hot", "nice", "pretty sexy", "good show", "liking this", "solid", "sounding good", "nice job", "decent show", "enjoying this", "not bad", "pretty good", "this is nice", "good work", "sounds hot", "doing good", "nice voice" ], tier4: [ /* 50-69 */ "not bad", "decent", "its alright", "okay", "pretty good", "decent moans", "fine", "okay i guess", "its fine", "not terrible", "average", "meh", "decent" ], tier5: [ /* 35-49 */ "seems forced", "try to be natural", "almost there", "keep trying", "not quite", "almost", "needs work", "try again", "sounds fake", "getting there", "practice more", "keep at it" ], tier6: [ /* <35 */ "lmaooo so fake", "bruh those sounds 💀", "nah this cringe", "yikes dude", "lol no", "lol so fake", "bruh...", "that aint it", "💀💀", "nah fam", "sounds fake af", "so cringe", "cant even lol", "bruh really", "oof" ] } }; /* Generate prawn chat based on score and action type */ window.generatePrawnChat = function(score, actionType, viewers) { let messages = []; let messagePool; /* Get action-specific messages */ let actionMessages = window.prawnChatMessages[actionType] || window.prawnChatMessages.STRIP_CLOTHING; /* Determine message pool based on score */ if (score >= 95) { messagePool = actionMessages.tier1; } else if (score >= 85) { messagePool = actionMessages.tier2; } else if (score >= 70) { messagePool = actionMessages.tier3; } else if (score >= 50) { messagePool = actionMessages.tier4; } else if (score >= 35) { messagePool = actionMessages.tier5; } else { messagePool = actionMessages.tier6; } /* Calculate number of messages based on viewers */ /* Min 3 messages, max 15 at 1000+ viewers */ let minMessages = 3; let maxMessages = 15; let viewerCount = viewers || 0; /* Scale messages: 3 at 0 viewers, 15 at 1000+ viewers */ let scaledMax = Math.min(maxMessages, minMessages + Math.floor((viewerCount / 1000) * (maxMessages - minMessages))); let numMessages = Math.floor(Math.random() * (scaledMax - minMessages + 1)) + minMessages; let usedIndices = new Set(); for (let i = 0; i < numMessages; i++) { let userIndex, msgIndex; /* Get unique user */ do { userIndex = Math.floor(Math.random() * window.prawnChatUsers.length); } while (usedIndices.has(userIndex) && usedIndices.size < window.prawnChatUsers.length); usedIndices.add(userIndex); /* Get random message */ msgIndex = Math.floor(Math.random() * messagePool.length); let user = window.prawnChatUsers[userIndex]; messages.push({ username: user.name, color: user.color, message: messagePool[msgIndex] }); } return messages; }; /* Display chat with scrolling animation */ window.displayPrawnChat = function(containerId, messages) { let container = document.getElementById(containerId); if (!container) return; container.innerHTML = ''; container.style.opacity = '0'; let delay = 0; messages.forEach((msg, index) => { setTimeout(() => { let chatLine = document.createElement('div'); chatLine.className = 'prawn-chat-line'; chatLine.innerHTML = `<span class="prawn-chat-username" style="color: ${msg.color};">${msg.username}:</span> <span class="prawn-chat-message">${msg.message}</span>`; container.appendChild(chatLine); /* Fade in container on first message */ if (index === 0) { container.style.opacity = '1'; } /* Scroll to bottom */ container.scrollTop = container.scrollHeight; }, delay); delay += 150 + Math.random() * 200; /* 150-350ms between messages */ }); }; <</script>>
<<nobr>> <<set $lastLocation = "PrawnHubAnalytics">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 25px; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #ff1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.4); text-align: center;"> <h1 style="color: white; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">📊 PrawnHub Analytics Dashboard</h1> <p style="color: #ffd; margin: 10px 0 0 0; font-size: 16px;"> Track your adult streaming performance and growth </p> </div> <!-- Overall Stats --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #ff1493; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #ff1493; margin: 0 0 20px 0;">🎯 Channel Overview</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #e74c3c; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL FOLLOWERS</div> <div style="font-size: 32px; font-weight: bold; color: #e74c3c;"><<print ($prawnhubFollowers || 0).toLocaleString()>></div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #3498db; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL STREAMS</div> <div style="font-size: 32px; font-weight: bold; color: #3498db;"><<print ($prawnhubStreamHistory ? $prawnhubStreamHistory.length : 0)>></div> </div> <<if $prawnhubStreamHistory && $prawnhubStreamHistory.length > 0>> <<set _totalMinutes = 0>> <<set _totalIncome = 0>> <<for _i = 0; _i < $prawnhubStreamHistory.length; _i++>> <<set _totalMinutes += $prawnhubStreamHistory[_i].duration>> <<set _totalIncome += $prawnhubStreamHistory[_i].netEarnings>> <</for>> <<set _totalHours = Math.floor(_totalMinutes / 60)>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TIME STREAMED</div> <div style="font-size: 32px; font-weight: bold; color: #9b59b6;"><<print _totalMinutes>> min</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #f39c12; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL EARNINGS</div> <div style="font-size: 32px; font-weight: bold; color: #f39c12;">$<<print Math.ceil(_totalIncome)>></div> </div> <</if>> </div> </div> <!-- Stream History --> <<if $prawnhubStreamHistory && $prawnhubStreamHistory.length > 0>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #4dabf7; margin: 0 0 20px 0;">📅 Recent Stream History (Last 7)</h2> <<set _historyLength = $prawnhubStreamHistory.length>> <<set _startIdx = Math.max(0, _historyLength - 7)>> <<for _i = _historyLength - 1; _i >= _startIdx; _i-->> <<set _stream = $prawnhubStreamHistory[_i]>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #333;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; flex-wrap: wrap;"> <div> <strong style="color: #ff1493; font-size: 18px;">Day <<print _stream.day>></strong> <span style="color: #aaa; margin-left: 15px;"><<print _stream.duration>> minutes</span> </div> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; margin-bottom: 15px;"> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">NEW FOLLOWERS</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">+<<print _stream.newFollowers>></div> </div> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">PEAK VIEWERS</div> <div style="color: #3498db; font-size: 20px; font-weight: bold;"><<print _stream.viewers>></div> </div> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">AVG ENGAGEMENT</div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print Math.round(_stream.engagement)>>%</div> </div> <div style="text-align: center; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <div style="color: #aaa; font-size: 12px; margin-bottom: 5px;">NET EARNED</div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;">$<<print Math.ceil(_stream.netEarnings)>></div> </div> </div> <!-- Actions Performed --> <<if _stream.actionsPerformed && _stream.actionsPerformed.length > 0>> <div style="background: #0a0a0a; padding: 15px; border-radius: 6px;"> <div style="color: #ff69b4; font-size: 12px; margin-bottom: 8px; font-weight: bold;">ACTIONS PERFORMED:</div> <div style="display: flex; flex-wrap: wrap; gap: 5px;"> <<for _j = 0; _j < _stream.actionsPerformed.length; _j++>> <<set _actionName = _stream.actionsPerformed[_j].replace(/_/g, " ")>> <span style="background: #333; padding: 4px 8px; border-radius: 4px; font-size: 11px; color: #aaa; border: 1px solid #ff1493;"> <<print _actionName>> </span> <</for>> </div> </div> <</if>> </div> <</for>> </div> <!-- Last 7 Streams Statistics --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #e74c3c; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h2 style="color: #e74c3c; margin: 0 0 20px 0;">📈 Last 7 Streams Statistics</h2> <<set _historyLength = $prawnhubStreamHistory.length>> <<set _statsStartIdx = Math.max(0, _historyLength - 7)>> <<set _last7TotalFollowers = 0>> <<set _last7TotalIncome = 0>> <<set _last7TotalMinutes = 0>> <<set _last7TotalViewers = 0>> <<set _last7TotalEngagement = 0>> <<set _last7Count = 0>> <<for _j = _statsStartIdx; _j < _historyLength; _j++>> <<set _last7TotalFollowers += $prawnhubStreamHistory[_j].newFollowers>> <<set _last7TotalIncome += $prawnhubStreamHistory[_j].netEarnings>> <<set _last7TotalMinutes += $prawnhubStreamHistory[_j].duration>> <<set _last7TotalViewers += $prawnhubStreamHistory[_j].viewers>> <<set _last7TotalEngagement += $prawnhubStreamHistory[_j].engagement>> <<set _last7Count++>> <</for>> <<set _avgViewers = Math.round(_last7TotalViewers / _last7Count)>> <<set _avgEngagement = Math.round(_last7TotalEngagement / _last7Count)>> <<set _avgIncomePerStream = Math.round((_last7TotalIncome / _last7Count) * 100) / 100>> <<set _avgFollowersPerStream = Math.round(_last7TotalFollowers / _last7Count)>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #e74c3c; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL NEW FOLLOWERS</div> <div style="font-size: 28px; font-weight: bold; color: #e74c3c;">+<<print _last7TotalFollowers>></div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Avg: <<print _avgFollowersPerStream>> per stream</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #f39c12; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">TOTAL EARNINGS</div> <div style="font-size: 28px; font-weight: bold; color: #f39c12;">$<<print Math.ceil(_last7TotalIncome)>></div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Avg: $<<print Math.ceil(_avgIncomePerStream)>> per stream</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #3498db; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">AVG PEAK VIEWERS</div> <div style="font-size: 28px; font-weight: bold; color: #3498db;"><<print _avgViewers>></div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Across <<print _last7Count>> streams</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 14px; color: #aaa; margin-bottom: 8px;">AVG ENGAGEMENT</div> <div style="font-size: 28px; font-weight: bold; color: #9b59b6;"><<print _avgEngagement>>%</div> <div style="font-size: 12px; color: #666; margin-top: 5px;">Across <<print _last7Count>> streams</div> </div> </div> </div> <<else>> <!-- No Stream History --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 40px; border-radius: 12px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4); text-align: center;"> <div style="font-size: 48px; margin-bottom: 20px;">📊</div> <h2 style="color: #aaa; margin: 0 0 15px 0;">No Stream Data Yet</h2> <p style="color: #888; font-size: 16px; margin: 0;"> Start streaming on PrawnHub to see your analytics and performance metrics here! </p> </div> <</if>> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to PrawnHub</div>">> <<goto "PrawnHub">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<silently>> <<if !$prawnhubRegistered>> <<set $prawnhubRegistered = false>> <</if>> <<if !$prawnhubFollowers>> <<set $prawnhubFollowers = 0>> <</if>> <<if !$prawnhubTotalEarnings>> <<set $prawnhubTotalEarnings = 0>> <</if>> <<if !$prawnhubSessionsToday>> <<set $prawnhubSessionsToday = 0>> <</if>> <<if !$prawnhubMaxSessions>> <<set $prawnhubMaxSessions = 3>> <</if>> <<if !$prawnhubStreamHistory>> <<set $prawnhubStreamHistory = []>> <</if>> <</silently>> <</nobr>> <<script>> window.savePrawnStream = function() { if (!State.variables.currentPrawnStream) return; var stream = State.variables.currentPrawnStream; /* Calculate followers gained (current followers - starting followers) */ var followersGained = stream.followersGained || 0; if (stream.startingFollowers !== undefined) { followersGained = (State.variables.prawnhubFollowers || 0) - stream.startingFollowers; } var streamRecord = { day: State.variables.dayNumber || 1, viewers: stream.peakViewers || stream.viewers || 0, engagement: stream.currentEngagement || 0, earnings: stream.earnings || 0, netEarnings: stream.earnings || 0, newFollowers: followersGained, duration: stream.totalMinutes || 0, actionsPerformed: stream.actionsPerformed || [] }; State.variables.prawnhubStreamHistory.push(streamRecord); State.variables.prawnhubTotalEarnings += (stream.earnings || 0); State.variables.prawnhubSessionsToday++; State.variables.currentPrawnStream = null; }; <</script>>
/* ---------------------------------- */ /* --- TRAIT BONUSES SYSTEM (MUST BE FIRST) --- */ /* ---------------------------------- */ <<set setup.traitBonuses = { /* ================================== */ /* SPECIAL PHYSICAL TRAITS */ /* ================================== */ "Definitely not a Vampire": {strength: 50, charisma: 50, dexterity: 50}, "Were-Creature": {strength: 60, dexterity: 60}, "Quill": {strength: 26, charisma: 26, dexterity: 26, intelligence: 26}, "Werewolf": {strength: 7, dexterity: 4, charisma: 2, intelligence: 3}, "Cerberus": {strength: 57, dexterity: 59, charisma: 7, intelligence: 3}, /* ================================== */ /* PHYSICAL TRAITS - POSITIVE */ /* ================================== */ "Artistic": {intelligence: 2, dexterity: 2}, "Athletic Build": {strength: 5, dexterity: 5}, "Blue Hair": {}, "Snow Fox": {}, "Attractive": {charisma: 8}, "Broad-shouldered": {strength: 4}, "Curvy": {charisma: 5}, "Customer-Focused": {charisma: 3, intelligence: 1}, "Dark Skin": {}, "Deep Thinker": {intelligence: 4}, "Detail-Oriented": {intelligence: 3, dexterity: 2}, "Fashionable": {charisma: 5}, "Fast": {dexterity: 6}, "Fit": {strength: 5, dexterity: 4}, "Flexible": {dexterity: 6}, "Freckled": {charisma: 2}, "Graceful": {dexterity: 6, charisma: 3}, "High Energy": {dexterity: 3, charisma: 4}, "Humorous": {charisma: 2}, "Lean": {dexterity: 4, strength: 2}, "Long Hair": {}, "Mature": {intelligence: 4, charisma: 2}, "Monotone Expression": {intelligence: 1}, "Muscular": {strength: 8}, "Pale Skin": {}, "Perceptive": {intelligence: 3}, "Petite": {dexterity: 4}, "Pierced": {charisma: 2}, "Punctual": {intelligence: 1, charisma: 1}, "Quick": {dexterity: 5}, "Quick Reflexes": {dexterity: 6}, "Relaxed": {charisma: 2}, "Sarcastic": {charisma: 2, intelligence: 1}, "Sharp Features": {charisma: 4}, "Short Hair": {}, "Smooth Skin": {charisma: 3}, "Soft": {charisma: 3}, "Striking": {charisma: 6}, "Strong": {strength: 7}, "Sturdy": {strength: 4}, "Tall": {}, "Tan Skin": {}, "Tattooed": {charisma: 3}, "Voluptuous": {charisma: 6}, "Youthful": {charisma: 3, dexterity: 2}, /* ================================== */ /* PHYSICAL TRAITS - MIXED */ /* ================================== */ "Scarred": {strength: 2, charisma: -3}, "Short": {}, /* ================================== */ /* PHYSICAL TRAITS - NEGATIVE */ /* ================================== */ "Blemished": {charisma: -4}, "Clumsy": {dexterity: -6}, "Overweight": {strength: -4, dexterity: -4, charisma: -3}, "Plain": {charisma: -3}, "Slow": {dexterity: -5, strength: -2}, "Stiff": {dexterity: -5}, "Ugly": {charisma: -8}, "Underweight": {strength: -5, charisma: -2}, "Unphotogenic": {charisma: -3}, "Weak": {strength: -7}, /* ================================== */ /* VOICE TRAITS - POSITIVE */ /* ================================== */ "Animated Tone": {charisma: 4}, "Articulate Speech": {charisma: 4, intelligence: 3}, "Balanced Neutral Tone": {}, "Bouncy Tone": {charisma: 3}, "Breathy Voice": {charisma: 2}, "Calm Voice": {charisma: 3}, "Charming Tone": {charisma: 5}, "Charismatic Voice": {charisma: 7}, "Clear Enunciation": {charisma: 3, intelligence: 2}, "Clear Pronunciation": {charisma: 3, intelligence: 2}, "Deep Voice": {charisma: 2}, "Eager Tone": {charisma: 3}, "Even-Paced Voice": {charisma: 2}, "Expressive Voice": {charisma: 5}, "Friendly Tone": {charisma: 4}, "Gentle Voice": {charisma: 3}, "Gravelly Voice": {charisma: 1}, "Hushed Intimate Voice": {charisma: 4}, "Lively Tone": {charisma: 4}, "Measured Speech": {intelligence: 3}, "Melodic Voice": {charisma: 5}, "Pleasant Cadence": {charisma: 4}, "Silky Voice": {charisma: 5}, "Sing-Songy Voice": {charisma: 3}, "Slow Calm Voice": {charisma: 2}, "Smooth Talker": {charisma: 6}, "Smooth Voice": {charisma: 4}, "Soft Monologue Style": {charisma: 2}, "Soft-Spoken": {charisma: 2}, "Soothing Tone": {charisma: 4}, "Steady Voice": {charisma: 3}, "Understated Voice": {charisma: 1}, "Warm Tone": {charisma: 5}, "Gaelic Accent": {charisma: 1}, /* ================================== */ /* VOICE TRAITS - MIXED/NEGATIVE */ /* ================================== */ "Choppy Speech": {charisma: -2}, "Croaky Voice": {charisma: -2}, "Deadpan Delivery": {intelligence: 2, charisma: -2}, "Detached Voice": {charisma: -3}, "Emotionless Tone": {charisma: -4}, "Fast Talker": {dexterity: 2, charisma: -1}, "Flat Voice": {charisma: -2}, "Grim Tone": {charisma: -2}, "High-Pitched Tone": {charisma: -1}, "Interruptive Tone": {charisma: -3}, "Lazy Drawl": {charisma: -2}, "Monotone": {charisma: -3}, "Mumbly Voice": {charisma: -4}, "Nasally Tone": {charisma: -3}, "Rapid-Fire Speech": {dexterity: 3, charisma: -2}, "Raspy Voice": {}, "Robotic Tone": {intelligence: 2, charisma: -3}, "Shaky Voice": {charisma: -3}, "Sharp Voice": {charisma: -1}, "Snappy Tone": {charisma: -2}, "Stoic Tone": {intelligence: 2, charisma: -1}, "Stuttering Speech": {charisma: -3}, /* ================================== */ /* MENTAL TRAITS - POSITIVE */ /* ================================== */ "Alluring": {charisma: 7}, "Ambitious": {intelligence: 4, charisma: 3}, "Analytical": {intelligence: 5}, "Bookworm": {intelligence: 6}, "Brave": {strength: 4, charisma: 3}, "Calm": {intelligence: 2, charisma: 2}, "Charming": {charisma: 6}, "Chill": {charisma: 3, intelligence: 2}, "Competitive": {strength: 3, intelligence: 2}, "Confident": {charisma: 6}, "Considerate": {charisma: 5}, "Crafty": {intelligence: 4, dexterity: 3}, "Creative": {intelligence: 5}, "Curious": {intelligence: 3}, "Determined": {strength: 4, intelligence: 2}, "Diplomatic": {charisma: 5, intelligence: 3}, "Direct": {charisma: 2, intelligence: 1}, "Disciplined": {strength: 3, intelligence: 3}, "Efficient": {intelligence: 4, dexterity: 2}, "Empathetic": {charisma: 5, intelligence: 2}, "Energetic": {dexterity: 2, charisma: 2}, "Extroverted": {charisma: 5}, "Flirty": {charisma: 5}, "Focused": {intelligence: 4}, "Friendly": {charisma: 6}, "Funny": {charisma: 5}, "Hardworking": {strength: 3, intelligence: 3}, "High Stamina": {strength: 6, dexterity: 3}, "Humble": {charisma: 4}, "Intelligent": {intelligence: 5}, "Kind": {charisma: 6}, "Logical": {intelligence: 6}, "Loyal": {charisma: 4}, "Lucky": {charisma: 3, dexterity: 3}, "Negotiator": {charisma: 6, intelligence: 3}, "Nonchalant": {charisma: 2}, "Optimistic": {charisma: 4}, "Organized": {intelligence: 4}, "Outgoing": {charisma: 4}, "Patient": {intelligence: 3, charisma: 2}, "Photogenic": {charisma: 5}, "Poised": {charisma: 4, dexterity: 2}, "Polite": {charisma: 4}, "Reassuring": {charisma: 4}, "Resourceful": {intelligence: 5, dexterity: 2}, "Seductive": {charisma: 6}, "Shrewd": {intelligence: 5, charisma: 2}, "Sly": {intelligence: 4, charisma: 2}, "Steadfast": {strength: 3, intelligence: 2}, "Supportive": {charisma: 5}, "Talkative": {charisma: 3}, "Thoughtful": {intelligence: 3}, "Trusting": {charisma: 3}, "Warm": {charisma: 5}, "Wise": {intelligence: 7}, "Witty": {charisma: 3, intelligence: 2}, "Workaholic": {intelligence: 3, strength: 2}, /* ================================== */ /* MENTAL TRAITS - MIXED */ /* ================================== */ "Aggressive": {strength: 5, charisma: -2}, "Awkward": {charisma: -4}, "Bimbo": {intelligence: -40, charisma: 10}, "Blunt": {charisma: -2, intelligence: 2}, "Clingy": {charisma: -3}, "Corporate Drone": {intelligence: 2, charisma: -2}, "Corrupt": {charisma: 1}, "Cynical": {intelligence: 2, charisma: -3}, "Dominant": {charisma: 4, strength: 3}, "Honest": {charisma: 3, intelligence: -2}, "Impulsive": {dexterity: 3, intelligence: -3}, "Introverted": {intelligence: 3, charisma: -3}, "Moody": {charisma: -3}, "Overthinker": {intelligence: 3, charisma: -3}, "Paranoid": {intelligence: 2, charisma: -4}, "Passive": {charisma: -2, intelligence: 3}, "Perfectionist": {intelligence: 4, charisma: -2}, "Perverted": {}, "Pessimistic": {intelligence: 3, charisma: -3}, "Quiet": {charisma: -2, intelligence: 2}, "Risk Taker": {strength: 3, intelligence: -2}, "Sensitive": {charisma: -2, intelligence: 2}, "Shy": {charisma: -5, intelligence: 2}, "Stubborn": {strength: 4, intelligence: -2}, "Submissive": {charisma: -3, dexterity: 2}, "Tease": {charisma: 2}, "Tone Deaf": {charisma: -3}, "Unpredictable": {charisma: -2}, "Musky": {}, "Gambling Addiction": {charisma: +1, intelligence: -5}, /* ================================== */ /* MENTAL TRAITS - NEGATIVE */ /* ================================== */ "Arrogant": {charisma: -6, intelligence: -2}, "Bitchy": {charisma: -5, intelligence: -2}, "Cold": {charisma: -5}, "Complacent": {intelligence: -4, strength: -3}, "Cowardly": {strength: -5, charisma: -4}, "Cruel": {charisma: -8, intelligence: -2}, "Deceitful": {charisma: -5, intelligence: -2}, "Disorganized": {intelligence: -4, dexterity: -2}, "Dull": {intelligence: -6, charisma: -3}, "Erratic": {charisma: -4, intelligence: -3}, "Foolish": {intelligence: -7, charisma: -2}, "Forgetful": {intelligence: -5}, "Impatient": {intelligence: -3, charisma: -4}, "Insecure": {charisma: -5}, "Insensitive": {charisma: -5}, "Jealous": {charisma: -5, intelligence: -2}, "Lazy": {strength: -5, intelligence: -4}, "Obsessive": {intelligence: -3, charisma: -4}, "Reckless": {intelligence: -4, strength: -3}, "Rude": {charisma: -6}, "Selfish": {charisma: -6}, "Short Tempered": {charisma: -5, intelligence: -2}, "Slow Learner": {intelligence: -6}, "Unlucky": {charisma: -3, dexterity: -3}, "Bad Luck": {charisma: -3, dexterity: -3}, "Caffeine Addict": {dexterity: 3, intelligence: 10, charisma: -5}, "Unreliable": {charisma: -5, intelligence: -3}, "Unskilled": {dexterity: -5, intelligence: -3}, /* ================================== */ /* STEREOTYPE TRAITS */ /* ================================== */ "Diva": {charisma: 6, intelligence: -3}, "Femboy": {charisma: 4, dexterity: 3}, "Geek": {intelligence: 5, charisma: -1}, "Goth": {charisma: 2, intelligence: 2}, "Jock": {strength: 5, dexterity: 4, intelligence: -2}, "Nerd": {intelligence: 6, charisma: -2}, "Prep": {charisma: 5, intelligence: 2}, "Tomboy": {strength: 3, dexterity: 3, charisma: -2}, "Delinquent": {strength: 7, dexterity: 4, charisma: -3}, /* ================================== */ /* FISHING MILESTONE TRAITS */ /* ================================== */ "Fishing": {}, "Advanced Angler": {}, "Master Angler": {}, "Fishimon Master": {}, /* ================================== */ /* SPECIAL TRAITS (ADDITIONAL) */ /* ================================== */ "Totally not a Vampire": {strength: 50, charisma: 50, dexterity: 50}, "Sunfish": {charisma: 50, dexterity: 50, strength: 50, intelligence: 50}, "Soul": {}, "Dragon": {}, "Half-Dragon Gyaru": {strength: 40, dexterity: 25, charisma: 30, intelligence: 15}, /* ================================== */ /* CHARACTER CREATION TRAITS */ /* ================================== */ "Naturally Gifted": {strength: 2, charisma: 2, dexterity: 2, intelligence: 2}, "Pensive": {intelligence: 4}, "Silver-Tongued": {charisma: 5}, "Swift": {dexterity: 5}, /* ================================== */ /* MISCELLANEOUS */ /* ================================== */ "Cuntboy": {}, "Dickgirl": {}, "Futanari": {}, /* ================================== */ /* NPC / SHARED TRAITS */ /* ================================== */ "Nervous": {charisma: -4, dexterity: -2}, "Scared": {strength: -3, charisma: -4}, "Assertive": {charisma: 4, strength: 2}, "Serious": {intelligence: 3, charisma: -1}, "Reserved": {charisma: -3, intelligence: 2}, "Demanding": {charisma: -3, intelligence: 1}, "Stocky": {strength: 4}, "Slim": {dexterity: 3}, "Prudish": {charisma: -2}, "Timid": {charisma: -3, dexterity: -1}, "Antisocial": {charisma: -5}, "Busy": {}, "Cautious": {intelligence: 3}, "Reliable": {charisma: 3, intelligence: 2}, "Careful": {intelligence: 3}, /* ================================== */ /* NPC MENTAL TRAITS (ADDITIONAL) */ /* ================================== */ "Anxious": {charisma: -4, dexterity: -2}, "Bold": {strength: 3, charisma: 3}, "Bubbly": {charisma: 4}, "By-the-Book": {intelligence: 3, charisma: -1}, "Clever": {intelligence: 4}, "Crazy": {strength: 3, charisma: -5}, "Eccentric": {intelligence: 3, charisma: -1}, "Gentle": {charisma: 3, strength: -1}, "Hot-Headed": {strength: 3, charisma: -3}, "Intimidating": {strength: 4, charisma: -2}, "Manipulative": {charisma: 3, intelligence: 2}, "Naive": {charisma: 2, intelligence: -3}, "Nurturing": {charisma: 4}, "Passionate": {charisma: 3, strength: 2}, "Playful": {charisma: 3, dexterity: 2}, "Protective": {strength: 4, charisma: 2}, "Romantic": {charisma: 4}, "Sassy": {charisma: 3}, "Simple": {intelligence: -2}, "Spiritual": {intelligence: 3}, "Street Smart": {intelligence: 4, dexterity: 2}, "Vain": {charisma: 2, intelligence: -2}, /* ================================== */ /* NPC VOICE TRAITS */ /* ================================== */ "Flat Uninterested Voice": {}, "Slurred Speech": {charisma: -2}, "Whiny Voice": {charisma: -2}, /* ================================== */ /* TRANSFORMATION BASE TRAITS */ /* ================================== */ "Fangs": {strength: 2}, "Pointed Ears": {charisma: 2}, "Glowing Eyes": {charisma: 3}, "Claws": {strength: 2, dexterity: 2}, "Wings": {dexterity: 3, charisma: 2}, "Tail": {dexterity: 2}, "Lactating": {}, "Mischievous": {dexterity: 3, charisma: 2}, "Docile": {charisma: 2, intelligence: -2}, "Feral": {strength: 5, intelligence: -4}, "Predatory": {strength: 3, dexterity: 3}, "Maternal": {charisma: 4}, "Paternal": {charisma: 3, strength: 2}, "Breeding Obsessed": {charisma: 2, intelligence: -3}, "Heat Cycles": {charisma: 3}, "Pack Minded": {charisma: 2, strength: 2}, "Nocturnal": {dexterity: 3, intelligence: 2}, "Territorial": {strength: 3}, "Shameless": {charisma: 4, intelligence: -2}, "Insatiable": {charisma: 3, intelligence: -2}, "Praise Seeking": {charisma: 2}, "Obedient": {charisma: 2, intelligence: -2}, "Collar Loving": {charisma: 2}, "Rebellious": {strength: 2, charisma: -2}, "Corrupted": {charisma: 3, intelligence: 2}, "Cunning": {intelligence: 4, charisma: 2}, /* ================================== */ /* INTERMEDIATE COMBINATION TRAITS */ /* ================================== */ "Temptress": {charisma: 8}, "Sadist": {strength: 3, charisma: 5}, "Masochist": {dexterity: 3, charisma: 5}, "Milky": {charisma: 5}, "Neko": {dexterity: 6, charisma: 4}, "Inu": {strength: 4, dexterity: 4}, "Imp-Touched": {charisma: 6, intelligence: -3}, "Mommy Energy": {charisma: 6}, "Devoted": {charisma: 4, intelligence: -2}, "Exhibitionist": {charisma: 7, intelligence: -2}, "Savage": {strength: 8, intelligence: -5}, "Genius": {intelligence: 10, charisma: -3}, /* ================================== */ /* FULL TRANSFORMATION TRAITS */ /* ================================== */ "Succubus": {charisma: 30, dexterity: 12}, "Incubus": {charisma: 15, strength: 5, intelligence: 3}, "Imp": {charisma: 5, dexterity: 10, intelligence: 10}, "Cerberus": {strength: 57, dexterity: 59, charisma: 7, intelligence: 3}, "Werecat": {strength: 3, dexterity: 20, charisma: 10, intelligence: 13}, "Werewolf": {strength: 7, dexterity: 4, charisma: 2, intelligence: 3}, "Werebunny": {dexterity: 20}, "Werefox": {intelligence: 4, charisma: 10}, "Weresheep": {charisma: 16}, "Hucow": {charisma: 16, intelligence: -15}, "Trophy Wife": {charisma: 15, intelligence: -10}, "Ojou": {charisma: 25, intelligence: 10}, "Gym Bunny": {strength: 45, dexterity: 20}, "Oni": {strength: 200, dexterity: 200}, "E-Girl": {charisma: 25, intelligence: 15}, "Punk": {strength: 5, charisma: 5}, "Siren": {charisma: 165, strength: 4, dexterity: 3}, "Living Doll": {intelligence: 32, charisma: 10}, "Dominatrix": {charisma: 42, strength: 43, intelligence: -2}, "Slut": {charisma: 30, strength: 6, dexterity: 5, intelligence: -10}, "Gyaru": {charisma: 45}, "Himbo": {strength: 55, intelligence: -25}, "Blessed": {strength: 10, intelligence: 10, charisma: 10, dexterity: 10}, "Wild": {strength: 5, dexterity: 5}, "Chosen": {strength: 100, intelligence: 100, charisma: 100, dexterity: 100}, "Honey": {charisma: 5}, "Cog": {intelligence: 20, strength: 70, dexterity: -10}, "Mystic": {strength: 7, intelligence: 7, charisma: 7, dexterity: 7}, "Heart": {charisma: 1}, "Guardian": {strength: 10, intelligence: 10, charisma: 10, dexterity: 10}, "Darkness": {strength: -300, intelligence: -300, charisma: -300, dexterity: -300}, "Alcoholic": {dexterity: -50, intelligence: -50}, "Disturbed": {strength: -1000, intelligence: -1000, charisma: -1000, dexterity: -1000}, "Mirrored": {}, "Thirsty": {}, "Blood": {}, "Burnt": {}, "Inferno": {dexterity: -50, charisma: -100}, "Scaled": {}, "Divine Sunfish": {}, "Electrified": {dexterity: 30}, "Totally not a Vampire": {strength: 50, charisma: 50, dexterity: 50}, "Fish": {}, /* NEW TRANSFORMATION TRAITS */ "Angel": {strength: 10, dexterity: 13, charisma: 17, intelligence: 10}, "Naiad": {strength: 54, dexterity: 53, charisma: 215, intelligence: 50}, "Automaton": {strength: 70, charisma: 10, intelligence: 52}, "Banshee": {}, "Cheshire Cat": {strength: 3, dexterity: 23, charisma: 63, intelligence: 13}, "Cupid": {strength: 10, dexterity: 13, charisma: 24, intelligence: 10}, "Dark Angel": {strength: 10, dexterity: 10, charisma: 10, intelligence: 10}, "Honeybee": {dexterity: 2, charisma: 11}, "Jinko": {strength: 124, dexterity: 88, charisma: 10, intelligence: 13}, "Kakuen": {strength: 10, dexterity: 11, charisma: 2}, "Lizardman": {strength: 4, intelligence: 2}, "Ocelomeh": {strength: 33, dexterity: 50, charisma: 10, intelligence: 20}, "Pyrow": {dexterity: 12, charisma: 10, intelligence: 10}, "Raiju": {strength: 66, dexterity: 95, charisma: 30}, "Salamander": {strength: 9, dexterity: 5, intelligence: 2}, "Satyros": {dexterity: 3, charisma: 20}, "Vampire": {strength: 50, dexterity: 50, charisma: 50}, "Kitsune": {strength: 7, dexterity: 7, charisma: 17, intelligence: 11}, "Anubis": {strength: 17, dexterity: 14, charisma: 16, intelligence: 13}, "Pharaoh": {strength: 1103, dexterity: 1100, charisma: 1109, intelligence: 1103} }>> <<set setup.skillBonuses = { /* ================================== */ /* SPECIAL SKILLS */ /* ================================== */ "Occult Expert": {intelligence: 30}, "Sunfish": {charisma: 50, dexterity: 50, strength: 50, intelligence: 50}, "Criminal Deluxe": {dexterity: 100, intelligence: 100, charisma: 100}, /* ================================== */ /* REGULAR SKILLS */ /* ================================== */ "Accounting": {intelligence: 6}, "Acting": {charisma: 6, intelligence: 2}, "Art": {dexterity: 4, intelligence: 3}, "Athletics": {strength: 5, dexterity: 4}, "Baking": {dexterity: 4, intelligence: 2}, "Cleaning": {dexterity: 3}, "Coding": {intelligence: 6}, "Combat": {strength: 6, dexterity: 3}, "Construction": {strength: 5, intelligence: 2}, "Cooking": {intelligence: 3, dexterity: 2}, "Customer Service": {charisma: 3, intelligence: 1}, "Dancing": {dexterity: 5, charisma: 3}, "Driving": {dexterity: 4}, "First Aid": {intelligence: 4}, "Foreign Language": {intelligence: 5}, "Forklift Certified": {dexterity: 3, strength: 2}, "Gardening": {intelligence: 2, strength: 2}, "Guitar": {dexterity: 4, charisma: 2}, "Hair Styling": {dexterity: 5, charisma: 2}, "Heavy Lifting": {strength: 7}, "High Heels Proficient": {dexterity: 4, charisma: 2}, "Inventory Management": {intelligence: 3, dexterity: 1}, "Languages": {intelligence: 5}, "Legal Knowledge": {intelligence: 7}, "Lock Picking": {dexterity: 6, intelligence: 2}, "Maid": {dexterity: 4}, "Makeup": {dexterity: 3, charisma: 3}, "Management": {intelligence: 5, charisma: 4}, "Martial Arts": {strength: 5, dexterity: 5}, "Math Skills": {intelligence: 5}, "Medicine": {intelligence: 7}, "Modeling": {charisma: 6}, "Music": {dexterity: 3, charisma: 4}, "Painting": {dexterity: 4, intelligence: 3}, "Persuasion": {charisma: 7}, "Photography": {intelligence: 3, charisma: 2}, "Piano": {dexterity: 5, intelligence: 2}, "Plumbing": {strength: 3, intelligence: 2}, "Product Knowledge": {intelligence: 2, charisma: 1}, "Public Speaking": {charisma: 6, intelligence: 2}, "Quick Learner": {}, "Retail": {charisma: 3, intelligence: 2}, "Sales": {charisma: 6, intelligence: 2}, "Serving": {charisma: 4, dexterity: 2}, "Sexually Skilled": {charisma: 5, dexterity: 2}, "Singing": {charisma: 5}, "Social Media": {charisma: 5, intelligence: 2}, "Stealth": {dexterity: 6}, "Swimmer": {strength: 4, dexterity: 3}, "Swimming": {strength: 4, dexterity: 3}, "Teaching": {intelligence: 5, charisma: 3}, "Tech-Savvy": {intelligence: 3, dexterity: 1}, "Trading": {charisma: 4, intelligence: 3}, "Troubleshooting": {intelligence: 3, dexterity: 2}, "Writing": {intelligence: 5}, "Yoga": {dexterity: 5, intelligence: 2}, /* ================================== */ /* SEXUAL EXPERTISE TRAITS */ /* ================================== */ "Oral Expert": {charisma: 8, dexterity: 4}, "Anal Expert": {charisma: 6, dexterity: 6}, "Rough Sex Enthusiast": {strength: 6, charisma: 4}, "Sensual Lover": {charisma: 10}, "BDSM Enthusiast - Dom": {charisma: 8, strength: 4}, "BDSM Enthusiast - Sub": {charisma: 6}, "Roleplay Expert": {charisma: 8, intelligence: 4}, "Dirty Talker": {charisma: 7}, "Exhibitionist": {charisma: 6}, "Sexual Stamina Expert": {strength: 12, dexterity: 8}, "Tit Worship Expert": {charisma: 7, dexterity: 3}, "Titfuck Master": {charisma: 8, dexterity: 5}, /* ================================== */ /* NPC SKILLS (ADDITIONAL) */ /* ================================== */ "Building PCs": {intelligence: 4, dexterity: 2}, "Animation": {intelligence: 3, dexterity: 4}, "Fashion Design": {charisma: 4, dexterity: 3}, "Finance": {intelligence: 6}, "Investigation": {intelligence: 5, dexterity: 2}, "Leadership": {charisma: 5, intelligence: 3}, "Social Skills": {charisma: 5}, "Video Editing": {intelligence: 3, dexterity: 2}, "Combat Training": {strength: 5, dexterity: 3}, "Gaming": {dexterity: 3, intelligence: 2}, "Basketball": {strength: 3, dexterity: 4}, "Business": {intelligence: 5, charisma: 3}, "Mechanical Repair": {strength: 3, intelligence: 3}, "Navigation": {intelligence: 4}, "Magic Theory": {intelligence: 7}, "Meditation": {intelligence: 4} }>> /* Function to calculate total stat bonuses from traits and skills */ <<set setup.calculateStatBonuses = function() { var v = State.variables; var localIsBanshee = v.physicalTraits && v.physicalTraits.includes("Banshee"); var localIsPharaoh = v.physicalTraits && v.physicalTraits.includes("Pharaoh"); var bonuses = { charisma: 0, dexterity: 0, strength: 0, intelligence: 0 }; /* Helper: apply trait bonus with Banshee inversion and Pharaoh negative immunity */ function applyBonus(traitBonus) { if (!traitBonus) return; for (var stat in traitBonus) { var val = traitBonus[stat]; if (localIsBanshee) val = -val; /* Banshee inverts ALL bonuses */ if (localIsPharaoh && val < 0) val = 0; /* Pharaoh: negatives become 0 */ bonuses[stat] += val; } } /* Add bonuses from physical traits */ if (v.physicalTraits) { v.physicalTraits.forEach(function(trait) { applyBonus(setup.traitBonuses[trait]); }); } /* Add bonuses from mental traits */ if (v.mentalTraits) { v.mentalTraits.forEach(function(trait) { applyBonus(setup.traitBonuses[trait]); }); } /* Add bonuses from character creation trait */ if (v.characterCreationTrait && setup.traitBonuses[v.characterCreationTrait]) { applyBonus(setup.traitBonuses[v.characterCreationTrait]); } /* Add bonuses from skills */ if (v.skills) { v.skills.forEach(function(skill) { var skillBonus = setup.skillBonuses[skill]; if (skillBonus) { applyBonus(skillBonus); } }); } /* Add bonuses from player-crafted ingredient traits */ if (v.craftedTraitBonuses && v.physicalTraits) { v.physicalTraits.forEach(function(trait) { applyBonus(v.craftedTraitBonuses[trait]); }); } return bonuses; }>> /* Function to get total stat (base + bonuses) */ <<set setup.getTotalStat = function(statName) { var v = State.variables; var bonuses = setup.calculateStatBonuses(); var base = v.stats[statName]; /* Pharaoh: minimum base stats of 1000 */ if (v.physicalTraits && v.physicalTraits.includes("Pharaoh") && base < 1000) { base = 1000; } var total = base + bonuses[statName]; /* === TRANSFORMATION PERCENTAGE MODIFIERS === */ var percentMultiplier = 1.0; var flatBonus = 0; /* Vampire: Day -50%, Night +50% */ if (v.physicalTraits && v.physicalTraits.includes("Vampire")) { var vHour = Math.floor(v.timeInMinutes / 60) % 24; if (vHour >= 6 && vHour < 18) { percentMultiplier *= 0.5; } else { percentMultiplier *= 1.5; } } /* Pyrow: Clear weather + Day = +25% all stats */ if (v.physicalTraits && v.physicalTraits.includes("Pyrow") && v.currentWeather === "Clear") { var pHour = Math.floor(v.timeInMinutes / 60) % 24; if (pHour >= 6 && pHour < 18) { percentMultiplier *= 1.25; } } /* Fish trait: +20% all stats */ if (v.physicalTraits && v.physicalTraits.includes("Fish")) { percentMultiplier *= 1.2; } /* Banshee: +100 flat at night */ if (v.physicalTraits && v.physicalTraits.includes("Banshee")) { var bHour = Math.floor(v.timeInMinutes / 60) % 24; if (bHour < 6 || bHour >= 18) { flatBonus += 100; } } /* Automaton Overcharged buff: +300 flat all stats */ if (v.activeBuffs && v.activeBuffs.some(function(b) { return b.id === "automaton_overcharged"; })) { flatBonus += 300; } /* Jinko fish buffs: percentage boost */ if (v.activeBuffs) { var jinkoBuff = v.activeBuffs.find(function(b) { return b.id && b.id.indexOf("jinko_fish_") === 0; }); if (jinkoBuff && jinkoBuff.effects && jinkoBuff.effects.allStatsPercent) { percentMultiplier *= (1 + jinkoBuff.effects.allStatsPercent / 100); } } total = Math.floor(total * percentMultiplier) + flatBonus; return total; }>> /* Temperature immunity helper */ <<set setup.isTemperatureImmune = function() { var v = State.variables; if (!v.physicalTraits) return false; return v.physicalTraits.includes("Inferno") || v.physicalTraits.includes("Automaton") || v.physicalTraits.includes("Pyrow") || v.physicalTraits.includes("Salamander") || v.physicalTraits.includes("Pharaoh") || v.physicalTraits.includes("Half-Dragon Gyaru"); }>> /* Negative trait checker (for Angel purify) */ <<set setup.isNegativeTrait = function(traitName) { var bonus = setup.traitBonuses[traitName] || setup.skillBonuses[traitName]; if (!bonus) return false; var hasPositive = false; var hasNegative = false; for (var stat in bonus) { if (bonus[stat] > 0) hasPositive = true; if (bonus[stat] < 0) hasNegative = true; } return hasNegative && !hasPositive; }>> /* Pyrow clear+day bonus checker */ <<set setup.isPyrowBonusActive = function() { var v = State.variables; if (!v.physicalTraits || !v.physicalTraits.includes("Pyrow")) return false; if (v.currentWeather !== "Clear") return false; var hour = Math.floor(v.timeInMinutes / 60) % 24; return hour >= 6 && hour < 18; }>> /* Function to sync current traits into discoveredTraits for the encyclopedia */ <<set setup.syncDiscoveredTraits = function() { var v = State.variables; if (!v.discoveredTraits) { v.discoveredTraits = {physical: [], mental: [], skills: [], voice: [], jobs: [], body: []}; } if (!v.discoveredTraits.jobs) { v.discoveredTraits.jobs = []; } if (!v.discoveredTraits.body) { v.discoveredTraits.body = []; } var excluded = ["Criminal Deluxe", "Long Hair", "Short Hair", "Quill"]; /* Lab-generated (crafted) traits: tracked in craftedTraitBonuses. They are kept OUT of the Trait Encyclopedia, but still show in the Body menu. */ var craftedMap = v.craftedTraitBonuses || {}; var voiceList = setup.availableVoiceTraits ? Object.keys(setup.availableVoiceTraits) : []; voiceList = voiceList.concat(["Flat Uninterested Voice", "Slurred Speech", "Whiny Voice", "Gaelic Accent"]); if (v.physicalTraits) { v.physicalTraits.forEach(function(t) { if (excluded.indexOf(t) === -1 && !craftedMap[t] && v.discoveredTraits.physical.indexOf(t) === -1) { v.discoveredTraits.physical.push(t); } }); } if (v.mentalTraits) { v.mentalTraits.forEach(function(t) { if (excluded.indexOf(t) === -1 && !craftedMap[t]) { if (voiceList.indexOf(t) !== -1) { if (v.discoveredTraits.voice.indexOf(t) === -1) { v.discoveredTraits.voice.push(t); } } else { if (v.discoveredTraits.mental.indexOf(t) === -1) { v.discoveredTraits.mental.push(t); } } } }); } if (v.skills) { v.skills.forEach(function(t) { if (excluded.indexOf(t) === -1 && v.discoveredTraits.skills.indexOf(t) === -1) { v.discoveredTraits.skills.push(t); } }); } if (v.jobs) { v.jobs.forEach(function(t) { if (v.discoveredTraits.jobs.indexOf(t) === -1) { v.discoveredTraits.jobs.push(t); } }); } if (v.bodyParts) { var bpKeys = ["gender", "chest", "butt", "genitals"]; var bpLabels = {gender: "Gender", chest: "Chest", butt: "Butt", genitals: "Genitals"}; bpKeys.forEach(function(key) { if (v.bodyParts[key]) { var already = v.discoveredTraits.body.some(function(b) { return b.label === bpLabels[key] && b.value === v.bodyParts[key]; }); if (!already) { v.discoveredTraits.body.push({label: bpLabels[key], value: v.bodyParts[key]}); } } }); } v.discoveredTraits.physical = v.discoveredTraits.physical.filter(function(t) { return !craftedMap[t]; }); v.discoveredTraits.mental = v.discoveredTraits.mental.filter(function(t) { return !craftedMap[t]; }); /* Check for trait discovery achievements */ var totalDiscovered = v.discoveredTraits.physical.length + v.discoveredTraits.mental.length + v.discoveredTraits.skills.length + v.discoveredTraits.voice.length + v.discoveredTraits.jobs.length + v.discoveredTraits.body.length; if (totalDiscovered >= 5 && setup.achievements) { setup.achievements.unlock("trait_novice"); } if (totalDiscovered >= 30 && setup.achievements) { setup.achievements.unlock("trait_collector"); } if (totalDiscovered >= 75 && setup.achievements) { setup.achievements.unlock("trait_connoisseur"); } if (totalDiscovered >= 180 && setup.achievements) { setup.achievements.unlock("trait_expert"); } if (totalDiscovered >= 301 && setup.achievements) { setup.achievements.unlock("trait_encyclopedist"); } }>> /* Function to get trait description for encyclopedia */ <<set setup.getTraitDescription = function(traitName) { if (setup.availablePhysicalTraits && setup.availablePhysicalTraits[traitName]) return setup.availablePhysicalTraits[traitName]; if (setup.availableMentalTraits && setup.availableMentalTraits[traitName]) return setup.availableMentalTraits[traitName]; if (setup.availableVoiceTraits && setup.availableVoiceTraits[traitName]) return setup.availableVoiceTraits[traitName]; if (setup.availableSkills && setup.availableSkills[traitName]) return setup.availableSkills[traitName]; if (setup.stereotypeTraits && setup.stereotypeTraits[traitName]) return setup.stereotypeTraits[traitName]; return ""; }>> /* ---------------------------------- */ /* --- TRAIT COMBINATION FUNCTIONS --- */ /* ---------------------------------- */ /* Check if a trait combination is valid - supports 2 or 3+ traits */ /* Returns combo data or null. Traits are sorted alphabetically for key lookup */ <<set setup.isValidTraitCombination = function(traits) { /* Convert to array if 2 args passed */ if (!Array.isArray(traits)) { traits = Array.prototype.slice.call(arguments); } /* Sort alphabetically to create consistent key */ var sortedTraits = traits.slice().sort(); var key = sortedTraits.join("|"); return setup.traitCombinations[key] || null; }>> /* Check if a combination was already tried and failed (blacklisted) */ /* Supports arrays of any length */ <<set setup.hasFailedCombination = function(traits) { if (!Array.isArray(traits)) { traits = Array.prototype.slice.call(arguments); } var v = State.variables; if (!v.failedTraitCombinations) return false; var sortedKey = traits.slice().sort().join("|"); return v.failedTraitCombinations.indexOf(sortedKey) !== -1; }>> /* Add a combination to the failed/blacklist array */ <<set setup.addFailedCombination = function(traits) { if (!Array.isArray(traits)) { traits = Array.prototype.slice.call(arguments); } var v = State.variables; if (!v.failedTraitCombinations) v.failedTraitCombinations = []; var sortedKey = traits.slice().sort().join("|"); if (v.failedTraitCombinations.indexOf(sortedKey) === -1) { if (v.failedTraitCombinations.length >= 100) { v.failedTraitCombinations.shift(); } v.failedTraitCombinations.push(sortedKey); } }>> /* Check if a trait appears in any recipe */ <<set setup.isTraitInAnyRecipe = function(traitName) { for (var key in setup.traitCombinations) { var traits = key.split("|"); if (traits.indexOf(traitName) !== -1) { return true; } } return false; }>> /* Get all recipes that contain a specific trait */ <<set setup.getRecipesContainingTrait = function(traitName) { var recipes = []; for (var key in setup.traitCombinations) { var traits = key.split("|"); if (traits.indexOf(traitName) !== -1) { recipes.push({ key: key, traits: traits, result: setup.traitCombinations[key].result }); } } return recipes; }>> /* Get trait recipe status for coloring - returns: 'none', 'inRecipe', 'partialMatch', 'twoMatch', 'complete' */ <<set setup.getTraitRecipeStatus = function(traitName, selectedTraits) { selectedTraits = selectedTraits || []; /* Check if this trait is in any recipe at all */ var inAnyRecipe = setup.isTraitInAnyRecipe(traitName); if (!inAnyRecipe) return 'none'; /* If no traits selected yet, just show it's in a recipe (orange) */ if (selectedTraits.length === 0) return 'inRecipe'; /* Get all recipes containing this trait */ var recipesWithTrait = setup.getRecipesContainingTrait(traitName); /* Check each recipe to see how many selected traits match */ var bestMatch = 0; for (var i = 0; i < recipesWithTrait.length; i++) { var recipe = recipesWithTrait[i]; var matchCount = 0; for (var j = 0; j < selectedTraits.length; j++) { if (recipe.traits.indexOf(selectedTraits[j]) !== -1) { matchCount++; } } /* Also count this trait itself if it would complete a match */ if (recipe.traits.indexOf(traitName) !== -1) { matchCount++; } if (matchCount > bestMatch) { bestMatch = matchCount; } } if (bestMatch >= 3) return 'complete'; if (bestMatch === 2) return 'twoMatch'; if (bestMatch === 1) return 'partialMatch'; return 'inRecipe'; }>> /* Check if selected traits form a complete recipe */ <<set setup.isCompleteRecipe = function(selectedTraits) { if (!selectedTraits || selectedTraits.length !== 3) return null; var sortedTraits = selectedTraits.slice().sort(); var key = sortedTraits.join("|"); return setup.traitCombinations[key] || null; }>> /* Get discovered recipes (successful combinations) */ <<set setup.getDiscoveredRecipes = function() { var v = State.variables; if (!v.discoveredRecipes) v.discoveredRecipes = []; return v.discoveredRecipes; }>> /* Add a recipe to discovered list */ <<set setup.addDiscoveredRecipe = function(recipeKey, resultName) { var v = State.variables; if (!v.discoveredRecipes) v.discoveredRecipes = []; /* Check if already discovered */ for (var i = 0; i < v.discoveredRecipes.length; i++) { if (v.discoveredRecipes[i].key === recipeKey) return; } v.discoveredRecipes.push({ key: recipeKey, traits: recipeKey.split("|"), result: resultName }); }>> /* Main trait combination attempt function - supports 2 or 3+ traits */ <<set setup.attemptTraitCombination = function(traits) { if (!Array.isArray(traits)) { traits = Array.prototype.slice.call(arguments); } var result = { success: false, message: "", newTrait: null, consumed: false, isFullTransformation: false }; /* Oni: lab equipment rejects demonic presence; no trait combination allowed. */ if (State.variables.physicalTraits && State.variables.physicalTraits.indexOf("Oni") !== -1) { result.message = "The lab equipment shrinks from your touch. Whatever you are now, the combiner will not accept it."; result.consumed = false; return result; } /* Clair form: this body is borrowed and will not be rewritten */ if (State.variables.clairFormActive) { result.message = "This shape is Clair's, lent whole. The combiner cannot touch it. Return to your own form first."; result.consumed = false; return result; } /* Witch form: cannot combine traits into transformations */ if (State.variables.witchFormActive) { result.message = "The Witch's Amulet interferes with the combiner. You must deactivate it first."; result.consumed = false; return result; } /* Check if already tried this invalid combo (don't consume use) */ if (setup.hasFailedCombination(traits)) { result.message = "You've already determined these traits cannot be combined."; result.consumed = false; return result; } /* This attempt will consume a daily trade */ result.consumed = true; /* Get valid combination */ var combo = setup.isValidTraitCombination(traits); if (!combo) { /* Invalid combination - auto fail, add to blacklist */ setup.addFailedCombination(traits); result.message = "The experiment failed! These traits are fundamentally incompatible. This combination has been recorded in your research notes."; return result; } /* Check for special requirements */ if (combo.requiresTier4Rod) { var v = State.variables; var hasTier4Rod = (v.fishingPole && v.fishingPole >= 4) || (v.hasSunfishRod === true); if (!hasTier4Rod) { result.message = "You sense these traits could combine into something powerful, but you don't meet the requirements yet... maybe try more fishing?"; result.consumed = false; return result; } } /* Valid combination - 100% success */ result.success = true; result.newTrait = combo.result; result.isFullTransformation = combo.isFullTransformation || false; result.message = "Success! The traits have been combined."; /* Add to discovered recipes */ var sortedTraits = traits.slice().sort(); var recipeKey = sortedTraits.join("|"); setup.addDiscoveredRecipe(recipeKey, combo.result); return result; }>> /* Apply a full transformation - grants traits and handles appearance override */ <<set setup.applyFullTransformation = function(transformationName) { var v = State.variables; if (v.clairFormActive) return false; if (setup.cafe && setup.cafe.isPlayerLifeswappedAsMaid && setup.cafe.isPlayerLifeswappedAsMaid()) { if (typeof UI !== "undefined" && UI.alert) { UI.alert("You can't transform while inhabiting " + v.lifeSwapPortraitSource + "'s body. Return to your own body first."); } return false; } var transform = setup.fullTransformations[transformationName]; if (!transform) return false; /* Voluptuous Succubus blocks all other lab transformations from being gained — the player is locked into this form until V-Succubus is removed (e.g. via storage). */ if (transformationName !== "Voluptuous Succubus" && v.physicalTraits && v.physicalTraits.indexOf("Voluptuous Succubus") !== -1) { if (typeof UI !== "undefined" && UI.alert) { UI.alert("Voluptuous Succubus blocks other transformations. Store the trait first."); } return false; } /* Initialize tracking if needed */ if (!v.transformationGrantedTraits) v.transformationGrantedTraits = {}; if (!v.transformationGrantedTraits[transformationName]) { v.transformationGrantedTraits[transformationName] = { physical: [], mental: [] }; } /* Remove ALL previous laboratory transformation traits before applying new one */ var allLabTransforms = [ "Succubus", "Imp", "Cerberus", /* "Incubus", - temporarily disabled */ "Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep", "Hucow", "Trophy Wife", "Ojou", "Gym Bunny", "E-Girl", "Punk", "Gyaru", "Siren", "Living Doll", "Dominatrix", "Slut", "Himbo", "Angel", "Naiad", "Automaton", "Banshee", "Cheshire Cat", "Cupid", "Dark Angel", "Honeybee", "Jinko", "Kakuen", "Lizardman", "Ocelomeh", "Pyrow", "Raiju", "Salamander", "Satyros", "Vampire", "Kitsune", "Anubis", "Pharaoh", "Witch", "Voluptuous Succubus", "Slime", "Oni", "Femboy", "Half-Dragon Gyaru" ]; /* When applying Voluptuous Succubus, the Succubus trait is preserved by the lab-transforms removal loop below and re-granted via grantsPhysical, so the player benefits from all Succubus checks while V-Succubus is active. */ /* Restore pre-transformation sizes if removing Voluptuous Succubus */ if (transformationName !== "Voluptuous Succubus" && v.physicalTraits && v.physicalTraits.indexOf("Voluptuous Succubus") !== -1) { if (v.voluptuousSuccubusPreSizes) { v.bodyParts.chest = v.voluptuousSuccubusPreSizes.chest; v.bodyParts.butt = v.voluptuousSuccubusPreSizes.butt; v.voluptuousSuccubusPreSizes = null; } } /* Witch transformation: dual-form system */ if (transformationName === "Witch") { /* Block Witch activation while player is slime-bodied or slime-possessing */ if (setup.slime && (setup.slime.isPlayerSlimeBodied() || v.slimePossessionActive === true)) { return false; } /* Save the player's current (normal) form before transforming */ /* Always save current state so changes to normal form persist across transforms */ v.witchOriginalForm = { physical: v.physicalTraits ? v.physicalTraits.slice() : [], mental: v.mentalTraits ? v.mentalTraits.slice() : [], skills: v.skills ? v.skills.slice() : [], voice: v.voiceTraits ? v.voiceTraits.slice() : [], gender: v.gender || (v.bodyParts ? v.bodyParts.gender : "male"), bodyParts: { gender: v.bodyParts ? v.bodyParts.gender : "male", chest: v.bodyParts ? v.bodyParts.chest : "flat", butt: v.bodyParts ? v.bodyParts.butt : "flat", genitals: v.bodyParts ? v.bodyParts.genitals : "penis" }, appearance: { skinTone: v.appearance ? v.appearance.skinTone : "fair", hairColor: v.appearance ? v.appearance.hairColor : "Brown", hairStyle: v.appearance ? v.appearance.hairStyle : "short", hairLength: v.appearance ? v.appearance.hairLength : "short", eyeColor: v.appearance ? v.appearance.eyeColor : "brown" }, stats: { strength: v.strength || 0, dexterity: v.dexterity || 0, charisma: v.charisma || 0, intelligence: v.intelligence || 0 }, firstName: v.firstName || "Unknown", lastName: v.lastName || "Person", relationships: v.relationships ? JSON.parse(JSON.stringify(v.relationships)) : {}, npcRelationships: v.npcRelationships ? JSON.parse(JSON.stringify(v.npcRelationships)) : {}, metNPCs: v.metNPCs ? v.metNPCs.slice() : [], portraitSource: v.lifeSwapPortraitSource || "player", customImages: v.imageSettings ? JSON.parse(JSON.stringify(v.imageSettings.customImages)) : {face: "", chest: "", butt: ""} }; /* Swap to witch name and relationships */ if (v.witchSavedForm && v.witchSavedForm.firstName) { v.firstName = v.witchSavedForm.firstName; v.lastName = v.witchSavedForm.lastName; } else if (v.witchFirstName) { v.firstName = v.witchFirstName; v.lastName = v.witchLastName || ""; } if (v.witchSavedForm && v.witchSavedForm.relationships) { v.relationships = JSON.parse(JSON.stringify(v.witchSavedForm.relationships)); if (v.witchSavedForm.npcRelationships) v.npcRelationships = JSON.parse(JSON.stringify(v.witchSavedForm.npcRelationships)); if (v.witchSavedForm.metNPCs) v.metNPCs = v.witchSavedForm.metNPCs.slice(); } else if (v.witchRelationships) { v.relationships = JSON.parse(JSON.stringify(v.witchRelationships)); if (v.witchNpcRelationships) v.npcRelationships = JSON.parse(JSON.stringify(v.witchNpcRelationships)); if (v.witchMetNPCs) v.metNPCs = v.witchMetNPCs.slice(); } /* Swap portrait if witch has its own */ if (v.witchSavedForm && v.witchSavedForm.portraitSource) { if (v.witchSavedForm.portraitSource === "player") { delete v.lifeSwapPortraitSource; } else { v.lifeSwapPortraitSource = v.witchSavedForm.portraitSource; } if (v.witchSavedForm.customImages) v.imageSettings.customImages = JSON.parse(JSON.stringify(v.witchSavedForm.customImages)); } /* Check if we have a saved Witch form to restore */ if (v.witchSavedForm) { /* Restore saved Witch form (player modified it previously) */ v.physicalTraits = v.witchSavedForm.physical.slice(); v.mentalTraits = v.witchSavedForm.mental.slice(); v.skills = v.witchSavedForm.skills.slice(); if (v.witchSavedForm.voice) v.voiceTraits = v.witchSavedForm.voice.slice(); v.bodyParts.gender = v.witchSavedForm.bodyParts.gender; v.gender = v.witchSavedForm.gender || v.witchSavedForm.bodyParts.gender; v.bodyParts.chest = v.witchSavedForm.bodyParts.chest; v.bodyParts.butt = v.witchSavedForm.bodyParts.butt; v.bodyParts.genitals = v.witchSavedForm.bodyParts.genitals; v.appearance.skinTone = v.witchSavedForm.appearance.skinTone; v.appearance.hairColor = v.witchSavedForm.appearance.hairColor; v.appearance.hairStyle = v.witchSavedForm.appearance.hairStyle; if (v.witchSavedForm.appearance.hairLength !== undefined) v.appearance.hairLength = v.witchSavedForm.appearance.hairLength; v.appearance.eyeColor = v.witchSavedForm.appearance.eyeColor; v.strength = v.witchSavedForm.stats.strength; v.dexterity = v.witchSavedForm.stats.dexterity; v.charisma = v.witchSavedForm.stats.charisma; v.intelligence = v.witchSavedForm.stats.intelligence; delete v.witchSavedForm; } else if (v.witchFormTraits) { /* First time or fresh Witch form: apply traits from Xanithar */ var wt = v.witchFormTraits; if (wt.mental) { for (var wmi = 0; wmi < wt.mental.length; wmi++) { if (!v.mentalTraits) v.mentalTraits = []; if (v.mentalTraits.indexOf(wt.mental[wmi]) === -1) v.mentalTraits.push(wt.mental[wmi]); } } if (wt.physical) { for (var wpi = 0; wpi < wt.physical.length; wpi++) { if (!v.physicalTraits) v.physicalTraits = []; if (v.physicalTraits.indexOf(wt.physical[wpi]) === -1) v.physicalTraits.push(wt.physical[wpi]); } } if (wt.skills) { for (var wsi = 0; wsi < wt.skills.length; wsi++) { if (!v.skills) v.skills = []; if (v.skills.indexOf(wt.skills[wsi]) === -1) v.skills.push(wt.skills[wsi]); } } /* Set pale skin */ if (v.bodyParts) v.bodyParts.skinTone = "pale"; if (v.appearance) v.appearance.skinTone = "pale"; } v.witchFormActive = true; } /* Snapshot full pre-TF state so revertFullTransformation can fully restore the player. Skipped for Witch — handled above via the dual-form system. See setup.snapshotPreTransformationState. */ if (typeof setup.snapshotPreTransformationState === "function") { setup.snapshotPreTransformationState(transformationName); } allLabTransforms.forEach(function(oldTransform) { if (oldTransform !== transformationName) { /* Voluptuous Succubus inherits all Succubus bonuses — preserve the Succubus trait when applying V-Succubus so existing Succubus checks across the codebase fire while V-Succubus is active. */ if (transformationName === "Voluptuous Succubus" && oldTransform === "Succubus") return; if (v.physicalTraits) { var pIdx = v.physicalTraits.indexOf(oldTransform); if (pIdx !== -1) v.physicalTraits.splice(pIdx, 1); } if (v.mentalTraits) { var mIdx = v.mentalTraits.indexOf(oldTransform); if (mIdx !== -1) v.mentalTraits.splice(mIdx, 1); } } }); /* Check gender lock - change gender if needed */ if (transform.genderLock) { var currentGender = v.bodyParts && v.bodyParts.gender ? v.bodyParts.gender.toLowerCase() : ""; if (transform.genderLock === "female" && currentGender !== "female") { if (!v.bodyParts) v.bodyParts = {}; v.bodyParts.gender = "female"; v.gender = "female"; v.bodyParts.genitals = "vagina"; /* Update appearance for feminine body */ if (!v.appearance) v.appearance = {}; } if (transform.genderLock === "male" && currentGender !== "male") { if (!v.bodyParts) v.bodyParts = {}; v.bodyParts.gender = "male"; v.gender = "male"; v.bodyParts.genitals = "penis"; /* Update appearance for masculine body */ if (!v.appearance) v.appearance = {}; } } /* Apply body part changes from transformation */ if (!v.bodyParts) v.bodyParts = {}; var sizeOrder = ["flat","flat masculine","small","medium","large","huge","giant","gigantic"]; /* Save pre-transformation sizes for Voluptuous Succubus (restored on removal) */ if (transformationName === "Voluptuous Succubus") { v.voluptuousSuccubusPreSizes = { chest: v.bodyParts.chest || "flat", butt: v.bodyParts.butt || "flat" }; } if (transform.setsChest) { if (transform.setsChestMinimum) { var curIdx = sizeOrder.indexOf(v.bodyParts.chest); var newIdx = sizeOrder.indexOf(transform.setsChest); if (curIdx < newIdx) v.bodyParts.chest = transform.setsChest; } else { v.bodyParts.chest = transform.setsChest; } } if (transform.setsButt) { if (transform.setButtMinimum) { var curIdx = sizeOrder.indexOf(v.bodyParts.butt); var newIdx = sizeOrder.indexOf(transform.setsButt); if (curIdx < newIdx) v.bodyParts.butt = transform.setsButt; } else { v.bodyParts.butt = transform.setsButt; } } if (transform.setsGenitals) { v.bodyParts.genitals = transform.setsGenitals; setup.checkFutanariConsistency(); } if (transform.setsHairColor) { if (!v.appearance) v.appearance = {}; v.appearance.hairColor = transform.setsHairColor; } if (transform.setsSkinTone) { if (!v.appearance) v.appearance = {}; v.appearance.skinTone = transform.setsSkinTone; } /* Mature adult size bump: increase chest and butt by one tier */ if (transform.matureAdultBump && v.bodyParts.age === "mature adult") { var chestIdx = sizeOrder.indexOf(v.bodyParts.chest); if (chestIdx >= 0 && chestIdx < sizeOrder.length - 1) { v.bodyParts.chest = sizeOrder[chestIdx + 1]; } var buttIdx = sizeOrder.indexOf(v.bodyParts.butt); if (buttIdx >= 0 && buttIdx < sizeOrder.length - 1) { v.bodyParts.butt = sizeOrder[buttIdx + 1]; } } /* Remove conflicting traits */ if (transform.removesOnGain && transform.removesOnGain.length > 0) { transform.removesOnGain.forEach(function(trait) { if (v.physicalTraits) { var pIdx = v.physicalTraits.indexOf(trait); if (pIdx !== -1) v.physicalTraits.splice(pIdx, 1); } if (v.mentalTraits) { var mIdx = v.mentalTraits.indexOf(trait); if (mIdx !== -1) v.mentalTraits.splice(mIdx, 1); } }); } /* Grant physical traits */ if (transform.grantsPhysical && transform.grantsPhysical.length > 0) { transform.grantsPhysical.forEach(function(trait) { if (!v.physicalTraits) v.physicalTraits = []; if (v.physicalTraits.indexOf(trait) === -1) { v.physicalTraits.push(trait); v.transformationGrantedTraits[transformationName].physical.push(trait); } }); } /* Grant mental traits */ if (transform.grantsMental && transform.grantsMental.length > 0) { transform.grantsMental.forEach(function(trait) { if (!v.mentalTraits) v.mentalTraits = []; if (v.mentalTraits.indexOf(trait) === -1) { v.mentalTraits.push(trait); v.transformationGrantedTraits[transformationName].mental.push(trait); } }); } /* Add the transformation trait itself */ if (transform.category === "physical") { if (!v.physicalTraits) v.physicalTraits = []; if (v.physicalTraits.indexOf(transformationName) === -1) { v.physicalTraits.push(transformationName); } } else { if (!v.mentalTraits) v.mentalTraits = []; if (v.mentalTraits.indexOf(transformationName) === -1) { v.mentalTraits.push(transformationName); } } /* Track active transformation for appearance override */ v.activeTransformation = transformationName; /* Unlock transformation achievement */ var achId = setup.transformAchievementMap[transformationName]; if (achId && setup.achievements && setup.achievements.unlock) { setup.achievements.unlock(achId); } return true; }>> /* ------------------------------------------------------------- Pre-transformation state snapshot / restore ------------------------------------------------------------- applyFullTransformation / applyTransformationSilent mutate body parts, gender, hair color, and strip existing traits/skills via removesOnGain / removesPhysicalOnGain / removesSkillsOnGain. The original revert function only removed the TF trait + its granted traits, leaving body/gender/hair/removed-traits untouched, so "Revert Transformation" was only a partial revert. These helpers snapshot the full player state BEFORE any TF mods, and restore it on revert. Witch uses its own dual-form system (witchOriginalForm / witchSavedForm) — we skip both snapshot and restore for Witch so those paths are unaffected. ------------------------------------------------------------- */ <<set setup.snapshotPreTransformationState = function(transformationName) { if (transformationName === "Witch") return; var v = State.variables; if (!v.transformationPreStates) v.transformationPreStates = {}; /* Only snapshot if we don't already have one — avoids clobbering the true pre-TF state if apply is called twice in a row. */ if (v.transformationPreStates[transformationName]) return; v.transformationPreStates[transformationName] = { physicalTraits: v.physicalTraits ? v.physicalTraits.slice() : [], mentalTraits: v.mentalTraits ? v.mentalTraits.slice() : [], skills: v.skills ? v.skills.slice() : [], voiceTraits: v.voiceTraits ? v.voiceTraits.slice() : [], bodyParts: v.bodyParts ? { gender: v.bodyParts.gender, chest: v.bodyParts.chest, butt: v.bodyParts.butt, genitals: v.bodyParts.genitals, age: v.bodyParts.age } : null, appearance: v.appearance ? { skinTone: v.appearance.skinTone, hairColor: v.appearance.hairColor, hairStyle: v.appearance.hairStyle, hairLength: v.appearance.hairLength, age: v.appearance.age, eyeColor: v.appearance.eyeColor } : null, gender: v.gender }; }>> <<set setup.restorePreTransformationState = function(transformationName) { if (transformationName === "Witch") return false; var v = State.variables; var snap = (v.transformationPreStates && v.transformationPreStates[transformationName]) ? v.transformationPreStates[transformationName] : null; if (snap) { /* Restore ONLY the traits the transformation explicitly removed when applied (removesOnGain / removesPhysicalOnGain / removesSkillsOnGain), and only if the player had them in the pre-TF snapshot. Do NOT wholesale replace the trait arrays - that would discard any trait the player gained between applying the TF and reverting it (the "storing Succubus wipes recent traits" bug). Body parts, gender, and appearance below still get a full restore since those ARE directly mutated by the TF. */ var restoreTransform = setup.fullTransformations && setup.fullTransformations[transformationName]; if (restoreTransform && snap.physicalTraits && restoreTransform.removesPhysicalOnGain) { if (!v.physicalTraits) v.physicalTraits = []; restoreTransform.removesPhysicalOnGain.forEach(function(t) { if (snap.physicalTraits.indexOf(t) !== -1 && v.physicalTraits.indexOf(t) === -1) { v.physicalTraits.push(t); } }); } if (restoreTransform && snap.mentalTraits && restoreTransform.removesOnGain) { if (!v.mentalTraits) v.mentalTraits = []; restoreTransform.removesOnGain.forEach(function(t) { if (snap.mentalTraits.indexOf(t) !== -1 && v.mentalTraits.indexOf(t) === -1) { v.mentalTraits.push(t); } }); } if (restoreTransform && snap.skills && restoreTransform.removesSkillsOnGain) { if (!v.skills) v.skills = []; restoreTransform.removesSkillsOnGain.forEach(function(t) { if (snap.skills.indexOf(t) !== -1 && v.skills.indexOf(t) === -1) { v.skills.push(t); } }); } /* voiceTraits: no known TF strips voice traits, but future-proof with the same merge pattern should one be added. */ if (restoreTransform && snap.voiceTraits && restoreTransform.removesVoiceOnGain) { if (!v.voiceTraits) v.voiceTraits = []; restoreTransform.removesVoiceOnGain.forEach(function(t) { if (snap.voiceTraits.indexOf(t) !== -1 && v.voiceTraits.indexOf(t) === -1) { v.voiceTraits.push(t); } }); } /* Body / appearance / gender restoration: ONLY for Voluptuous Succubus. Other transformations leave their body changes in place after revert so the player keeps the body shape they earned. (V-Succubus has its own voluptuousSuccubusPreSizes mechanism that runs in revertFullTransformation; the snapshot path is a redundant safety net for V-Succubus only.) */ if (transformationName === "Voluptuous Succubus") { if (snap.bodyParts) { if (!v.bodyParts) v.bodyParts = {}; if (snap.bodyParts.gender !== undefined) v.bodyParts.gender = snap.bodyParts.gender; if (snap.bodyParts.chest !== undefined) v.bodyParts.chest = snap.bodyParts.chest; if (snap.bodyParts.butt !== undefined) v.bodyParts.butt = snap.bodyParts.butt; if (snap.bodyParts.genitals !== undefined) v.bodyParts.genitals = snap.bodyParts.genitals; if (snap.bodyParts.age !== undefined) v.bodyParts.age = snap.bodyParts.age; } if (snap.appearance) { if (!v.appearance) v.appearance = {}; if (snap.appearance.skinTone !== undefined) v.appearance.skinTone = snap.appearance.skinTone; if (snap.appearance.hairColor !== undefined) v.appearance.hairColor = snap.appearance.hairColor; if (snap.appearance.hairStyle !== undefined) v.appearance.hairStyle = snap.appearance.hairStyle; if (snap.appearance.hairLength !== undefined) v.appearance.hairLength = snap.appearance.hairLength; if (snap.appearance.age !== undefined) v.appearance.age = snap.appearance.age; if (snap.appearance.eyeColor !== undefined) v.appearance.eyeColor = snap.appearance.eyeColor; } if (snap.gender !== undefined) { v.gender = snap.gender; } else if (snap.bodyParts && snap.bodyParts.gender !== undefined) { v.gender = snap.bodyParts.gender; } } /* Oni: restore pre-TF hair color on revert so storing the trait gives the player back their original hair color. Body / gender / skin tone / other appearance stay as-is so the player keeps the rest of the Oni body. */ if (transformationName === "Oni" && snap.appearance && v.appearance) { if (snap.appearance.hairColor !== undefined) { v.appearance.hairColor = snap.appearance.hairColor; } } if (transformationName === "Femboy") { if (snap.bodyParts) { if (!v.bodyParts) v.bodyParts = {}; if (snap.bodyParts.gender !== undefined) v.bodyParts.gender = snap.bodyParts.gender; if (snap.bodyParts.chest !== undefined) v.bodyParts.chest = snap.bodyParts.chest; if (snap.bodyParts.butt !== undefined) v.bodyParts.butt = snap.bodyParts.butt; if (snap.bodyParts.genitals !== undefined) v.bodyParts.genitals = snap.bodyParts.genitals; if (snap.bodyParts.age !== undefined) v.bodyParts.age = snap.bodyParts.age; } if (snap.appearance) { if (!v.appearance) v.appearance = {}; if (snap.appearance.skinTone !== undefined) v.appearance.skinTone = snap.appearance.skinTone; if (snap.appearance.hairColor !== undefined) v.appearance.hairColor = snap.appearance.hairColor; if (snap.appearance.age !== undefined) v.appearance.age = snap.appearance.age; } if (snap.gender !== undefined) { v.gender = snap.gender; } else if (snap.bodyParts && snap.bodyParts.gender !== undefined) { v.gender = snap.bodyParts.gender; } } delete v.transformationPreStates[transformationName]; return true; } /* FALLBACK for saves where the TF was applied before the snapshot system existed. ONLY runs for Voluptuous Succubus — other transformations keep their body changes after revert. */ if (transformationName !== "Voluptuous Succubus") return false; if (!v.bodyParts) v.bodyParts = {}; var didRestore = false; if (v.preTransformGender !== undefined && v.preTransformGender !== null) { v.bodyParts.gender = v.preTransformGender; v.gender = v.preTransformGender; didRestore = true; } if (v.preTransformChest !== undefined && v.preTransformChest !== null) { v.bodyParts.chest = v.preTransformChest; didRestore = true; } if (v.preTransformButt !== undefined && v.preTransformButt !== null) { v.bodyParts.butt = v.preTransformButt; didRestore = true; } if (v.preTransformGenitals !== undefined && v.preTransformGenitals !== null) { v.bodyParts.genitals = v.preTransformGenitals; didRestore = true; } if (v.preTransformAge !== undefined && v.preTransformAge !== null) { if (!v.appearance) v.appearance = {}; v.appearance.age = v.preTransformAge; didRestore = true; } return didRestore; }>> /* Revert a full transformation - removes granted traits */ <<set setup.revertFullTransformation = function(transformationName) { var v = State.variables; if (v.clairFormActive) return false; if (v.slimePossessionActive === true && setup.slimePossession && typeof setup.slimePossession.revertSlimePossession === "function") { setup.slimePossession.revertSlimePossession(true); } var transform = setup.fullTransformations[transformationName]; if (!transform) return false; /* Cerberus three-head: drop the per-form trait split so mental traits revert to the flat list. Names are kept (persist). */ if (transformationName === "Cerberus") { v.cerberusHeadMap = {}; } /* Restore pre-transformation body sizes for Voluptuous Succubus */ if (transformationName === "Voluptuous Succubus" && v.voluptuousSuccubusPreSizes) { v.bodyParts.chest = v.voluptuousSuccubusPreSizes.chest; v.bodyParts.butt = v.voluptuousSuccubusPreSizes.butt; v.voluptuousSuccubusPreSizes = null; } /* Remove the transformation trait itself */ if (transform.category === "physical" && v.physicalTraits) { var pIdx = v.physicalTraits.indexOf(transformationName); if (pIdx !== -1) v.physicalTraits.splice(pIdx, 1); } else if (v.mentalTraits) { var mIdx = v.mentalTraits.indexOf(transformationName); if (mIdx !== -1) v.mentalTraits.splice(mIdx, 1); } /* Remove traits that were granted by this transformation */ if (v.transformationGrantedTraits && v.transformationGrantedTraits[transformationName]) { var granted = v.transformationGrantedTraits[transformationName]; /* Remove granted physical traits */ if (granted.physical && v.physicalTraits) { granted.physical.forEach(function(trait) { var idx = v.physicalTraits.indexOf(trait); if (idx !== -1) v.physicalTraits.splice(idx, 1); }); } /* Remove granted mental traits */ if (granted.mental && v.mentalTraits) { granted.mental.forEach(function(trait) { var idx = v.mentalTraits.indexOf(trait); if (idx !== -1) v.mentalTraits.splice(idx, 1); }); } /* Clear the tracking */ delete v.transformationGrantedTraits[transformationName]; } /* Witch revert: save current Witch form, restore original form */ if (transformationName === "Witch") { /* Save current Witch form state so it can be restored later */ v.witchSavedForm = { physical: v.physicalTraits ? v.physicalTraits.slice() : [], mental: v.mentalTraits ? v.mentalTraits.slice() : [], skills: v.skills ? v.skills.slice() : [], voice: v.voiceTraits ? v.voiceTraits.slice() : [], gender: v.gender || (v.bodyParts ? v.bodyParts.gender : "female"), bodyParts: { gender: v.bodyParts ? v.bodyParts.gender : "female", chest: v.bodyParts ? v.bodyParts.chest : "huge", butt: v.bodyParts ? v.bodyParts.butt : "giant", genitals: v.bodyParts ? v.bodyParts.genitals : "vagina" }, appearance: { skinTone: v.appearance ? v.appearance.skinTone : "pale", hairColor: v.appearance ? v.appearance.hairColor : "Black", hairStyle: v.appearance ? v.appearance.hairStyle : "long", hairLength: v.appearance ? v.appearance.hairLength : "long", eyeColor: v.appearance ? v.appearance.eyeColor : "purple" }, stats: { strength: v.strength || 0, dexterity: v.dexterity || 0, charisma: v.charisma || 0, intelligence: v.intelligence || 0 }, firstName: v.firstName || "", lastName: v.lastName || "", relationships: v.relationships ? JSON.parse(JSON.stringify(v.relationships)) : {}, npcRelationships: v.npcRelationships ? JSON.parse(JSON.stringify(v.npcRelationships)) : {}, metNPCs: v.metNPCs ? v.metNPCs.slice() : [], portraitSource: v.lifeSwapPortraitSource || "player", customImages: v.imageSettings ? JSON.parse(JSON.stringify(v.imageSettings.customImages)) : {face: "", chest: "", butt: ""} }; /* Restore original form if saved (witchOriginalForm is PERMANENT, never deleted) */ if (v.witchOriginalForm) { v.physicalTraits = v.witchOriginalForm.physical.slice(); v.mentalTraits = v.witchOriginalForm.mental.slice(); v.skills = v.witchOriginalForm.skills.slice(); if (v.witchOriginalForm.voice) v.voiceTraits = v.witchOriginalForm.voice.slice(); if (v.bodyParts) { v.bodyParts.gender = v.witchOriginalForm.bodyParts.gender; v.bodyParts.chest = v.witchOriginalForm.bodyParts.chest; v.bodyParts.butt = v.witchOriginalForm.bodyParts.butt; v.bodyParts.genitals = v.witchOriginalForm.bodyParts.genitals; } /* Restore top-level gender variable */ v.gender = v.witchOriginalForm.gender || v.witchOriginalForm.bodyParts.gender; if (v.appearance) { v.appearance.skinTone = v.witchOriginalForm.appearance.skinTone; v.appearance.hairColor = v.witchOriginalForm.appearance.hairColor; v.appearance.hairStyle = v.witchOriginalForm.appearance.hairStyle; if (v.witchOriginalForm.appearance.hairLength !== undefined) v.appearance.hairLength = v.witchOriginalForm.appearance.hairLength; v.appearance.eyeColor = v.witchOriginalForm.appearance.eyeColor; } v.strength = v.witchOriginalForm.stats.strength; v.dexterity = v.witchOriginalForm.stats.dexterity; v.charisma = v.witchOriginalForm.stats.charisma; v.intelligence = v.witchOriginalForm.stats.intelligence; /* Restore original name */ if (v.witchOriginalForm.firstName) { v.firstName = v.witchOriginalForm.firstName; v.lastName = v.witchOriginalForm.lastName; } /* Restore original relationships */ if (v.witchOriginalForm.relationships) { v.relationships = JSON.parse(JSON.stringify(v.witchOriginalForm.relationships)); if (v.witchOriginalForm.npcRelationships) v.npcRelationships = JSON.parse(JSON.stringify(v.witchOriginalForm.npcRelationships)); if (v.witchOriginalForm.metNPCs) v.metNPCs = v.witchOriginalForm.metNPCs.slice(); } /* Restore original portrait */ if (v.witchOriginalForm.portraitSource) { if (v.witchOriginalForm.portraitSource === "player") { delete v.lifeSwapPortraitSource; } else { v.lifeSwapPortraitSource = v.witchOriginalForm.portraitSource; } if (v.witchOriginalForm.customImages) v.imageSettings.customImages = JSON.parse(JSON.stringify(v.witchOriginalForm.customImages)); } /* DO NOT delete witchOriginalForm - it is permanent (pre-amulet body) */ } else if (v.witchFormTraits) { /* Fallback: old-style revert if no original form saved */ var wt = v.witchFormTraits; if (wt.mental && v.mentalTraits) { for (var wmi = wt.mental.length - 1; wmi >= 0; wmi--) { var wmIdx = v.mentalTraits.indexOf(wt.mental[wmi]); if (wmIdx !== -1) v.mentalTraits.splice(wmIdx, 1); } } if (wt.physical && v.physicalTraits) { for (var wpi = wt.physical.length - 1; wpi >= 0; wpi--) { var wpIdx = v.physicalTraits.indexOf(wt.physical[wpi]); if (wpIdx !== -1) v.physicalTraits.splice(wpIdx, 1); } } if (wt.skills && v.skills) { for (var wsi = wt.skills.length - 1; wsi >= 0; wsi--) { var wsIdx = v.skills.indexOf(wt.skills[wsi]); if (wsIdx !== -1) v.skills.splice(wsIdx, 1); } } } v.witchFormActive = false; } /* Full pre-TF state restore for non-Witch transformations. Runs AFTER the trait-removal logic above (so the TF trait + its granted traits are already gone); restores body parts, gender, hair/appearance, and any traits/skills the TF stripped via removesOnGain/removesPhysicalOnGain /removesSkillsOnGain. Delegates to setup.restorePreTransformationState, which is a no-op for Witch (dual-form system handles its own state). */ if (typeof setup.restorePreTransformationState === "function") { setup.restorePreTransformationState(transformationName); } /* Clear active transformation if this was it */ if (v.activeTransformation === transformationName) { v.activeTransformation = null; } return true; }>> /* Check if player has an active full transformation */ <<set setup.hasActiveTransformation = function() { var v = State.variables; return v.activeTransformation && setup.fullTransformations[v.activeTransformation]; }>> /* Get current transformation data */ <<set setup.getActiveTransformation = function() { var v = State.variables; if (!v.activeTransformation) return null; return setup.fullTransformations[v.activeTransformation] || null; }>> /* Get all traits that are blocked from being acquired due to current transformation */ <<set setup.getTransformationBlockedTraits = function() { var v = State.variables; var blocked = { physical: [], mental: [], skills: [] }; if (!v.activeTransformation) return blocked; var transform = setup.fullTransformations[v.activeTransformation]; if (!transform) return blocked; /* Block all traits granted by the current transformation */ if (transform.grantsPhysical) { blocked.physical = blocked.physical.concat(transform.grantsPhysical); } if (transform.grantsMental) { blocked.mental = blocked.mental.concat(transform.grantsMental); } /* Also block traits that are removed/blocked by the transformation */ if (transform.removesOnGain) { blocked.mental = blocked.mental.concat(transform.removesOnGain); } if (transform.removesPhysicalOnGain) { blocked.physical = blocked.physical.concat(transform.removesPhysicalOnGain); } if (transform.removesSkillsOnGain) { blocked.skills = blocked.skills.concat(transform.removesSkillsOnGain); } if (transform.blocksTraits) { blocked.mental = blocked.mental.concat(transform.blocksTraits); } if (transform.blocksPhysical) { blocked.physical = blocked.physical.concat(transform.blocksPhysical); } return blocked; }>> /* Check if a trait is blocked due to current transformation */ <<set setup.isTraitBlockedByTransformation = function(traitName, traitType) { var blocked = setup.getTransformationBlockedTraits(); if (traitType === "physical") { return blocked.physical.includes(traitName); } else if (traitType === "mental") { return blocked.mental.includes(traitName); } else if (traitType === "skill") { return blocked.skills.includes(traitName); } return false; }>> <<set setup.isBodyPartLockedByTransformation = function(partName) { var v = State.variables; if (setup.slime && setup.slime.isPlayerSlimeBodied()) return true; if (!v.activeTransformation) return false; var t = setup.fullTransformations[v.activeTransformation]; return !!(t && t.lockedBodyParts && t.lockedBodyParts.indexOf(partName) !== -1); }>> /* Check if a trait is a transformation trait (main trait that defines the transformation) */ <<set setup.isTransformationTrait = function(traitName) { return setup.fullTransformations && setup.fullTransformations[traitName] !== undefined; }>> /* Apply transformation silently (no cutscene) - used when receiving trait via trade */ <<set setup.applyTransformationSilent = function(transformationName) { var v = State.variables; var transform = setup.fullTransformations[transformationName]; if (!transform) return false; /* Snapshot full pre-TF state so a later revertFullTransformation can fully restore the player. See setup.snapshotPreTransformationState. */ if (typeof setup.snapshotPreTransformationState === "function") { setup.snapshotPreTransformationState(transformationName); } /* Remove ALL previous laboratory transformation traits before applying new one */ var allLabTransforms = [ "Succubus", "Imp", "Cerberus", "Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep", "Hucow", "Trophy Wife", "Ojou", "Gym Bunny", "E-Girl", "Punk", "Gyaru", "Siren", "Living Doll", "Dominatrix", "Slut", "Himbo", "Angel", "Naiad", "Automaton", "Banshee", "Cheshire Cat", "Cupid", "Dark Angel", "Honeybee", "Jinko", "Kakuen", "Lizardman", "Ocelomeh", "Pyrow", "Raiju", "Salamander", "Satyros", "Vampire", "Kitsune", "Anubis", "Pharaoh", "Oni", "Femboy", "Slime", "Half-Dragon Gyaru" ]; allLabTransforms.forEach(function(oldTransform) { if (oldTransform !== transformationName) { if (v.physicalTraits) { var pIdx = v.physicalTraits.indexOf(oldTransform); if (pIdx !== -1) v.physicalTraits.splice(pIdx, 1); } if (v.mentalTraits) { var mIdx = v.mentalTraits.indexOf(oldTransform); if (mIdx !== -1) v.mentalTraits.splice(mIdx, 1); } } }); /* If already have an active transformation, revert it first */ if (v.activeTransformation && v.activeTransformation !== transformationName) { setup.revertFullTransformation(v.activeTransformation); } /* Initialize tracking object if needed */ if (!v.transformationGrantedTraits) { v.transformationGrantedTraits = {}; } v.transformationGrantedTraits[transformationName] = { physical: [], mental: [] }; /* The main trait is already added via trade, so don't add it again */ /* But we need to set up the body changes and other effects */ /* Apply body changes if transformation has them */ if (v.bodyParts) { var sizeOrder = ["flat","flat masculine","small","medium","large","huge","giant","gigantic"]; if (transform.setsChest) { if (transform.setsChestMinimum) { var curIdx = sizeOrder.indexOf(v.bodyParts.chest); var newIdx = sizeOrder.indexOf(transform.setsChest); if (curIdx < newIdx) v.bodyParts.chest = transform.setsChest; } else { v.bodyParts.chest = transform.setsChest; } } if (transform.setsButt) { if (transform.setButtMinimum) { var curIdx = sizeOrder.indexOf(v.bodyParts.butt); var newIdx = sizeOrder.indexOf(transform.setsButt); if (curIdx < newIdx) v.bodyParts.butt = transform.setsButt; } else { v.bodyParts.butt = transform.setsButt; } } if (transform.setsGenitals) { v.bodyParts.genitals = transform.setsGenitals; setup.checkFutanariConsistency(); } if (transform.genderLock) { v.bodyParts.gender = transform.genderLock; v.gender = transform.genderLock; } if (transform.setsHairColor && v.appearance) { v.appearance.hairColor = transform.setsHairColor; } if (transform.setsSkinTone && v.appearance) { v.appearance.skinTone = transform.setsSkinTone; } if (transform.setsAge) { if (v.appearance) v.appearance.age = transform.setsAge; v.bodyParts.age = transform.setsAge.toLowerCase(); } /* Mature adult size bump */ if (transform.matureAdultBump && v.bodyParts.age === "mature adult") { var chestIdx = sizeOrder.indexOf(v.bodyParts.chest); if (chestIdx >= 0 && chestIdx < sizeOrder.length - 1) { v.bodyParts.chest = sizeOrder[chestIdx + 1]; } var buttIdx = sizeOrder.indexOf(v.bodyParts.butt); if (buttIdx >= 0 && buttIdx < sizeOrder.length - 1) { v.bodyParts.butt = sizeOrder[buttIdx + 1]; } } } /* Remove blocked traits */ if (transform.removesOnGain && v.mentalTraits) { transform.removesOnGain.forEach(function(trait) { var idx = v.mentalTraits.indexOf(trait); if (idx !== -1) v.mentalTraits.splice(idx, 1); }); } if (transform.removesPhysicalOnGain && v.physicalTraits) { transform.removesPhysicalOnGain.forEach(function(trait) { var idx = v.physicalTraits.indexOf(trait); if (idx !== -1) v.physicalTraits.splice(idx, 1); }); } if (transform.removesSkillsOnGain && v.skills) { transform.removesSkillsOnGain.forEach(function(skill) { var idx = v.skills.indexOf(skill); if (idx !== -1) v.skills.splice(idx, 1); }); } /* Track active transformation */ v.activeTransformation = transformationName; /* Unlock transformation achievement */ var achId = setup.transformAchievementMap[transformationName]; if (achId && setup.achievements && setup.achievements.unlock) { setup.achievements.unlock(achId); } return true; }>> /* Helper function to check if a skill is blocked by current transformation */ <<set setup.isSkillBlocked = function(skillName) { var v = State.variables; if (!v.physicalTraits) return false; /* Check all transformations for blocksSkills */ for (var transName in setup.fullTransformations) { var transform = setup.fullTransformations[transName]; if (transform.blocksSkills && v.physicalTraits.includes(transName)) { if (transform.blocksSkills.includes(skillName)) { return true; } } } return false; }>> /* Safe function to add a skill (respects transformation blocks) */ <<set setup.addSkill = function(skillName) { var v = State.variables; if (!v.skills) v.skills = []; /* Check if already has skill */ if (v.skills.includes(skillName)) return false; /* Check if skill is blocked by transformation */ if (setup.isSkillBlocked(skillName)) return false; v.skills.push(skillName); return true; }>> /* Function to get trait effects across jobs, theft, and trading for the encyclopedia */ <<set setup.getTraitJobEffects = function(traitName) { var effects = []; var isSunfish = (traitName === "Sunfish"); var s = isSunfish; /* Check hourly job bonuses */ if (setup.jobWorkConfig) { var jobNames = Object.keys(setup.jobWorkConfig); for (var i = 0; i < jobNames.length; i++) { var job = jobNames[i]; var config = setup.jobWorkConfig[job]; if (!config || !config.bonuses) continue; if (config.bonuses.big && config.bonuses.big.indexOf(traitName) !== -1) { effects.push(s ? job + ": ???" : job + ": +15% wage"); } else if (config.bonuses.medium && config.bonuses.medium.indexOf(traitName) !== -1) { effects.push(s ? job + ": ???" : job + ": +5% wage"); } else if (config.bonuses.small && config.bonuses.small.indexOf(traitName) !== -1) { effects.push(s ? job + ": ???" : job + ": +2% wage"); } if (config.negativeRemovable && config.negativeRemovable.indexOf(traitName) !== -1) { effects.push(s ? job + ": ???" : job + ": -10% wage"); } if (config.negativePermanent && config.negativePermanent.indexOf(traitName) !== -1) { effects.push(s ? job + ": ???" : job + ": -5% wage"); } } } /* Receptionist/Secretary job bonuses */ var recPhonePlus = {"Polite": 3, "Friendly": 3, "Patient": 3, "Calm": 2, "Customer Service": 5, "Clear Enunciation": 4, "Articulate Speech": 4, "Smooth Voice": 3, "Friendly Tone": 3, "Warm Tone": 3}; var recPhoneMinus = {"Rude": 5, "Impatient": 4, "Short Tempered": 4, "Mumbly Voice": 5, "Stuttering Speech": 5, "Monotone": 3, "Flat Voice": 3}; var recWalkPlus = {"Polite": 3, "Friendly": 3, "Patient": 4, "Empathetic": 4, "Diplomatic": 3, "Customer Service": 5}; var recWalkMinus = {"Rude": 6, "Bitchy": 5, "Cold": 4, "Insensitive": 4, "Short Tempered": 4}; var recFilePlus = {"Organized": 6, "Detail-Oriented": 4, "Efficient": 3, "Focused": 3, "Punctual": 2}; var recFileMinus = {"Disorganized": 6, "Forgetful": 4, "Lazy": 4, "Slow": 3, "Clumsy": 3}; var recBadgePlus = {"Organized": 4, "Detail-Oriented": 5, "Perceptive": 4, "Focused": 3}; var recBadgeMinus = {"Disorganized": 5, "Forgetful": 5, "Reckless": 4, "Careless": 4}; var recEffects = []; if (recPhonePlus[traitName]) recEffects.push("Phone Calls: +" + recPhonePlus[traitName] + "%"); if (recPhoneMinus[traitName]) recEffects.push("Phone Calls: -" + recPhoneMinus[traitName] + "%"); if (recWalkPlus[traitName]) recEffects.push("Walk-ins: +" + recWalkPlus[traitName] + "%"); if (recWalkMinus[traitName]) recEffects.push("Walk-ins: -" + recWalkMinus[traitName] + "%"); if (recFilePlus[traitName]) recEffects.push("Filing: +" + recFilePlus[traitName] + "%"); if (recFileMinus[traitName]) recEffects.push("Filing: -" + recFileMinus[traitName] + "%"); if (recBadgePlus[traitName]) recEffects.push("Badges: +" + recBadgePlus[traitName] + "%"); if (recBadgeMinus[traitName]) recEffects.push("Badges: -" + recBadgeMinus[traitName] + "%"); if (traitName === "Organized") recEffects.push("Missing: -5% filing penalty"); if (traitName === "Customer Service") recEffects.push("Missing: -5% overall penalty"); if (recEffects.length > 0) { for (var r = 0; r < recEffects.length; r++) { effects.push(s ? "Receptionist: ???" : "Receptionist: " + recEffects[r]); } } /* Janitor job bonuses */ var janitorEffects = []; if (traitName === "Punctual") janitorEffects.push("Missing: -5% penalty"); if (traitName === "Cleaning") janitorEffects.push("Missing: -5% penalty"); if (traitName === "Slow Learner") janitorEffects.push("-5% penalty"); if (traitName === "Forgetful") janitorEffects.push("-5% penalty"); if (janitorEffects.length > 0) { for (var j = 0; j < janitorEffects.length; j++) { effects.push(s ? "Janitor: ???" : "Janitor: " + janitorEffects[j]); } } /* Stripping job bonuses */ var stripEffects = []; if (traitName === "Attractive") { stripEffects.push("Topless Tease: +20% tips"); stripEffects.push("Full Strip: +30% tips"); stripEffects.push("Freestyle: +25% tips"); } if (traitName === "Alluring") { stripEffects.push("Topless Tease: +15% tips"); stripEffects.push("Full Strip: +25% tips"); stripEffects.push("Freestyle: +30% tips"); } if (traitName === "Seductive") { stripEffects.push("Full Strip: +20% tips"); stripEffects.push("Freestyle: +25% tips"); } if (traitName === "Athletic") stripEffects.push("Pole Dance: +30% tips"); if (traitName === "Graceful") stripEffects.push("Pole Dance: +25% tips"); if (traitName === "Flexible") stripEffects.push("Pole Dance: +20% tips"); if (stripEffects.length > 0) { for (var st = 0; st < stripEffects.length; st++) { effects.push(s ? "Stripping: ???" : "Stripping: " + stripEffects[st]); } } /* Scanner theft bonuses */ var scannerEffects = []; if (traitName === "Lock Picking") scannerEffects.push("+10% success"); if (traitName === "Stealth") scannerEffects.push("+10% success"); if (traitName === "Sly") scannerEffects.push("+5% success"); if (traitName === "Quick Reflexes") scannerEffects.push("+8% success"); if (scannerEffects.length > 0) { for (var sc = 0; sc < scannerEffects.length; sc++) { effects.push(s ? "Scanner Theft: ???" : "Scanner Theft: " + scannerEffects[sc]); } } /* Check trait theft bonuses */ if (setup.theftBonusTraits && setup.theftBonusTraits[traitName] !== undefined) { var val = setup.theftBonusTraits[traitName]; effects.push(s ? "Trait Theft: ???" : "Trait Theft: +" + (val * 2) + "% success"); } if (setup.theftBonusSkills && setup.theftBonusSkills[traitName] !== undefined) { var val2 = setup.theftBonusSkills[traitName]; effects.push(s ? "Trait Theft: ???" : "Trait Theft: +" + (val2 * 2) + "% success"); } if (setup.moralTraitsBlockingTheft && setup.moralTraitsBlockingTheft.indexOf(traitName) !== -1) { effects.push(s ? "Trait Theft: ???" : "Trait Theft: Blocks stealing"); } if (setup.moralTraitsPenalty && setup.moralTraitsPenalty.indexOf(traitName) !== -1) { effects.push(s ? "Trait Theft: ???" : "Trait Theft: -6% success"); } /* Special theft one-offs */ if (!s) { if (traitName === "Clumsy") effects.push("Trait Theft: -7.5% success"); if (traitName === "Lucky") { effects.push("Trait Theft: +20% success"); effects.push("Scanner Theft: +10% success"); } if (traitName === "Unlucky" || traitName === "Bad Luck") { effects.push("Trait Theft: -20% success"); effects.push("Scanner Theft: -10% success"); } } else { if (traitName === "Clumsy" || traitName === "Lucky" || traitName === "Unlucky" || traitName === "Bad Luck") { effects.push("Trait Theft: ???"); effects.push("Scanner Theft: ???"); } } /* Trading success bonuses */ if (traitName === "Trading") effects.push(s ? "Trading: ???" : "Trading: +2 success chance"); if (traitName === "Persuasion") effects.push(s ? "Trading: ???" : "Trading: +3 success chance"); var beneficialTrade = ["Honest", "Confident", "Friendly", "Trusting", "Patient", "Intelligent", "Analytical", "Chill", "Nonchalant", "Charming", "Diplomatic", "Polite", "Reassuring", "Efficient", "Warm", "Lucky", "Cerberus", "Werecat", "Weresheep", "Himbo", "Werefox", "Trophy Wife", "Werebunny", "Punk", "Gym Bunny"]; var detrimentalTrade = ["Aggressive", "Awkward", "Blunt", "Corrupt", "Moody", "Pessimistic", "Sensitive", "Shy", "Stubborn", "Arrogant", "Cold", "Deceitful", "Foolish", "Forgetful", "Impatient", "Insecure", "Reckless", "Rude", "Selfish", "Short Tempered", "Unlucky", "Unreliable", "Bitchy"]; if (beneficialTrade.indexOf(traitName) !== -1) effects.push(s ? "Trading: ???" : "Trading: +2 success chance"); if (detrimentalTrade.indexOf(traitName) !== -1) effects.push(s ? "Trading: ???" : "Trading: -3 success chance"); if (traitName === "Sunfish") effects.push(s ? "Trading: ???" : "Trading: +10 success chance"); /* Streaming bonuses - check all 5 categories dynamically */ var streamCats = { "ASMR": setup.asmrTraitEffects, "Styling/Makeup": setup.stylingMakeupTraitEffects, "Music": setup.musicTraitEffects, "Cooking": setup.cookingTraitEffects, "Gaming": setup.gamingTraitEffects }; var streamCatNames = Object.keys(streamCats); for (var si = 0; si < streamCatNames.length; si++) { var catName = streamCatNames[si]; var catEffects = streamCats[catName]; if (catEffects && catEffects.positive && catEffects.positive[traitName]) { var pe = catEffects.positive[traitName]; effects.push(s ? "Stream " + catName + ": ???" : "Stream " + catName + ": +" + pe.viewerBonus + "% viewers, +" + pe.engagementBonus + "% engagement"); } if (catEffects && catEffects.negative && catEffects.negative[traitName]) { var ne = catEffects.negative[traitName]; effects.push(s ? "Stream " + catName + ": ???" : "Stream " + catName + ": -" + ne.viewerPenalty + "% viewers, -" + ne.engagementPenalty + "% engagement"); } } /* PrawnHub bonuses - each positive trait gives +5 to action roll */ var prawnSet1 = ["Sexually Skilled", "Alluring", "Attractive", "Seductive", "High Stamina"]; var prawnSet2 = ["Curvy", "Soft", "Smooth Skin", "Graceful", "Voluptuous"]; if (prawnSet1.indexOf(traitName) !== -1) { effects.push(s ? "PrawnHub: ???" : "PrawnHub: +5 action bonus (most scenes)"); } if (prawnSet2.indexOf(traitName) !== -1) { effects.push(s ? "PrawnHub: ???" : "PrawnHub: +5 action bonus (body scenes)"); } /* Brothel bonus traits - each gives +$15 per session */ var brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion", "Oral Expert", "Anal Expert", "Rough Sex Enthusiast", "Sensual Lover", "BDSM Enthusiast - Dom", "BDSM Enthusiast - Sub", "Roleplay Expert", "Dirty Talker", "Exhibitionist", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master"]; if (brothelBonusTraits.indexOf(traitName) !== -1) { effects.push(s ? "Brothel: ???" : "Brothel: +$15 per session"); } /* Patrol Officer requirement */ if (traitName === "Driving") effects.push(s ? "Patrol Officer: ???" : "Patrol Officer: Required to patrol"); /* Brothel requirement - only show for Sexually Skilled, not for transformations that inherit it */ if (traitName === "Sexually Skilled") effects.push(s ? "Brothel: ???" : "Brothel: Required to work"); /* Swimming / Underwater Cave discovery */ if (traitName === "Swimmer" || traitName === "Swimming") { effects.push(s ? "Exploration: ???" : "Exploration: 5% chance to discover Underwater Cave while swimming"); } if (traitName === "Sunfish") { effects.push(s ? "Exploration: ???" : "Exploration: 50% chance to discover Underwater Cave while swimming"); } /* Gambling effects */ if (traitName === "Lucky") { effects.push(s ? "Slots: ???" : "Slots: -10% lose chance, +10% $100 win chance"); effects.push(s ? "Roulette: ???" : "Roulette: +10% forced win chance"); } if (traitName === "Unlucky" || traitName === "Bad Luck") { effects.push(s ? "Slots: ???" : "Slots: Much worse odds across all tiers"); effects.push(s ? "Roulette: ???" : "Roulette: 10% forced loss chance"); } if (traitName === "Gambling Addiction") { effects.push(s ? "Casino: ???" : "Casino: 50% chance of forced gambling on entry"); } return effects; }>> /* Function to apply trait bonus */ <<set setup.applyTraitBonus = function(traitName, character) { var bonuses = setup.traitBonuses[traitName] || setup.skillBonuses[traitName]; if (!bonuses) return; for (var stat in bonuses) { if (character.stats && character.stats[stat] !== undefined) { character.stats[stat] += bonuses[stat]; /* Also increase max cap if it exists */ if (character.statMaxCaps && character.statMaxCaps[stat] !== undefined) { character.statMaxCaps[stat] += bonuses[stat]; } } } }>> /* Function to remove trait bonus */ <<set setup.removeTraitBonus = function(traitName, character) { var bonuses = setup.traitBonuses[traitName] || setup.skillBonuses[traitName]; if (!bonuses) return; for (var stat in bonuses) { if (character.stats && character.stats[stat] !== undefined) { character.stats[stat] -= bonuses[stat]; /* Also decrease max cap if it exists */ if (character.statMaxCaps && character.statMaxCaps[stat] !== undefined) { character.statMaxCaps[stat] -= bonuses[stat]; } } } }>>
/* ---------------------------------- */ /* --- MUTUALLY EXCLUSIVE TRAITS --- */ /* ---------------------------------- */ <<set setup.exclusiveTraitGroups = { /* Height traits (Imp includes Short, Succubus includes Imp) */ "height": ["Tall", "Short", "Imp", "Succubus"], /* Hair length traits */ "hairLength": ["Short Hair", "Long Hair"], /* Body type traits with chest/butt requirements (Succubus includes Curvy, Hucow includes Voluptuous) */ "bodyType": ["Curvy", "Voluptuous", "Petite", "Slim", "Muscular", "Stocky", "Lean", "Succubus", "Hucow"], /* Voice traits - only one voice trait allowed (format: [Adjective] Voice) */ "voice": ["Smooth Voice", "Soft Voice", "Warm Voice", "Gentle Voice", "Deep Voice", "Raspy Voice", "Gravelly Voice", "Breathy Voice", "High-Pitched Voice", "Sharp Voice", "Clear Voice", "Monotone Voice", "Flat Voice", "Deadpan Voice", "Energetic Voice", "Calm Voice", "Sultry Voice", "Silky Voice", "Melodic Voice", "Husky Voice", "Nasal Voice", "Whispery Voice", "Booming Voice", "Squeaky Voice", "Gruff Voice", "Shrill Voice", "Velvety Voice", "Croaky Voice", "Rich Voice"], /* Accent traits - optional (format: [Regional] Accent) */ "accent": ["Southern Accent", "British Accent", "French Accent", "Russian Accent", "German Accent", "Italian Accent", "Spanish Accent", "Irish Accent", "Scottish Accent", "Australian Accent", "Japanese Accent", "Indian Accent", "New York Accent", "Texan Accent", "Caribbean Accent", "Eastern European Accent", "Scandinavian Accent", "Middle Eastern Accent", "Brazilian Accent", "Chinese Accent"], /* Sexual orientation traits - only one allowed */ "orientation": ["Straight", "Gay", "Lesbian", "Bisexual", "Pansexual", "Asexual", "Demisexual", "Questioning", "Fluid"], /* Personality opposites */ "dominance": ["Dominant", "Submissive"], "kindness": ["Bitchy", "Kind"], "confidence": ["Confident", "Shy"], "energy": ["Energetic", "Lazy"], "social": ["Introverted", "Extroverted"], "optimism": ["Optimistic", "Pessimistic"], "morality": ["Cruel", "Kind"], "arrogance": ["Arrogant", "Humble"], "paranoia": ["Paranoid", "Trusting"], "bravery": ["Brave", "Cowardly"], "patience": ["Patient", "Impatient"], "wisdom": ["Wise", "Foolish"], "work": ["Hardworking", "Lazy"], "aggression": ["Aggressive", "Passive"], "attraction": ["Attractive", "Ugly", "Imp", "Succubus"], "organization": ["Organized", "Disorganized"], "reliability": ["Reliable", "Unreliable"], "temperament": ["Calm", "Short Tempered", "Moody"], "sociability": ["Talkative", "Quiet"], "manners": ["Polite", "Rude"], "warmth": ["Warm", "Cold"], "sensitivity": ["Sensitive", "Insensitive"], "charm": ["Charming", "Awkward"], "honesty": ["Honest", "Deceitful"], "selflessness": ["Considerate", "Selfish"], "speed": ["Fast", "Slow", "Quick"], "learning": ["Quick Learner", "Slow Learner"], "luck": ["Lucky", "Unlucky"], "badluck": ["Lucky", "Bad Luck"], "impulsiveness": ["Disciplined", "Impulsive", "Reckless"], "stability": ["Steadfast", "Erratic", "Unpredictable"], "security": ["Confident", "Insecure"], "stereotypes": ["Nerd", "Geek", "Jock", "Prep", "Tomboy", "Femboy", "Diva", "Goth"], /* Age appearance traits (physical) - cannot have both */ "ageAppearance": ["Youthful", "Mature"], /* Gender-mismatch traits (auto-assigned, untradable) */ "genderMismatch": ["Cuntboy", "Dickgirl"], /* Laboratory Transformation Traits - Base animal types (mutually exclusive) */ "animalBase": [], /* Laboratory Transformation Traits - Were-Creature forms (mutually exclusive - only one full form) */ "wereCreature": ["Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep"], /* Laboratory Transformation Traits - Advanced Neko/Inu forms */ "advancedAnimal": ["Neko", "Inu"], /* Laboratory Transformation Traits - Demonic forms (mutually exclusive) */ /* "Incubus" temporarily disabled from demonicForm */ "demonicForm": ["Succubus", "Imp", "Cerberus", "Imp-Touched"], /* Laboratory Transformation Traits - Lifestyle transformations (mutually exclusive) */ "lifestyleTransform": ["Hucow", "Trophy Wife", "Ojou", "Gym Bunny", "E-Girl", "Punk", "Siren", "Living Doll", "Dominatrix"], /* Laboratory Transformation Traits - Dominance mentality (mutually exclusive with personality) */ "transformDominance": ["Sadist", "Masochist"], /* Laboratory Transformation Traits - Parental instincts (mutually exclusive) */ "parentalInstinct": ["Maternal", "Paternal", "Mommy Energy"], /* Laboratory Transformation Traits - Obedience vs Rebellion (mutually exclusive) */ "obedienceSpectrum": ["Obedient", "Rebellious", "Docile", "Feral"], /* ALL Laboratory Transformations - all mutually exclusive with each other */ "labTransform": ["Succubus", "Imp", "Cerberus", "Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep", "Hucow", "Trophy Wife", "Ojou", "Gym Bunny", "E-Girl", "Punk", "Gyaru", "Siren", "Living Doll", "Dominatrix", "Slut", "Himbo", "Angel", "Naiad", "Automaton", "Anubis", "Banshee", "Cheshire Cat", "Cupid", "Dark Angel", "Honeybee", "Jinko", "Kakuen", "Lizardman", "Ocelomeh", "Pharaoh", "Pyrow", "Raiju", "Salamander", "Satyros", "Vampire", "Kitsune"] }>> <<set setup.bodyTypeRequirements = { "Curvy": { minChest: "medium", minButt: "medium" }, "Voluptuous": { minChest: "medium", minButt: "medium" }, "Petite": { maxChest: "medium", maxButt: "medium" }, "Slim": { maxChest: "small", maxButt: "small" } }>> <<set setup.chestSizeOrder = ["flat", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set setup.buttSizeOrder = ["flat", "small", "medium", "large", "huge", "giant", "gigantic"]>> /* Check if a trait is exclusive with any existing traits - FIXED VERSION */ <<set setup.getConflictingTrait = function(newTrait, existingTraits) { /* Ensure existingTraits is an array */ if (!Array.isArray(existingTraits)) { existingTraits = []; } for (var groupName in setup.exclusiveTraitGroups) { var group = setup.exclusiveTraitGroups[groupName]; /* If the new trait is in this group */ if (group.includes(newTrait)) { /* Check if any existing trait is also in this SAME group */ for (var i = 0; i < existingTraits.length; i++) { var existingTrait = existingTraits[i]; if (group.includes(existingTrait) && existingTrait !== newTrait) { /* Found a conflict in the same group */ return existingTrait; } } } } /* No conflict found */ return null; }>> /* Check if body type is compatible with current chest/butt size */ <<set setup.isBodyTypeCompatible = function(bodyType, chest, butt) { var requirements = setup.bodyTypeRequirements[bodyType]; if (!requirements) return true; var chestIndex = setup.chestSizeOrder.indexOf(chest.toLowerCase()); var buttIndex = setup.buttSizeOrder.indexOf(butt.toLowerCase()); if (requirements.minChest) { var minChestIndex = setup.chestSizeOrder.indexOf(requirements.minChest); if (chestIndex < minChestIndex) return false; } if (requirements.maxChest) { var maxChestIndex = setup.chestSizeOrder.indexOf(requirements.maxChest); if (chestIndex > maxChestIndex) return false; } if (requirements.minButt) { var minButtIndex = setup.buttSizeOrder.indexOf(requirements.minButt); if (buttIndex < minButtIndex) return false; } if (requirements.maxButt) { var maxButtIndex = setup.buttSizeOrder.indexOf(requirements.maxButt); if (buttIndex > maxButtIndex) return false; } return true; }>> /* Auto-adjust body parts when body type trait is gained */ <<set setup.adjustBodyPartsForTrait = function(bodyType, isPlayer) { var requirements = setup.bodyTypeRequirements[bodyType]; if (!requirements) return; var v = State.variables; var target = isPlayer ? v : arguments[2]; /* Third argument is NPC object if not player */ var chest = isPlayer ? v.bodyParts.chest : target.bodyParts.chest; var butt = isPlayer ? v.bodyParts.butt : target.bodyParts.butt; var chestIndex = setup.chestSizeOrder.indexOf(chest.toLowerCase()); var buttIndex = setup.buttSizeOrder.indexOf(butt.toLowerCase()); var changed = false; /* Adjust chest if needed */ if (requirements.minChest) { var minChestIndex = setup.chestSizeOrder.indexOf(requirements.minChest); if (chestIndex < minChestIndex) { if (isPlayer) { v.bodyParts.chest = requirements.minChest; } else { target.bodyParts.chest = requirements.minChest; } changed = true; } } if (requirements.maxChest) { var maxChestIndex = setup.chestSizeOrder.indexOf(requirements.maxChest); if (chestIndex > maxChestIndex) { if (isPlayer) { v.bodyParts.chest = requirements.maxChest; } else { target.bodyParts.chest = requirements.maxChest; } changed = true; } } /* Adjust butt if needed */ if (requirements.minButt) { var minButtIndex = setup.buttSizeOrder.indexOf(requirements.minButt); if (buttIndex < minButtIndex) { if (isPlayer) { v.bodyParts.butt = requirements.minButt; } else { target.bodyParts.butt = requirements.minButt; } changed = true; } } if (requirements.maxButt) { var maxButtIndex = setup.buttSizeOrder.indexOf(requirements.maxButt); if (buttIndex > maxButtIndex) { if (isPlayer) { v.bodyParts.butt = requirements.maxButt; } else { target.bodyParts.butt = requirements.maxButt; } changed = true; } } return changed; }>> /* Update gender-mismatch traits based on current body configuration */ <<set setup.updateGenderMismatchTraits = function(target) { var v = State.variables; var isPlayer = !target; /* Get the relevant object */ var obj = isPlayer ? v : target; /* Remove both gender-mismatch traits first */ if (isPlayer) { v.physicalTraits.delete("Cuntboy"); v.physicalTraits.delete("Dickgirl"); } else { target.physicalTraits.delete("Cuntboy"); target.physicalTraits.delete("Dickgirl"); } /* Futanari trait overrides gender-mismatch traits */ if (isPlayer && v.physicalTraits.includes("Futanari")) { return; } if (!isPlayer && target.physicalTraits.includes("Futanari")) { return; } /* Check for gender-mismatch situations and add appropriate trait */ var genitals = obj.bodyParts.genitals; var hasVagina = genitals === "tight vagina" || genitals === "vagina" || genitals === "loose vagina"; var hasPenis = genitals === "small penis" || genitals === "penis" || genitals === "big penis"; if (obj.bodyParts.gender === "male" && hasVagina) { /* Male body with vagina = Cuntboy */ if (isPlayer) { if (!v.physicalTraits.includes("Cuntboy")) { v.physicalTraits.push("Cuntboy"); } } else { if (!target.physicalTraits.includes("Cuntboy")) { target.physicalTraits.push("Cuntboy"); } } } else if (obj.bodyParts.gender === "female" && hasPenis) { /* Female body with penis = Dickgirl */ if (isPlayer) { if (!v.physicalTraits.includes("Dickgirl")) { v.physicalTraits.push("Dickgirl"); } } else { if (!target.physicalTraits.includes("Dickgirl")) { target.physicalTraits.push("Dickgirl"); } } } }>>
/* ---------------------------------- */ /* --- JOB STAT REQUIREMENTS (NO LONGER USED FOR TRADING) --- */ /* ---------------------------------- */ <<set setup.jobRequirements = { "Adult Store Clerk": {charisma: 20}, "Adult Streamer": {charisma: 20, dexterity: 15, strength: 5}, "Musician": {charisma: 20, dexterity: 10}, "Baker": {dexterity: 10}, "Barista": {charisma: 10, dexterity: 10}, "Beauty Salon Stylist": {dexterity: 20}, "Black Market Dealer": {charisma: 45}, "Bouncer": {strength: 40}, "Brothel Owner": {charisma: 90, intelligence: 85}, "Brothel Worker": {charisma: 90}, "Bus Driver": {strength: 15, dexterity: 20}, "City Mayor": {charisma: 70, intelligence: 50}, "Clinic Assistant": {intelligence: 40}, "Cocktail Waitress": {charisma: 35, dexterity: 20}, "Construction Worker": {strength: 15}, "Criminal": {}, "Dancing Instructor": {strength: 45, dexterity: 50}, "Data Analyst": {intelligence: 50}, "Detective": {intelligence: 45, strength: 35}, "Dock Worker": {strength: 20}, "Donuts Deliverer": {dexterity: 15}, "Ecentric Shop Worker": {charisma: 20}, "Enforcer": {strength: 50}, "Fitness Shop Clerk": {strength: 25}, "Fitness Trainer": {strength: 50, dexterity: 50}, "Maid": {dexterity: 10}, "Head Maid": {}, "Mayor's Secretary": {intelligence: 85}, "Model": {charisma: 35}, "Mysterious Book Shop owner": {charisma: 100, intelligence: 50}, "Negotiator": {charisma: 50}, "Package Courier": {dexterity: 10}, "Patrol Officer": {strength: 80}, "Police Officer": {strength: 45}, "Police Station Janitor": {strength: 10}, "Police Station Receptionist": {charisma: 25}, "Porn Star": {charisma: 50}, "Security Guard": {strength: 15}, "Sheriff": {strength: 50, charisma: 45}, "Social Media Influencer": {charisma: 45}, "Streamer": {charisma: 5, intelligence: 5, dexterity: 5, strength: 5}, "Street Performer": {charisma: 10}, "Stripper": {charisma: 40, dexterity: 30}, "Tech Store Clerk": {intelligence: 20}, "Unemployed": {} }>> <<set setup.jobTraitRequirements = { "Bus Driver": {traits: ["Driving"]}, "Donuts Deliverer": {traits: ["Driving"]}, "Cocktail Waitress": {traits: ["Serving"]}, "Fitness Trainer": {stats: {strength: 50, dexterity: 50}}, "Street Performer": {traits: ["Performer"]}, "Musician": {traits: ["Musical"]}, "Dancing Instructor": {traits: ["Dancing"]}, "Social Media Influencer": {traits: ["Social Media"]}, "Negotiator": {traits: ["Persuasion"]}, "Model": {traits: ["Modeling"]}, "Porn Star": {traits: ["Modeling", "Sexually Skilled"]} }>> <<set setup.jobCapacity = { "Bus Driver": 3, "Donuts Deliverer": 3, "Cocktail Waitress": 3, "Fitness Trainer": 2, "Dancing Instructor": 4, "Model": 5, "Negotiator": 3, "Black Market Dealer": 2, "Porn Star": 4 }>> <<set setup.selfEmploymentJobs = ["Musician", "Street Performer", "Social Media Influencer"]>> <<set setup.isJobAtCapacity = function(jobName) { var cap = setup.jobCapacity[jobName]; if (!cap) return false; var npcsWithJob = setup.getNPCsByJob(jobName); var count = npcsWithJob.length; var v = State.variables; if (v.jobs && v.jobs.includes(jobName)) count++; return count >= cap; }>> <<set setup.meetsJobRequirements = function(stats, jobName) { var v = State.variables; /* Pharaoh: can take any job */ if (v.physicalTraits && v.physicalTraits.includes("Pharaoh")) return true; /* Banshee: cannot take any jobs */ if (v.physicalTraits && v.physicalTraits.includes("Banshee")) return false; /* Model: disqualification check (body size / appearance) */ if (jobName === "Model" && setup.modelDisqualified && setup.modelDisqualified()) return false; /* Porn Star: disqualification check (appearance traits) */ if (jobName === "Porn Star" && setup.pornStarDisqualified && setup.pornStarDisqualified()) return false; /* Use effective stats (base + trait bonuses + TF multipliers). The passed-in `stats` param is retained as a fallback when getTotalStat isn't available (matches the old behaviour for external callers). */ var statFor = function(stat) { if (typeof setup.getTotalStat === "function") return setup.getTotalStat(stat); return (stats && stats[stat] !== undefined) ? stats[stat] : 0; }; /* Check stat requirements */ var requirements = setup.jobRequirements[jobName]; if (requirements) { for (var stat in requirements) { if (statFor(stat) < requirements[stat]) { return false; } } } /* Check trait/skill requirements */ var traitReqs = setup.jobTraitRequirements ? setup.jobTraitRequirements[jobName] : null; if (traitReqs) { if (traitReqs.traits) { for (var t = 0; t < traitReqs.traits.length; t++) { if (!setup.playerHasTrait(traitReqs.traits[t])) return false; } } if (traitReqs.stats) { for (var s in traitReqs.stats) { if (statFor(s) < traitReqs.stats[s]) return false; } } } /* Check hiring capacity (skip for self-employment jobs) */ if (setup.selfEmploymentJobs && setup.selfEmploymentJobs.indexOf(jobName) === -1) { if (setup.isJobAtCapacity && setup.isJobAtCapacity(jobName)) return false; } return true; }>> <<set setup.getJobApplicationStatus = function(jobName) { var v = State.variables; /* Sunfish Artifact possession: Roisin lists "Fuck Employment". You cannot apply for any job while you are her. */ if (v.possessionActive) return "notQualified"; /* Already employed at this job? */ if (v.jobs && v.jobs.includes(jobName)) return "employed"; /* Criminal cannot apply to any other jobs */ if (v.jobs && v.jobs.includes("Criminal") && jobName !== "Criminal") return "notQualified"; /* Banshee cannot take any jobs */ if (v.physicalTraits && v.physicalTraits.includes("Banshee")) return "notQualified"; /* Pharaoh bypasses requirements (but not capacity) */ var isPharaoh = v.physicalTraits && v.physicalTraits.includes("Pharaoh"); if (!isPharaoh) { /* Model: disqualification check (body size / appearance) */ if (jobName === "Model" && setup.modelDisqualified && setup.modelDisqualified()) return "notQualified"; /* Porn Star: disqualification check (appearance traits) */ if (jobName === "Porn Star" && setup.pornStarDisqualified && setup.pornStarDisqualified()) return "notQualified"; /* Use effective stats (base + trait bonuses + TF multipliers) via setup.getTotalStat. Previously this read v.stats[stat] directly, which meant e.g. a Strong/Muscular player whose trait bonuses brought them over the charisma requirement still got rejected because their BASE charisma was too low. Hiring requirements are meant to check the player's actual capability. */ var statFor = function(stat) { return (typeof setup.getTotalStat === "function") ? setup.getTotalStat(stat) : (v.stats && v.stats[stat] !== undefined ? v.stats[stat] : 0); }; /* Check stat requirements */ var reqs = setup.jobRequirements[jobName]; if (reqs) { for (var stat in reqs) { if (statFor(stat) < reqs[stat]) return "notQualified"; } } /* Check trait requirements */ var traitReqs = setup.jobTraitRequirements ? setup.jobTraitRequirements[jobName] : null; if (traitReqs) { if (traitReqs.traits) { for (var t = 0; t < traitReqs.traits.length; t++) { if (!setup.playerHasTrait(traitReqs.traits[t])) return "notQualified"; } } if (traitReqs.stats) { for (var s in traitReqs.stats) { if (statFor(s) < traitReqs.stats[s]) return "notQualified"; } } } } /* Check capacity */ if (setup.isJobAtCapacity && setup.isJobAtCapacity(jobName)) return "notHiring"; return "canApply"; }>> <<set setup.getJobRequirementDisplay = function(jobName) { var parts = []; var names = {strength: "STR", dexterity: "DEX", charisma: "CHA", intelligence: "INT"}; var reqs = setup.jobRequirements[jobName]; if (reqs) { for (var stat in reqs) { parts.push((names[stat] || stat) + " " + reqs[stat]); } } var traitReqs = setup.jobTraitRequirements ? setup.jobTraitRequirements[jobName] : null; if (traitReqs) { if (traitReqs.traits) { for (var t = 0; t < traitReqs.traits.length; t++) { parts.push(traitReqs.traits[t] + " trait"); } } if (traitReqs.stats) { for (var s in traitReqs.stats) { parts.push((names[s] || s) + " " + traitReqs.stats[s]); } } } /* Model: additional body/appearance requirements */ if (jobName === "Model") { parts.push("No Plain/Ugly traits"); parts.push("Chest/Butt medium or smaller"); } /* Porn Star: appearance requirements */ if (jobName === "Porn Star") { parts.push("No Ugly/Plain/Overweight traits"); } return parts.length > 0 ? parts.join(", ") : "None"; }>> <<set setup.canTradeJob = function(playerJob, npcJob) { /* Sunfish Artifact possession: cannot trade jobs while you are Roisin's body. The trade goes through her, not you. */ if (State.variables.possessionActive) return false; /* Jobs can always be traded regardless of stats */ return true; }>>
/* ---------------------------------- */ /* --- TRAIT VALUE FUNCTION --- */ /* ---------------------------------- */ <<set setup.getTraitValue = function(type, name, size) { /* Were-Creature - DON'T CHANGE */ if (name === "Were-Creature") { return 480; } /* Soul trait - worth 0 value, cannot be traded */ if (name === "Soul") { return 0; } /* Fishing milestone traits */ if (name === "Fishing") { return 50; } if (name === "Advanced Angler") { return 75; } if (name === "Master Angler") { return 100; } if (name === "Fishimon Master") { return 200; } if (name === "Blessed") { return 100; } if (name === "Wild") { return 25; } if (name === "Chosen") { return 2347; } if (name === "Mystic") { return 910; } if (name === "Heart") { return 5; } if (name === "Guardian") { return 60; } if (name === "Darkness") { return -3000; } if (name === "Alcoholic") { return -500; } if (name === "Disturbed") { return -10000; } if (name === "Mirrored") { return 0; } if (name === "Thirsty") { return 0; } if (name === "Blood") { return 0; } if (name === "Burnt") { return 50; } if (name === "Inferno") { return 0; } if (name === "Scaled") { return 30; } if (name === "Divine Sunfish") { return 0; } if (name === "Electrified") { return 74; } /* Special handling for jobs - value = total stat requirements */ if (type === "job") { if (name === "Unemployed") { return -5; } if (name === "Criminal") { return -150; } var jobReqs = setup.jobRequirements[name]; if (jobReqs) { var totalReqs = 0; for (var stat in jobReqs) { totalReqs += jobReqs[stat]; } return totalReqs; } return 15; /* Default job value */ } /* Body parts - DON'T CHANGE */ if (type === "bodyPart") { if (name === "chest" || name === "butt") { var sizeValues = { "flat masculine": 10, "flat": 10, "small": 20, "medium": 50, "large": 70, "huge": 100, "giant": 150, "gigantic": 300 /* NEW SIZE VALUE */ }; return sizeValues[size.toLowerCase()] || 12; } /* Genital values */ if (name === "genitals") { var genitalValues = { "small penis": 15, "penis": 25, "big penis": 40, "tight vagina": 15, "vagina": 25, "loose vagina": 40, "both": 40 }; return genitalValues[size.toLowerCase()] || 20; } /* Other body parts (gender, skin, hair, age) */ if (name === "gender") return 20; if (name === "skinTone") return 10; if (name === "hairColor") return 8; if (name === "hairLength") return 8; if (name === "age") return 12; return 12; } /* INDIVIDUAL TRAIT VALUES */ var traitValues = { /* ================================== */ /* SPECIAL TRAITS */ /* ================================== */ "Brick": 999, "Definitely not a Vampire": 480, "Sunfish": 999, "Totally not a Vampire": 480, "Quill": 604, "Honey": 50, "Cog": 87, /* ================================== */ /* CHARACTER CREATION TRAITS */ /* ================================== */ "Jock": 30, "Naturally Gifted": 50, "Pensive": 30, "Quick Learner": 50, "Silver-Tongued": 30, "Swift": 30, /* ================================== */ /* PHYSICAL TRAITS - POSITIVE */ /* ================================== */ "Artistic": 36, "Athletic Build": 70, "Attractive": 70, "Broad-shouldered": 35, "Curvy": 150, "Customer-Focused": 40, "Dark Skin": 10, "Deep Thinker": 50, "Detail-Oriented": 35, "Fashionable": 40, "Fast": 35, "Fit": 70, "Flexible": 50, "Freckled": 20, "Graceful": 55, "High Energy": 35, "Humorous": 20, "Lean": 45, "Long Hair": 10, "Mature": 35, "Monotone Expression": 10, "Muscular": 95, "Pale Skin": 10, "Perceptive": 12, "Petite": 30, "Pierced": 15, "Punctual": 20, "Quick": 55, "Quick Reflexes": 35, "Relaxed": 25, "Sarcastic": 15, "Sharp Features": 35, "Short Hair": 5, "Smooth Skin": 50, "Soft": 30, "Strong": 55, "Sturdy": 25, "Tall": 35, "Tan Skin": 10, "Tattooed": 15, "Voluptuous": 105, "Youthful": 69, "Lactating": 83, /* ================================== */ /* PHYSICAL TRAITS - MIXED */ /* ================================== */ "Scarred": 5, "Short": 10, /* ================================== */ /* PHYSICAL TRAITS - NEGATIVE */ /* (Values halved from original) */ /* ================================== */ "Blemished": -10, "Clumsy": -15, "Overweight": -15, "Plain": -8, "Slow": -14, "Stiff": -13, "Ugly": -20, "Underweight": -14, "Weak": -18, /* ================================== */ /* VOICE TRAITS - POSITIVE */ /* ================================== */ "Animated Tone": 25, "Articulate Speech": 32, "Balanced Neutral Tone": 10, "Bouncy Tone": 20, "Breathy Voice": 15, "Calm Voice": 20, "Charming Tone": 28, "Charismatic Voice": 38, "Clear Enunciation": 28, "Clear Pronunciation": 28, "Deep Voice": 15, "Eager Tone": 20, "Even-Paced Voice": 18, "Expressive Voice": 28, "Friendly Tone": 25, "Gentle Voice": 20, "Gravelly Voice": 12, "Hushed Intimate Voice": 25, "Lively Tone": 25, "Measured Speech": 18, "Melodic Voice": 28, "Pleasant Cadence": 25, "Silky Voice": 50, "Sing-Songy Voice": 20, "Slow Calm Voice": 15, "Smooth Talker": 35, "Smooth Voice": 39, "Soft Monologue Style": 18, "Soft-Spoken": 18, "Soothing Tone": 25, "Steady Voice": 20, "Understated Voice": 12, "Warm Tone": 28, /* ================================== */ /* VOICE TRAITS - MIXED/NEGATIVE */ /* ================================== */ "Choppy Speech": -5, "Croaky Voice": 5, "Deadpan Delivery": 5, "Detached Voice": -8, "Emotionless Tone": -10, "Fast Talker": 8, "Flat Voice": -5, "Grim Tone": -5, "High-Pitched Tone": 5, "Interruptive Tone": -8, "Lazy Drawl": -5, "Monotone": -8, "Mumbly Voice": -10, "Nasally Tone": -8, "Rapid-Fire Speech": 10, "Raspy Voice": 10, "Robotic Tone": -5, "Shaky Voice": -8, "Sharp Voice": 5, "Snappy Tone": -5, "Stoic Tone": 8, "Stuttering Speech": -8, /* ================================== */ /* MENTAL TRAITS - POSITIVE */ /* ================================== */ "Alluring": 90, "Ambitious": 32, "Analytical": 28, "Bookworm": 30, "Brave": 32, "Calm": 25, "Charming": 45, "Chill": 28, "Competitive": 28, "Confident": 35, "Considerate": 28, "Crafty": 30, "Creative": 28, "Curious": 20, "Determined": 60, "Diplomatic": 45, "Direct": 10, "Disciplined": 32, "Efficient": 60, "Empathetic": 32, "Energetic": 25, "Extroverted": 28, "Flirty": 30, "Focused": 25, "Friendly": 35, "Funny": 28, "Hardworking": 32, "High Stamina": 90, "Humble": 25, "Intelligent": 28, "Kind": 35, "Logical": 35, "Loyal": 30, "Lucky": 777, "Negotiator": 40, "Nonchalant": 18, "Optimistic": 25, "Organized": 25, "Outgoing": 25, "Patient": 28, "Polite": 25, "Reassuring": 25, "Resourceful": 32, "Seductive": 95, "Shrewd": 32, "Sly": 50, "Steadfast": 28, "Supportive": 28, "Talkative": 20, "Thoughtful": 20, "Trusting": 20, "Warm": 30, "Wise": 40, "Witty": 28, "Workaholic": 30, /* ================================== */ /* MENTAL TRAITS - MIXED */ /* ================================== */ "Aggressive": 18, "Awkward": -5, "Blunt": 10, "Clingy": -4, "Corporate Drone": 5, "Cynical": -3, "Dominant": 70, "Honest": 12, "Impulsive": 5, "Introverted": 8, "Moody": -4, "Overthinker": 8, "Paranoid": -3, "Passive": 5, "Perfectionist": 15, "Perverted": 0, "Pessimistic": 5, "Quiet": 5, "Risk Taker": 8, "Sensitive": 5, "Shy": -5, "Stubborn": 15, "Submissive": 8, "Tease": 15, "Tone Deaf": -4, "Unpredictable": -3, "Gambling Addiction": -666, /* ================================== */ /* MENTAL TRAITS - NEGATIVE */ /* (Values halved, except Unlucky and Unskilled) */ /* ================================== */ "Arrogant": -18, "Bitchy": -15, "Cold": -13, "Complacent": -15, "Corrupt": -3, "Cowardly": -19, "Cruel": -23, "Deceitful": -14, "Disorganized": -11, "Dull": -19, "Erratic": -14, "Foolish": -20, "Forgetful": -13, "Impatient": -14, "Insecure": -13, "Insensitive": -13, "Jealous": -14, "Lazy": -19, "Obsessive": -14, "Reckless": -14, "Rude": -15, "Selfish": -15, "Short Tempered": -14, "Slow Learner": -15, "Unlucky": -70, "Bad Luck": -70, "Unreliable": -16, "Unskilled": -50, /* ================================== */ /* STEREOTYPE TRAITS */ /* ================================== */ "Diva": 20, "Femboy": 32, "Geek": 23, "Goth": 35, "Nerd": 25, "Prep": 32, "Tomboy": 22, /* ================================== */ /* SKILLS - SPECIAL */ /* ================================== */ "Criminal Deluxe": 600, "Occult Expert": 160, /* ================================== */ /* SKILLS - REGULAR */ /* ================================== */ "Accounting": 35, "Acting": 38, "Art": 32, "Athletics": 40, "Baking": 30, "Cleaning": 20, "Coding": 35, "Combat": 40, "Construction": 32, "Cooking": 28, "Customer Service": 25, "Dancing": 38, "Driving": 25, "First Aid": 25, "Foreign Language": 28, "Forklift Certified": 68, "Gardening": 22, "Guitar": 30, "Hair Styling": 32, "Heavy Lifting": 58, "High Heels Proficient": 30, "Inventory Management": 22, "Languages": 28, "Legal Knowledge": 42, "Lock Picking": 48, "Maid": 25, "Makeup": 30, "Management": 42, "Martial Arts": 45, "Math Skills": 28, "Medicine": 42, "Modeling": 55, "Music": 32, "Painting": 32, "Persuasion": 50, "Photography": 28, "Piano": 32, "Plumbing": 28, "Product Knowledge": 18, "Public Speaking": 38, "Retail": 28, "Sales": 38, "Serving": 30, "Sexually Skilled": 100, "Singing": 28, "Social Media": 32, "Stealth": 35, "Swimmer": 32, "Swimming": 32, "Teaching": 38, "Tech-Savvy": 22, "Trading": 43, "Troubleshooting": 28, "Writing": 28, "Yoga": 32, /* ================================== */ /* SEXUAL EXPERTISE TRAITS */ /* ================================== */ "Oral Expert": 85, "Anal Expert": 80, "Rough Sex Enthusiast": 75, "Sensual Lover": 85, "BDSM Enthusiast - Dom": 90, "BDSM Enthusiast - Sub": 80, "Roleplay Expert": 95, "Dirty Talker": 70, "Exhibitionist": 65, "Sexual Stamina Expert": 100, "Tit Worship Expert": 75, "Titfuck Master": 85, /* ================================== */ /* MISCELLANEOUS */ /* ================================== */ "Cuntboy": 0, "Dickgirl": 0, "Futanari": 40, /* ================================== */ /* MENTAL TRAITS - MIXED (ADDITIONAL) */ /* ================================== */ "Bimbo": 30, "Musky": 5, /* ================================== */ /* STEREOTYPE TRAITS (ADDITIONAL) */ /* ================================== */ "Delinquent": 25, /* ================================== */ /* VOICE TRAITS (ADDITIONAL) */ /* ================================== */ "Gaelic Accent": 10, /* ================================== */ /* NPC / SHARED TRAITS */ /* ================================== */ "Nervous": -10, "Scared": -15, "Assertive": 30, "Serious": 15, "Reserved": 10, "Demanding": -10, "Stocky": 20, "Slim": 20, "Prudish": 5, "Timid": -8, "Antisocial": -12, "Busy": 5, "Cautious": 15, "Reliable": 25, "Careful": 15, /* ================================== */ /* NPC SKILLS (ADDITIONAL) */ /* ================================== */ "Building PCs": 28, "Animation": 32, "Fashion Design": 32, "Finance": 38, "Investigation": 35, "Leadership": 38, "Social Skills": 30, "Video Editing": 28, "Combat Training": 35, "Gaming": 22, "Basketball": 30, "Business": 38, "Mechanical Repair": 28, "Navigation": 25, "Magic Theory": 40, "Meditation": 30, /* ================================== */ /* NPC MENTAL TRAITS (ADDITIONAL) */ /* ================================== */ "Anxious": -12, "Bold": 25, "Bubbly": 15, "By-the-Book": 10, "Clever": 20, "Crazy": -20, "Eccentric": 10, "Gentle": 15, "Hot-Headed": -5, "Intimidating": 20, "Manipulative": -15, "Naive": -10, "Nurturing": 20, "Passionate": 20, "Playful": 15, "Protective": 25, "Romantic": 15, "Sassy": 10, "Simple": -5, "Spiritual": 15, "Street Smart": 25, "Vain": -10, /* ================================== */ /* NPC VOICE TRAITS (ADDITIONAL) */ /* ================================== */ "Flat Uninterested Voice": 0, "Slurred Speech": -5, "Whiny Voice": -5, /* ================================== */ /* TRANSFORMATION TRAITS */ /* ================================== */ "Imp": 87, "Succubus": 347, "Hucow": 179, "Living Doll": 242, "Werewolf": 123, "Cerberus": 935, "Hellhound": 935, "Werecat": 32, "Weresheep": 225, "Himbo": 191, "E-Girl": 112, "Werefox": 180, "Trophy Wife": 153, "Werebunny": 123, "Punk": 75, "Gym Bunny": 178, /* NEW TRANSFORMATION TRAITS */ "Angel": 902, "Naiad": 1029, "Automaton": 344, "Banshee": 0, "Cheshire Cat": 824, "Cupid": 952, "Dark Angel": 100, "Honeybee": 105, "Jinko": 82, "Kakuen": 120, "Lizardman": 65, "Ocelomeh": 97, "Pyrow": 437, "Raiju": 104, "Salamander": 340, "Satyros": 257, "Vampire": 480, "Kitsune": 1105, "Anubis": 213, "Pharaoh": 2455 }; /* Return the defined value or default */ if (traitValues[name] !== undefined) { return traitValues[name]; } /* Default values if not found */ if (type === "physical") return 15; if (type === "mental") return 15; if (type === "skill") return 25; return 10; }>>
/* ---------------------------------- */ /* --- NPC LOOKUP FUNCTIONS --- */ /* ---------------------------------- */ <<set setup.getNPCsByJob = function(jobName) { var npcs = State.variables.npcs; var result = []; for (var i = 0; i < npcs.length; i++) { var npc = npcs[i]; /* Skip possessed/absorbed NPCs hidden from the world (mirrors getNPCsAtLocation) */ if (npc.hiddenFromWorld) continue; /* Handle unemployed specifically - NPCs with no jobs array or empty jobs array */ if (jobName === "Unemployed") { if (!npc.jobs || npc.jobs.length === 0) { result.push(npc); } } else { /* Regular job matching - only include if they have this specific job */ if (npc.jobs && npc.jobs.length > 0 && npc.jobs.includes(jobName)) { result.push(npc); } } } return result; }>> <<set setup.getNPCByName = function(npcName) { var npcs = State.variables.npcs; for (var i = 0; i < npcs.length; i++) { if (npcs[i].name === npcName) { var npc = npcs[i]; /* Ensure NPC has hair length (for backwards compatibility) */ if (!npc.appearance.hairLength) { npc.appearance.hairLength = Math.random() < 0.5 ? "short" : "long"; /* Add corresponding physical trait */ var hairLengthTrait = npc.appearance.hairLength === "short" ? "Short Hair" : "Long Hair"; if (!npc.physicalTraits.includes(hairLengthTrait)) { npc.physicalTraits.push(hairLengthTrait); } } return npc; } } return null; }>> /* Compatibility function - always returns true since getNPCsAtLocation handles filtering */ <<set setup.isNPCAvailable = function(npcName) { return true; }>>
/* ---------------------------------- */ /* --- INITIALIZE CORE VARIABLES --- */ /* ---------------------------------- */ /* Initialize NPC array BEFORE loading data passages */ <<set $npcs = []>> <<set $metNPCs = []>> <<set $currentTradeNPC = null>> /* Function to calculate relationship bonus to trade chance */ <<set setup.getRelationshipTradeBonus = function(npcName) { var v = State.variables; if (!v.relationships[npcName]) return 0; var level = v.relationships[npcName].level; /* Level 1 (Stranger) = 0%, each level after gives +3% */ if (level <= 1) return 0; return (level - 1) * 3; }>>
/* ---------------------------------- */ /* --- TRADE CALCULATION FUNCTIONS --- */ /* ---------------------------------- */ <<set setup.calculateTradeValue = function(tradePackage, isPlayer) { var totalValue = 0; /* Add physical traits */ if (tradePackage.physical && tradePackage.physical.length > 0) { for (var i = 0; i < tradePackage.physical.length; i++) { totalValue += setup.getTraitValue("physical", tradePackage.physical[i]); } } /* Add mental traits */ if (tradePackage.mental && tradePackage.mental.length > 0) { for (var i = 0; i < tradePackage.mental.length; i++) { totalValue += setup.getTraitValue("mental", tradePackage.mental[i]); } } /* Add skills */ if (tradePackage.skills && tradePackage.skills.length > 0) { for (var i = 0; i < tradePackage.skills.length; i++) { totalValue += setup.getTraitValue("skill", tradePackage.skills[i]); } } /* Add body parts */ if (tradePackage.bodyParts && tradePackage.bodyParts.length > 0) { for (var i = 0; i < tradePackage.bodyParts.length; i++) { var part = tradePackage.bodyParts[i]; var v = State.variables; var actualValue; if (isPlayer) { actualValue = (part.name === "chest" || part.name === "butt" || part.name === "genitals") ? v.bodyParts[part.name] : v.appearance[part.name]; } else { var npc = part.npc; actualValue = (part.name === "chest" || part.name === "butt" || part.name === "genitals") ? npc.bodyParts[part.name] : npc.appearance[part.name]; } totalValue += setup.getTraitValue("bodyPart", part.name, actualValue); } } /* Add gender value (standalone property) */ if (tradePackage.gender !== null && tradePackage.gender !== undefined) { var v = State.variables; var genderValue; if (isPlayer) { /* For player package, use player's gender */ genderValue = v.bodyParts.gender; } else { /* For NPC package, use NPC's gender */ var tradingNPC = v.tradingWithNPC; if (tradingNPC && tradingNPC.bodyParts && tradingNPC.bodyParts.gender) { genderValue = tradingNPC.bodyParts.gender; } } if (genderValue) { var genderTraitValue = setup.getTraitValue("bodyPart", "gender", genderValue); totalValue += genderTraitValue; } } /* Add job value */ if (tradePackage.job !== null && tradePackage.job !== undefined) { totalValue += setup.getTraitValue("job", tradePackage.job); } /* Add name value */ if (tradePackage.name && tradePackage.name.length > 0) { totalValue += tradePackage.name.length * 5; } /* Add stats */ if (tradePackage.stats && tradePackage.stats.length > 0) { for (var i = 0; i < tradePackage.stats.length; i++) { totalValue += tradePackage.stats[i].amount; } } return totalValue; }>> <<set setup.calculateTradeValueDEBUG = function(tradePackage, isPlayer) { setup.DEBUG && console.log("=== DEBUG calculateTradeValue ==="); setup.DEBUG && console.log("isPlayer:", isPlayer); setup.DEBUG && console.log("tradePackage:", tradePackage); setup.DEBUG && console.log("tradePackage.gender:", tradePackage.gender); setup.DEBUG && console.log("tradePackage.gender !== null:", tradePackage.gender !== null); setup.DEBUG && console.log("tradePackage.gender !== undefined:", tradePackage.gender !== undefined); var totalValue = 0; /* Skip to gender section */ if (tradePackage.gender !== null && tradePackage.gender !== undefined) { setup.DEBUG && console.log("✓ INSIDE GENDER CONDITION"); var v = State.variables; var genderValue; if (isPlayer) { setup.DEBUG && console.log("→ PLAYER BRANCH"); genderValue = v.bodyParts.gender; setup.DEBUG && console.log(" genderValue from v.bodyParts.gender:", genderValue); } else { setup.DEBUG && console.log("→ NPC BRANCH"); var tradingNPC = v.tradingWithNPC; setup.DEBUG && console.log(" tradingNPC:", tradingNPC); setup.DEBUG && console.log(" tradingNPC exists?", !!tradingNPC); if (tradingNPC) { setup.DEBUG && console.log(" tradingNPC.bodyParts:", tradingNPC.bodyParts); setup.DEBUG && console.log(" tradingNPC.bodyParts.gender:", tradingNPC.bodyParts.gender); } if (tradingNPC && tradingNPC.bodyParts && tradingNPC.bodyParts.gender) { genderValue = tradingNPC.bodyParts.gender; setup.DEBUG && console.log(" ✓ genderValue set to:", genderValue); } else { setup.DEBUG && console.log(" ✗ Failed to get NPC gender value"); } } setup.DEBUG && console.log("genderValue (final):", genderValue); setup.DEBUG && console.log("genderValue is truthy?", !!genderValue); if (genderValue) { setup.DEBUG && console.log("→ CALLING setup.getTraitValue('bodyPart', 'gender', '" + genderValue + "')"); var genderTraitValue = setup.getTraitValue("bodyPart", "gender", genderValue); setup.DEBUG && console.log(" ✓ Returned value:", genderTraitValue); setup.DEBUG && console.log(" Type:", typeof genderTraitValue); totalValue += genderTraitValue; setup.DEBUG && console.log(" ✓ totalValue after adding:", totalValue); } else { setup.DEBUG && console.log("✗ SKIPPED - genderValue was falsy"); } } else { setup.DEBUG && console.log("✗ SKIPPED GENDER CONDITION - gender is null or undefined"); } setup.DEBUG && console.log("=== FINAL TOTAL:", totalValue, "==="); return totalValue; }>> <<set setup.calculatePreferenceValueAdjustment = function(npc, playerPackage, npcPackage, baseNpcValue) { var preferences = setup.getNPCPreferences(npc.name); if (!preferences) return baseNpcValue; var adjustedValue = 0; /* Entrancement waives all reluctance premiums for the entranced NPC today */ var sandmanEntranced = !!(setup.witchSpells && npc && setup.witchSpells.sandmanActiveFor(npc.name)); /* Skills - check each skill's preference */ if (npcPackage.skills && npcPackage.skills.length > 0) { for (var i = 0; i < npcPackage.skills.length; i++) { var skill = npcPackage.skills[i]; var skillValue = setup.getTraitValue("skill", skill); /* Add base value */ adjustedValue += skillValue; /* Add reluctant penalty (flat 30% more points needed) */ if (!sandmanEntranced && preferences.reluctantToTrade && preferences.reluctantToTrade.skills && preferences.reluctantToTrade.skills.includes(skill)) { adjustedValue += Math.ceil(skillValue * 0.3); } /* Apply willing discount (20% discount) */ else if (preferences.willingToTrade && preferences.willingToTrade.skills && preferences.willingToTrade.skills.includes(skill)) { adjustedValue -= Math.ceil(skillValue * 0.2); } } } /* Mental traits - check each trait's preference */ if (npcPackage.mental && npcPackage.mental.length > 0) { for (var i = 0; i < npcPackage.mental.length; i++) { var trait = npcPackage.mental[i]; var traitValue = setup.getTraitValue("mental", trait); /* Add base value */ adjustedValue += traitValue; /* Add reluctant penalty (flat 30% more points needed) */ if (!sandmanEntranced && preferences.reluctantToTrade && preferences.reluctantToTrade.mental && preferences.reluctantToTrade.mental.includes(trait)) { adjustedValue += Math.ceil(traitValue * 0.3); } /* Apply willing discount (20% discount) */ else if (preferences.willingToTrade && preferences.willingToTrade.mental && preferences.willingToTrade.mental.includes(trait)) { adjustedValue -= Math.ceil(traitValue * 0.2); } } } /* Physical traits - check each trait's preference */ if (npcPackage.physical && npcPackage.physical.length > 0) { for (var i = 0; i < npcPackage.physical.length; i++) { var trait = npcPackage.physical[i]; var traitValue = setup.getTraitValue("physical", trait); /* Add base value */ adjustedValue += traitValue; /* Add reluctant penalty (flat 30% more points needed) */ if (!sandmanEntranced && preferences.reluctantToTrade && preferences.reluctantToTrade.physical && preferences.reluctantToTrade.physical.includes(trait)) { adjustedValue += Math.ceil(traitValue * 0.3); } /* Apply willing discount (20% discount) */ else if (preferences.willingToTrade && preferences.willingToTrade.physical && preferences.willingToTrade.physical.includes(trait)) { adjustedValue -= Math.ceil(traitValue * 0.2); } } } /* Body parts - check each body part's preference */ if (npcPackage.bodyParts && npcPackage.bodyParts.length > 0) { for (var i = 0; i < npcPackage.bodyParts.length; i++) { var part = npcPackage.bodyParts[i]; /* Get the actual value from the correct location */ var actualValue; if (part.name === "chest" || part.name === "butt" || part.name === "genitals") { actualValue = npc.bodyParts[part.name]; } else if (part.name === "skinTone" || part.name === "hairColor" || part.name === "hairLength" || part.name === "age") { actualValue = npc.appearance[part.name]; } var partValue = setup.getTraitValue("bodyPart", part.name, actualValue); /* Add base value */ adjustedValue += partValue; /* Add reluctant penalty (flat 30% more points needed) */ if (!sandmanEntranced && preferences.reluctantToTrade && preferences.reluctantToTrade.bodyParts && preferences.reluctantToTrade.bodyParts.includes(part.name)) { adjustedValue += Math.ceil(partValue * 0.3); } /* Apply willing discount (20% discount) */ else if (preferences.willingToTrade && preferences.willingToTrade.bodyParts && preferences.willingToTrade.bodyParts.includes(part.name)) { adjustedValue -= Math.ceil(partValue * 0.2); } } } /* Gender - check gender preference (standalone property) */ if (npcPackage.gender !== null && npcPackage.gender !== undefined) { var genderValue = 0; /* Get the NPC's actual gender value */ if (npc && npc.bodyParts && npc.bodyParts.gender) { genderValue = setup.getTraitValue("bodyPart", "gender", npc.bodyParts.gender); } /* Add base value */ adjustedValue += genderValue; /* Check if NPC has gender preferences */ if (preferences.neverTrade && preferences.neverTrade.gender) { /* Extreme cost to make trade essentially impossible */ adjustedValue += genderValue * 9; /* 10x total cost */ } else if (!sandmanEntranced && preferences.reluctantToTrade && preferences.reluctantToTrade.gender) { /* Add 30% more points needed */ adjustedValue += Math.ceil(genderValue * 0.3); } else if (preferences.willingToTrade && preferences.willingToTrade.gender) { /* 20% discount */ adjustedValue -= Math.ceil(genderValue * 0.2); } } /* Job - check job preference */ if (npcPackage.job !== null && npcPackage.job !== undefined) { var jobValue = setup.getTraitValue("job", npcPackage.job || "Unemployed"); /* Add base value */ adjustedValue += jobValue; /* Add reluctant penalty (flat 30% more points needed) */ if (!sandmanEntranced && preferences.reluctantToTrade && preferences.reluctantToTrade.job) { adjustedValue += Math.ceil(jobValue * 0.3); } /* Apply willing discount (20% discount) */ else if (preferences.willingToTrade && preferences.willingToTrade.job) { adjustedValue -= Math.ceil(jobValue * 0.2); } } /* Name parts - no preference modifiers, just add base value */ if (npcPackage.name && npcPackage.name.length > 0) { adjustedValue += npcPackage.name.length * 5; } /* Stats - no preference modifiers, just add base value */ if (npcPackage.stats && npcPackage.stats.length > 0) { for (var i = 0; i < npcPackage.stats.length; i++) { adjustedValue += npcPackage.stats[i].amount; } } return Math.max(0, adjustedValue); }>> <<set setup.calculateTradeChance = function(playerValue, npcValue, npc, playerPackage, npcPackage) { /* Quest trades always succeed — check if this NPC has an active quest */ var qv = State.variables; if (qv.questData && qv.questData.active && npc && npc.name) { var activeIds = Object.keys(qv.questData.active); for (var qi = 0; qi < activeIds.length; qi++) { var qDef = setup.quests[activeIds[qi]]; if (qDef && qDef.involvedNPCs && qDef.involvedNPCs.indexOf(npc.name) !== -1) { return 100; } } } /* If player is offering negative or zero value, automatic fail */ if (playerValue <= 0) { return 0; } if (npcValue === 0) return 100; var v = State.variables; var ratio = playerValue / npcValue; var chance; /* Need at least equal value for any chance */ if (playerValue < npcValue) { return 0; } /* Equal value = 1% base chance */ if (ratio === 1.0) { chance = 1; } /* 1.7x or more = 100% chance */ else if (ratio >= 1.7) { chance = 100; } /* Calculate chance between 1% and 100% based on ratio */ else { /* At 1.0x = 1%, at 1.7x = 100% */ /* Range is 0.7 (from 1.0 to 1.7), giving us 99% spread (from 1% to 100%) */ var normalizedRatio = (ratio - 1.0) / 0.7; /* Normalize to 0-1 range */ chance = 1 + (normalizedRatio * 99); /* Map to 1-100% range */ chance = Math.round(chance); } /* Apply charisma bonus: 1% per 3.75 charisma (including bonus charisma) */ /* Capped at 40% (achieved at 150 charisma) */ var totalCharisma = setup.getTotalStat("charisma"); var charismaBonus = 0; if (totalCharisma > 0) { charismaBonus = Math.min(40, Math.floor(totalCharisma / 3.75)); } chance += charismaBonus; /* Apply Trading skill bonus: +2% */ if (v.skills.includes("Trading")) { chance += 2; } /* Apply Persuasion skill bonus: +3% */ if (v.skills.includes("Persuasion")) { chance += 3; } /* Apply Sunfish trait bonus: +10% */ if (v.mentalTraits.includes("Sunfish")) { chance += 10; } /* Werefox +10% trade bonus */ if (v.physicalTraits && v.physicalTraits.includes("Werefox")) { chance += 10; } /* Siren +30% trade bonus - Siren is a physical trait */ if (v.physicalTraits && v.physicalTraits.includes("Siren")) { chance += 30; } /* ===== SKILL TREE: Trade Success Bonus ===== */ var skillTreeTradeBonus = setup.skillTree.getEffect("tradeSuccessBonus"); if (skillTreeTradeBonus > 0) { chance += skillTreeTradeBonus; } /* ===== BUFF SYSTEM: Apply tradeChance buffs (e.g., shower_fresh, well_rested, food buffs) ===== */ var buffTradeBonus = setup.getBuffEffect("tradeChance"); if (buffTradeBonus > 0) { chance += buffTradeBonus; } /* ===== DEBUFF SYSTEM: Apply tradeChance debuffs (e.g., exhaustion) ===== */ var debuffTradePenalty = setup.getDebuffEffect("tradeChance"); if (debuffTradePenalty !== 0) { chance += debuffTradePenalty; } /* Define beneficial mental traits that improve trading (+2% each) */ var beneficialTraits = [ "Honest", "Confident", "Friendly", "Trusting", "Patient", "Intelligent", "Analytical", "Chill", "Nonchalant", "Charming", "Diplomatic", "Polite", "Reassuring", "Efficient", "Warm", "Lucky", "Cerberus", "Werecat", "Weresheep", "Himbo", "Werefox", "Trophy Wife", "Werebunny", "Punk", "Gym Bunny", "Siren" ]; /* Define detrimental mental traits that hurt trading (-3% each) */ var detrimentalTraits = [ "Aggressive", "Awkward", "Blunt", "Corrupt", "Moody", "Pessimistic", "Sensitive", "Shy", "Stubborn", "Arrogant", "Cold", "Deceitful", "Foolish", "Forgetful", "Impatient", "Insecure", "Reckless", "Rude", "Selfish", "Short Tempered", "Unlucky", "Bad Luck", "Unreliable", "Bitchy" ]; /* Count beneficial traits */ var beneficialCount = 0; for (var i = 0; i < beneficialTraits.length; i++) { if (v.mentalTraits.includes(beneficialTraits[i])) { beneficialCount++; } } var beneficialBonus = Math.ceil(beneficialCount * 2); /* +2% per trait, round up */ chance += beneficialBonus; /* Count detrimental traits */ var detrimentalCount = 0; for (var i = 0; i < detrimentalTraits.length; i++) { if (v.mentalTraits.includes(detrimentalTraits[i])) { detrimentalCount++; } } var detrimentalPenalty = Math.ceil(detrimentalCount * 3); /* -3% per trait, round up */ chance -= detrimentalPenalty; /* Apply NPC preference modifier */ var preferenceModifier = setup.calculatePreferenceModifier(npc, playerPackage, npcPackage); chance += preferenceModifier; /* Apply relationship bonus */ var relationshipBonus = setup.getRelationshipTradeBonus(npc.name); chance += relationshipBonus; /* Apply Criminal job penalty: Multiplicative 75% reduction (keep only 25% of chance) */ /* This is applied AFTER all additive bonuses but BEFORE Drifter's Coin */ if (v.jobs && v.jobs.includes("Criminal")) { chance = Math.floor(chance * 0.25); /* 75% penalty = multiply by 0.25 */ } /* Apply Drifter's Coin multiplier (2x) BEFORE final clamping */ if (v.currentArtifact === "The Drifter's Coin" || (v.physicalTraits && v.physicalTraits.includes("Naiad"))) { chance = chance * 2; } /* Pyrow: +25% trade chance on clear weather days */ if (v.physicalTraits && v.physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()) { chance += 25; } /* Clamp between 0 and 100 */ return Math.max(0, Math.min(100, Math.round(chance))); }>> /* ---------------------------------- */ /* --- TRADE RELATIONSHIP BONUS --- */ /* ---------------------------------- */ <<set setup.addTradeRelationshipBonus = function(npc, playerPackage, npcPackage) { var v = State.variables; var preferences = setup.getNPCPreferences(npc.name); var baseBonus = 5; /* Base relationship bonus for successful trade */ var desiredBonus = 0; /* Check if the NPC received something they desired */ if (preferences && preferences.desires) { /* Check physical traits the NPC received (from player package) */ if (playerPackage.physical && preferences.desires.physical) { for (var i = 0; i < playerPackage.physical.length; i++) { if (preferences.desires.physical.includes(playerPackage.physical[i])) { desiredBonus += 10; /* +10 per desired trait received */ } } } /* Check mental traits the NPC received */ if (playerPackage.mental && preferences.desires.mental) { for (var i = 0; i < playerPackage.mental.length; i++) { if (preferences.desires.mental.includes(playerPackage.mental[i])) { desiredBonus += 10; } } } /* Check skills the NPC received */ if (playerPackage.skills && preferences.desires.skills) { for (var i = 0; i < playerPackage.skills.length; i++) { if (preferences.desires.skills.includes(playerPackage.skills[i])) { desiredBonus += 10; } } } } /* ===== SKILL TREE: Trade Relationship Bonus ===== */ /* Add bonus relationship points when NPC received desired items */ if (desiredBonus > 0) { var skillTreeRelBonus = setup.skillTree.getEffect("tradeRelationshipBonus"); if (skillTreeRelBonus > 0) { desiredBonus += skillTreeRelBonus; } } return baseBonus + desiredBonus; }>> /* ---------------------------------- */ /* --- APPLY SKILL TREE VALUE REDUCTION --- */ /* ---------------------------------- */ <<set setup.applyTradeValueReduction = function(adjustedValue) { /* Get skill tree trade value reduction bonus */ var reduction = setup.skillTree.getEffect("tradeValueReduction"); if (reduction > 0) { adjustedValue = Math.max(0, adjustedValue - reduction); } return adjustedValue; }>>
/* ---------------------------------- */ /* --- NPC MEETING & RELATIONSHIP UPDATE --- */ /* ---------------------------------- */ <<set setup.meetNPC = function(npc) { var v = State.variables; var npcName = typeof npc === 'string' ? npc : npc.name; /* Check if already met */ if (v.metNPCs.includes(npcName)) { return; /* Already met, do nothing */ } /* Add to met NPCs */ v.metNPCs.push(npcName); /* Initialize relationship if it doesn't exist */ if (!v.relationships[npcName]) { v.relationships[npcName] = { level: 0, points: 0 }; } }>> <<set setup.addRelationshipPoints = function(npcName, points) { var v = State.variables; /* During Roisin possession, v.relationships IS already her view (swapped in by setup.possession.applyRoisin and stashed back on revert). Writes naturally land in her tracker. */ /* Initialize relationship if it doesn't exist */ if (!v.relationships[npcName]) { var startPts = 0; if (typeof setup.skillTree !== 'undefined') { startPts = setup.skillTree.getEffect("firstImpressionBonus") || 0; } v.relationships[npcName] = { level: 0, points: startPts }; } /* Weresheep 2x relationship bonus (only for positive gains) */ if (points > 0 && v.physicalTraits && v.physicalTraits.includes("Weresheep")) { points = points * 2; } /* Himbo 2x relationship bonus with male NPCs (only for positive gains) */ if (points > 0 && v.physicalTraits && v.physicalTraits.includes("Himbo")) { var npc = setup.getNPCByName(npcName); if (npc && npc.bodyParts && npc.bodyParts.gender === "male") { points = points * 2; } } /* Gyaru 2x relationship bonus with male NPCs (only for positive gains) */ if (points > 0 && v.physicalTraits && v.physicalTraits.includes("Gyaru")) { var npc = setup.getNPCByName(npcName); if (npc && npc.bodyParts && npc.bodyParts.gender === "male") { points = points * 2; } } /* Cupid 4x relationship bonus (only for positive gains) */ if (points > 0 && v.physicalTraits && v.physicalTraits.includes("Cupid")) { points = points * 4; } /* Pyrow +25% relationship bonus on clear weather days (only for positive gains) */ if (points > 0 && v.physicalTraits && v.physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()) { points = Math.floor(points * 1.25); } /* Naiad / Gentle Giant's Heart 8x relationship bonus, normal + romance (only for positive gains) */ if (points > 0 && (v.currentArtifact === "The Gentle Giant's Heart" || (v.physicalTraits && v.physicalTraits.includes("Naiad")))) { points = points * 8; } /* Skill tree: Charmer relationship gain bonus */ if (points > 0 && typeof setup.skillTree !== 'undefined') { var relBonus = setup.skillTree.getEffect("relationshipGainBonus") || 0; if (relBonus > 0) points = Math.floor(points * (1 + relBonus / 100)); } /* Beguile spell: double positive gains with the beguiled NPC today */ if (points > 0 && v.beguileTarget === npcName && v.beguileDay === v.dayNumber) { points = points * 2; } /* Automaton: No relationship gains */ if (v.physicalTraits && v.physicalTraits.includes("Automaton")) { if (points > 0) points = 0; } /* Store old level for achievement checking */ var oldLevel = v.relationships[npcName].level; /* Add points (can be negative) */ v.relationships[npcName].points += points; /* Clamp to minimum -50 (Disliked floor) */ if (v.relationships[npcName].points < -50) { v.relationships[npcName].points = -50; } /* Calculate new level based on points using the new system */ /* Level -1: Disliked (-50 to -1) */ /* Level 0: Stranger (0 to 24) */ /* Level 1: Acquaintance (25 to 74) */ /* Level 2: Friend (75 to 174) */ /* Level 3: Close Friend (175 to 424) */ /* Level 4: Best Friend (425 to 599) */ /* Level 5: Confidant (600+) */ var currentPoints = v.relationships[npcName].points; var newLevel = setup.calculateRelationshipLevel(currentPoints); v.relationships[npcName].level = newLevel; /* Record milestone in memory system */ if (newLevel > oldLevel && setup.recordMilestone) { setup.recordMilestone(npcName, newLevel); } /* Relationship level achievements - check both $relationships and $npcRelationships */ var npcRelLevel = (v.npcRelationships && v.npcRelationships[npcName]) ? v.npcRelationships[npcName].level : -99; var maxLevel = Math.max(newLevel, npcRelLevel); if (newLevel >= 2 && oldLevel < 2) { setup.achievements.unlock("relationship_2"); } if (newLevel >= 4 && oldLevel < 4) { setup.achievements.unlock("relationship_4"); /* Award Heart trait on first level 4 relationship (skip if already have Heart or Cupid) */ if (newLevel >= 4 && oldLevel < 4 && v.physicalTraits && !v.physicalTraits.includes("Heart") && !v.physicalTraits.includes("Cupid")) { v.physicalTraits.push("Heart"); } } /* Add romance-specific points for romantic NPCs */ if (v.npcRomance && v.npcRomance[npcName] && points > 0) { if (typeof v.npcRomance[npcName].romancePoints !== "number") v.npcRomance[npcName].romancePoints = 0; v.npcRomance[npcName].romancePoints += points; } /* Check romance level transition for romantic NPCs */ if (setup.romance && setup.romance.checkLevelTransition && v.npcRomance && v.npcRomance[npcName]) { setup.romance.checkLevelTransition(npcName); } /* Return the updated relationship for verification */ return v.relationships[npcName]; }>> /* Wrapper for sexual relationship gains — applies Pillow Talk bonus */ <<set setup.addSexualRelationshipPoints = function(npcName, points) { if (points > 0 && typeof setup.skillTree !== 'undefined') { var sexRelBonus = setup.skillTree.getEffect("sexRelationshipBonus") || 0; if (sexRelBonus > 0) points = Math.floor(points * (1 + sexRelBonus / 100)); } return setup.addRelationshipPoints(npcName, points); }>> <<set setup.updateNPCRelationshipKey = function(oldName, newName) { var v = State.variables; /* Update metNPCs array */ var metIndex = v.metNPCs.indexOf(oldName); if (metIndex !== -1) { v.metNPCs[metIndex] = newName; } /* Transfer relationship data to new name */ if (v.relationships[oldName]) { v.relationships[newName] = v.relationships[oldName]; delete v.relationships[oldName]; } }>> <<set setup.updateRelationshipFromTrade = function(npc, playerPackage, npcPackage, tradeSucceeded) { var v = State.variables; var npcName = npc.name; /* Ensure relationship exists */ if (!v.relationships[npcName]) { v.relationships[npcName] = { level: 1, points: 0 }; } var prefs = setup.getNPCPreferences(npcName); if (!prefs) return; /* No preferences set */ var pointsChange = 0; /* Check what player OFFERED (things NPC receives) */ /* DESIRES - NPC wants these (+2 points per desired item) */ if (prefs.desires) { if (prefs.desires.skills) { playerPackage.skills.forEach(function(skill) { if (prefs.desires.skills.includes(skill)) { pointsChange += 2; } }); } if (prefs.desires.mental) { playerPackage.mental.forEach(function(trait) { if (prefs.desires.mental.includes(trait)) { pointsChange += 2; } }); } if (prefs.desires.physical) { playerPackage.physical.forEach(function(trait) { if (prefs.desires.physical.includes(trait)) { pointsChange += 2; } }); } if (prefs.desires.bodyParts) { playerPackage.bodyParts.forEach(function(part) { if (prefs.desires.bodyParts.includes(part.name)) { pointsChange += 2; } }); } } /* Check what player TOOK from NPC (things NPC loses) */ /* RELUCTANT - NPC doesn't want to give these (-1 point per reluctant item) */ if (prefs.reluctantToTrade && tradeSucceeded) { if (prefs.reluctantToTrade.skills) { npcPackage.skills.forEach(function(skill) { if (prefs.reluctantToTrade.skills.includes(skill)) { pointsChange -= 1; } }); } if (prefs.reluctantToTrade.mental) { npcPackage.mental.forEach(function(trait) { if (prefs.reluctantToTrade.mental.includes(trait)) { pointsChange -= 1; } }); } if (prefs.reluctantToTrade.physical) { npcPackage.physical.forEach(function(trait) { if (prefs.reluctantToTrade.physical.includes(trait)) { pointsChange -= 1; } }); } if (prefs.reluctantToTrade.bodyParts) { npcPackage.bodyParts.forEach(function(part) { if (prefs.reluctantToTrade.bodyParts.includes(part.name)) { pointsChange -= 1; } }); } } /* Apply points change */ if (pointsChange !== 0) { setup.addRelationshipPoints(npcName, pointsChange); } }>> <<set setup.calculateTradeValue = function(tradePackage, isPlayer) { var v = State.variables; var totalValue = 0; /* Calculate value from skills */ if (tradePackage.skills && tradePackage.skills.length > 0) { for (var i = 0; i < tradePackage.skills.length; i++) { totalValue += setup.getTraitValue("skill", tradePackage.skills[i]); } } /* Calculate value from mental traits */ if (tradePackage.mental && tradePackage.mental.length > 0) { for (var i = 0; i < tradePackage.mental.length; i++) { totalValue += setup.getTraitValue("mental", tradePackage.mental[i]); } } /* Calculate value from physical traits */ if (tradePackage.physical && tradePackage.physical.length > 0) { for (var i = 0; i < tradePackage.physical.length; i++) { totalValue += setup.getTraitValue("physical", tradePackage.physical[i]); } } /* Calculate value from body parts */ if (tradePackage.bodyParts && tradePackage.bodyParts.length > 0) { for (var i = 0; i < tradePackage.bodyParts.length; i++) { var part = tradePackage.bodyParts[i]; var actualValue; /* Get the actual value from the correct location */ if (isPlayer) { if (part.name === "chest" || part.name === "butt" || part.name === "gender" || part.name === "genitals") { actualValue = v.bodyParts[part.name]; } else if (part.name === "skinTone" || part.name === "hairColor" || part.name === "hairLength" || part.name === "age") { actualValue = v.appearance[part.name]; } } else { /* For NPC, need to get from tradingWithNPC */ var npc = v.tradingWithNPC; if (part.name === "chest" || part.name === "butt" || part.name === "gender" || part.name === "genitals") { actualValue = npc.bodyParts[part.name]; } else if (part.name === "skinTone" || part.name === "hairColor" || part.name === "hairLength" || part.name === "age") { actualValue = npc.appearance[part.name]; } } if (actualValue && actualValue !== "") { var partValue = setup.getTraitValue("bodyPart", part.name, actualValue); totalValue += partValue; } } } /* Calculate value from job */ if (tradePackage.job !== null && tradePackage.job !== undefined) { totalValue += setup.getTraitValue("job", tradePackage.job); } /* Calculate value from name parts */ if (tradePackage.name && tradePackage.name.length > 0) { totalValue += tradePackage.name.length * 5; /* 5 points per name part */ } /* Calculate value from stats */ if (tradePackage.stats && tradePackage.stats.length > 0) { for (var i = 0; i < tradePackage.stats.length; i++) { totalValue += tradePackage.stats[i].amount; } } return totalValue; }>>
/* ---------------------------------- */ /* --- NPC TRADING PREFERENCES --- */ /* ---------------------------------- */ <<set setup.npcTradingPreferences = { /* Puffy's Maid Cafe Staff - won't trade transformations, hair, or jobs */ "Mochi": { neverTrade: {name: true, job: true, bodyParts: ["hairColor"], physical: ["Werecat"]}, desires: { skills: ["Acrobatics", "Dancing"], mental: ["Brave", "Confident"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: ["Energetic"], physical: ["Smooth Skin"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Cooking"], mental: ["Kind"], physical: ["Cute"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, refuseToTrade: ["Werecat", "Maid"] }, "Ren": { neverTrade: {name: true, job: true, bodyParts: ["hairColor"], physical: ["Kitsune"]}, desires: { skills: ["Cooking", "Painting"], mental: ["Submissive"], physical: ["Cute"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Public Speaking"], mental: ["Calm"], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Acting"], mental: ["Confident"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, refuseToTrade: ["Kitsune", "Maid"] }, "Clover": { neverTrade: {name: true, job: true, bodyParts: ["hairColor"], physical: ["Lactating", "Hucow"]}, wontTradeFor: { chestSize: ["flat", "flat masculine", "small", "medium", "large", "huge"], buttSize: ["flat", "flat masculine", "small", "medium", "large", "huge"] }, desires: { skills: ["Cooking", "Gardening"], mental: ["Patient", "Kind"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Heavy Lifting"], mental: [], physical: ["Smooth Skin"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Cooking"], mental: ["Kind"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, refuseToTrade: ["Hucow", "Lactating", "Maternal", "Maid"] }, "Marcus Carter": { desires: { skills: ["Medicine", "Coding"], mental: ["Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Combat", "Athletics", "Public Speaking", "Acting"], mental: ["Confident", "Brave"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Guitar"], mental: ["Outgoing"], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Shy", "Cowardly"], physical: ["Weak", "Underweight", "Ugly"], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] } }, "Elena Romero": { desires: { skills: ["Languages", "Art"], mental: ["Creative", "Empathetic"], physical: ["Attractive"], bodyParts: [], chestSize: ["medium", "large"], buttSize: ["medium", "large"], genitals: [] }, willingToTrade: { skills: ["Coding", "Math Skills", "Painting"], mental: ["Analytical", "Shy"], physical: ["Graceful", "Youthful"], bodyParts: [], chestSize: ["small"], buttSize: ["small"], genitals: [], job: true }, reluctantToTrade: { skills: ["Medicine", "First Aid"], mental: ["Patient", "Kind", "Intelligent"], physical: ["Sharp Features"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cruel", "Aggressive", "Arrogant"], physical: ["Muscular", "Scarred", "Ugly"], bodyParts: [], chestSize: ["giant","flat masculine"], buttSize: ["giant","flat masculine"], genitals: [] } }, "Silva Silva": { desires: { skills: ["Management", "Accounting"], mental: ["Diplomatic", "Organized"], physical: ["Fashionable", "Attractive"], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["large", "huge"], genitals: [] }, willingToTrade: { skills: ["Driving", "Athletics", "Languages"], mental: ["Ambitious"], physical: ["Quick", "Lean"], bodyParts: [], chestSize: ["medium"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Persuasion", "Public Speaking"], mental: ["Shrewd", "Confident"], physical: ["Athletic Build"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Disorganized", "Dull"], physical: ["Overweight", "Clumsy", "Plain"], bodyParts: [], chestSize: ["small", "flat"], buttSize: ["small", "flat"], genitals: [] } }, "Grimm Patel": { desires: { skills: ["Legal Knowledge"], mental: ["Calm", "Patient"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Cooking"], mental: ["Stubborn", "Cynical"], physical: ["Scarred"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Combat", "Stealth", "Persuasion"], mental: ["Dominant", "Shrewd"], physical: ["Muscular", "Strong"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Naive", "Trusting", "Submissive"], physical: ["Weak", "Youthful", "Soft"], bodyParts: [], chestSize: ["medium", "large", "huge", "giant"], buttSize: ["medium", "large", "huge", "giant"], genitals: [] } }, "Scarlett Vex": { desires: { skills: ["Management", "Business"], mental: ["Shrewd", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Photography", "Dancing"], mental: ["Ambitious", "Arrogant"], physical: ["Fit", "Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled", "Acting", "Modeling"], mental: ["Confident", "Outgoing"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Submissive"], physical: ["Ugly", "Plain", "Overweight"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Jade Nightshade": { desires: { skills: ["Persuasion", "Social Media"], mental: ["Confident", "Alluring"], physical: ["Voluptuous"], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Singing", "Acting"], mental: ["Creative"], physical: ["Flexible", "Graceful"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Dancing", "Sexually Skilled"], mental: ["Sly"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Honest", "Naive", "Insecure"], physical: ["Plain", "Stiff", "Clumsy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Apollo Sterling": { desires: { skills: ["Acting", "Photography"], mental: ["Ambitious", "Charismatic"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Music", "Athletics"], mental: ["Creative"], physical: ["Flexible", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Dancing", "Modeling"], mental: ["Confident", "Outgoing"], physical: ["Muscular"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Awkward", "Insecure"], physical: ["Ugly", "Overweight", "Weak"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Diamond Murphy": { desires: { skills: ["Management", "Sales"], mental: ["Organized", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Baking", "Stealth"], mental: ["Stubborn", "Selfish"], physical: ["Tattooed"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled", "Persuasion"], mental: ["Sly", "Hardworking"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Naive", "Trusting", "Kind"], physical: ["Soft", "Youthful", "Plain"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Tank Morrison": { desires: { skills: ["First Aid", "Driving"], mental: ["Patient", "Intelligent"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Cooking", "Athletics"], mental: [], physical: ["Scarred"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Combat", "Heavy Lifting"], mental: ["Brave", "Calm", "Honest", "Loyal"], physical: ["Muscular", "Tall", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Deceitful", "Selfish", "Cowardly"], physical: ["Weak", "Clumsy", "Frail"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Candace Luxe": { desires: { skills: ["Photography", "Art"], mental: ["Creative", "Sensitive"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Painting", "Dancing"], mental: ["Friendly", "Empathetic"], physical: ["Pierced", "Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Confident", "Warm"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cold", "Cruel", "Aggressive"], physical: ["Scarred", "Blemished", "Ugly"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Ruby Becker": { desires: { skills: ["Public Speaking", "Acting"], mental: ["Confident", "Outgoing"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Writing", "Photography"], mental: ["Creative", "Shy"], physical: ["Freckled", "Smooth Skin"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Kind", "Sensitive"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cruel", "Aggressive", "Arrogant"], physical: ["Scarred", "Ugly", "Overweight"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Sapphire Wallace": { desires: { skills: ["Management", "Business"], mental: ["Shrewd", "Organized"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Martial Arts", "Dancing"], mental: ["Ambitious", "Aggressive"], physical: ["Tattooed", "Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Dominant", "Confident"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Shy", "Weak"], physical: ["Soft", "Weak", "Plain"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Jasmine Abrams": { desires: { skills: ["Meditation", "Art"], mental: ["Calm", "Creative"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Yoga"], mental: ["Patient", "Submissive"], physical: ["Flexible", "Graceful", "Smooth Skin"], bodyParts: [], chestSize: ["medium"], buttSize: ["huge"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled", "Dancing"], mental: ["Friendly", "Kind"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Scarred", "Ugly", "Stiff"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Ebony Vasquez": { desires: { skills: ["Management", "Public Speaking"], mental: ["Confident", "Ambitious"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Acting", "Singing"], mental: ["Competitive"], physical: ["Smooth Skin"], bodyParts: [], chestSize: ["large"], buttSize: ["huge"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Sly", "Witty"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Dull"], physical: ["Ugly", "Plain", "Clumsy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Amber Skye": { desires: { skills: ["Photography", "Acting"], mental: ["Creative", "Ambitious"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Social Media", "Music"], mental: ["Curious", "Naive"], physical: ["Youthful", "Smooth Skin"], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Optimistic", "Energetic"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cynical", "Cruel", "Pessimistic"], physical: ["Scarred", "Ugly", "Mature"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Kate Velvet": { desires: { skills: ["Legal Knowledge", "Public Speaking"], mental: ["Intelligent", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Languages"], mental: ["Arrogant"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Management", "Persuasion", "Accounting", "Sexually Skilled"], mental: ["Dominant", "Shrewd", "Ambitious", "Confident"], physical: ["Attractive", "Mature", "Voluptuous", "Sharp Features"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], genitals: [], job: false }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Naive", "Foolish"], physical: ["Ugly", "Youthful", "Plain"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Bella Carver": { desires: { skills: ["Management", "Business"], mental: ["Shrewd", "Organized"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Acting", "Makeup"], mental: ["Creative", "Naive"], physical: ["Youthful"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Social Media", "Photography"], mental: ["Outgoing", "Ambitious"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Introverted", "Cynical", "Mature"], physical: ["Ugly", "Mature", "Scarred"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Jake Steel": { desires: { skills: ["Mechanical Repair"], mental: ["Patient", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Fishing", "Driving"], mental: ["Calm"], physical: ["Sturdy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Hardworking", "Honest", "Loyal"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Deceitful", "Lazy"], physical: ["Weak", "Clumsy", "Soft"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Marco Rodriguez": { desires: { skills: ["Dancing", "Music"], mental: ["Creative", "Outgoing"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Cooking", "Guitar"], mental: ["Friendly"], physical: ["Tattooed"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Competitive", "Brave"], physical: ["Muscular", "Strong", "Sturdy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Introverted", "Cold"], physical: ["Weak", "Stiff", "Plain"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Tyrone Washington": { desires: { skills: ["Business", "Public Speaking"], mental: ["Ambitious", "Confident"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Basketball", "Music"], mental: [], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Outgoing", "Witty"], physical: ["Muscular", "Strong", "Sturdy", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Submissive"], physical: ["Short", "Weak", "Ugly"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Sheryl Williams": { desires: { skills: ["Management", "Leadership"], mental: ["Organized", "Diplomatic"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Gardening"], mental: ["Stubborn"], physical: ["Athletic Build"], bodyParts: [], chestSize: ["small"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction", "Martial Arts"], mental: ["Hardworking", "Brave"], physical: ["Muscular", "Strong", "Sturdy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Shy", "Weak"], physical: ["Soft", "Weak", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "David O'Brien": { desires: { skills: ["Art", "Music"], mental: ["Creative", "Calm"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Plumbing", "Painting"], mental: [], physical: ["Freckled"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Calm", "Patient", "Thoughtful"], physical: ["Muscular", "Strong", "Sturdy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Loud", "Arrogant"], physical: ["Weak", "Clumsy", "Ugly"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Mike Murphy": { desires: { skills: ["Combat Training"], mental: ["Disciplined", "Focused"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], desiredJob: "Brothel Worker" }, willingToTrade: { skills: ["Cooking", "Swimming"], mental: ["Aggressive", "Short Tempered"], physical: ["Tattooed"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Competitive", "Brave"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Calm", "Patient", "Submissive"], physical: ["Weak", "Soft", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Carlos Mendez": { desires: { skills: ["Cooking", "Performance"], mental: ["Creative", "Charming"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Dancing", "Guitar"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Friendly", "Outgoing", "Optimistic"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cold", "Cruel", "Pessimistic"], physical: ["Ugly", "Scarred", "Weak"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Jamal Rivers": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Basketball", "Writing"], mental: [], physical: ["Athletic Build"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Intelligent", "Competitive"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Foolish", "Disorganized"], physical: ["Weak", "Overweight", "Clumsy"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Rosa Otterino": { desires: { skills: ["Art", "Photography"], mental: ["Creative", "Patient"], physical: [], bodyParts: [], chestSize: ["medium", "large"], buttSize: ["large", "huge"], genitals: [] }, willingToTrade: { skills: ["Swimming", "Painting"], mental: [], physical: ["Athletic Build", "Tattooed"], bodyParts: [], chestSize: ["small"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Hardworking", "Honest", "Calm"], physical: ["Muscular", "Strong"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Deceitful", "Lazy"], physical: ["Weak", "Soft", "Clumsy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Keisha Jackson": { desires: { skills: ["Performance", "Music"], mental: ["Creative", "Outgoing"], physical: ["Attractive"], bodyParts: [], chestSize: ["large", "huge","flat masculine"], buttSize: ["huge", "giant","flat masculine"], genitals: [] }, willingToTrade: { skills: ["Singing", "Cooking"], mental: [], physical: ["Curvy"], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Confident", "Outgoing", "Brave"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Introverted", "Cold"], physical: ["Weak", "Plain", "Slim"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Dick Richardson": { desires: { skills: ["Business", "Finance"], mental: ["Shrewd", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: ["Arrogant", "Selfish"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Public Speaking", "Management", "Legal Knowledge"], mental: ["Shrewd", "Ambitious", "Dominant"], physical: ["Mature", "Sharp Features"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Honest", "Kind", "Submissive"], physical: ["Youthful", "Attractive", "Weak"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Creo Applesauce": { desires: { skills: ["Art", "Music"], mental: ["Creative", "Confident"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Piano", "Languages"], mental: ["Submissive", "Anxious", "Corporate Drone"], physical: ["Lean"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Management", "Accounting", "Coding"], mental: ["Intelligent", "Analytical", "Patient"], physical: ["Sharp Features"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Dominant", "Arrogant"], physical: ["Muscular", "Scarred", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Brad Icus": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Gardening", "Cooking"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Athletics", "Sales", "Heavy Lifting"], mental: ["Energetic", "Friendly", "Optimistic"], physical: ["Fit", "Muscular", "Athletic Build", "Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Pessimistic", "Introverted"], physical: ["Weak", "Overweight", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Raven Bido": { desires: { skills: ["Music", "Performance"], mental: ["Confident", "Outgoing"], physical: [], bodyParts: [], chestSize: ["medium", "large","flat masculine"], buttSize: ["medium", "large","flat masculine"], genitals: [] }, willingToTrade: { skills: [], mental: ["Introverted", "Shy"], physical: ["Lean", "Youthful"], bodyParts: [], chestSize: ["small"], buttSize: ["small"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sales", "Art", "Painting", "Music", "Writing"], mental: ["Creative", "Curious"], physical: ["Tattooed", "Pierced"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Prep", "Optimistic"], physical: ["Plain", "Fashionable", "Smooth Skin"], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [] } }, "Crystal Meffin": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["large", "huge"], genitals: [] }, willingToTrade: { skills: ["Art", "Photography"], mental: [], physical: ["Youthful"], bodyParts: [], chestSize: ["medium"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Hair Styling", "Makeup"], mental: ["Friendly", "Outgoing", "Creative"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Introverted", "Cynical", "Rude"], physical: ["Ugly", "Clumsy", "Scarred"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Sophi Boris": { desires: { skills: ["Acting", "Performance"], mental: ["Creative", "Confident"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Social Media", "Singing"], mental: ["Arrogant"], physical: ["Curvy"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Hair Styling", "Makeup", "Dancing"], mental: ["Witty", "Ambitious"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Humble", "Submissive"], physical: ["Plain", "Ugly", "Stiff"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Naomi Light": { desires: { skills: ["Meditation", "Teaching"], mental: ["Calm", "Wise"], physical: [], bodyParts: [], chestSize: ["medium", "large","flat masculine"], buttSize: ["large", "huge","flat masculine"], genitals: [] }, willingToTrade: { skills: ["Yoga", "Gardening"], mental: [], physical: ["Flexible"], bodyParts: [], chestSize: ["small"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Hair Styling", "Makeup"], mental: ["Kind", "Patient", "Empathetic"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Scarred", "Ugly", "Stiff"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Kevin Oats": { desires: { skills: ["Social Skills", "Public Speaking"], mental: ["Confident", "Outgoing"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], desiredJob: "Brothel Worker" }, willingToTrade: { skills: ["Gaming"], mental: ["Shy", "Awkward", "Insecure"], physical: ["Lean", "Youthful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Coding", "Sales", "Math Skills"], mental: ["Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: ["flat masculine"], buttSize: ["flat masculine"], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Aggressive", "Dominant"], physical: ["Ugly", "Muscular", "Scarred"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Destiny Pumpkin": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Art", "Writing"], mental: ["Selfish"], physical: ["Tattooed", "Pierced"], bodyParts: [], chestSize: ["huge"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Sales", "Persuasion", "Sexually Skilled"], mental: ["Confident", "Sly", "Creative"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Kind", "Honest", "Submissive"], physical: ["Plain", "Ugly", "Soft"], bodyParts: [], chestSize: ["flat", "small", "medium"], buttSize: ["flat", "small"], genitals: [] } }, "Alex Passionfruit": { desires: { skills: ["Art", "Photography"], mental: ["Creative", "Sensitive"], physical: [], bodyParts: ["huge"], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Music", "Gaming"], mental: [], physical: ["Lean", "Pierced"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Sales", "Persuasion", "Sexually Skilled"], mental: ["Outgoing", "Witty", "Curious"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: ["Femboy"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Ugly", "Muscular", "Overweight"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Hannah Chuckins": { desires: { skills: ["Business", "Sales"], mental: ["Ambitious", "Confident"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: ["Painting", "Singing"], mental: ["Shy"], physical: ["Freckled"], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Baking", "Cooking", "Gardening"], mental: ["Kind", "Patient", "Creative"], physical: ["Soft", "Curvy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cruel", "Aggressive", "Arrogant"], physical: ["Ugly", "Scarred", "Athletic Build"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"], genitals: [] } }, "Pheiffer Coms": { desires: { skills: ["Medicine", "Investigation"], mental: ["Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Fishing"], mental: ["Stubborn"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Combat", "Driving", "First Aid", "Athletics"], mental: ["Brave", "Honest"], physical: ["Fit", "Strong", "Athletic Build", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Deceitful", "Cowardly", "Lazy"], physical: ["Weak", "Overweight", "Clumsy"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Fen Ris": { desires: { skills: ["Legal Knowledge", "Sexually Skilled"], mental: ["Calm", "Patient", "Honest"], physical: ["Curvy"], bodyParts: [], chestSize: ["giant"], buttSize: ["large", "huge", "giant"], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: ["huge"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Teaching", "Athletics", "Heavy Lifting", "Combat", "Yoga"], mental: ["Confident"], physical: ["Sharp Features", "Muscular", "Athletic Build", "Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: ["Calm", "Patient", "Honest"], physical: ["Were-Creature"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Deceitful", "Cowardly", "Cruel"], physical: ["Weak", "Ugly", "Blemished"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Selkira Onyxia": { desires: { skills: ["Public Speaking", "Social Media"], mental: ["Extroverted", "Patient", "Warm"], physical: ["Pale Skin"], bodyParts: [], chestSize: ["huge"], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Serving", "Acting", "Languages"], mental: ["Overthinker", "Impulsive", "Cold", "Jealous"], physical: ["Broad-shouldered"], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [], job: true }, reluctantToTrade: { skills: ["High Heels Proficient", "Sexually Skilled"], mental: ["Seductive", "Alluring"], physical: ["Silky Voice"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: ["Dominant"], physical: ["Curvy", "Flexible"], bodyParts: ["gender"], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive"], physical: ["Ugly", "Overweight", "Blemished", "Scarred"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Janis Besser": { desires: { skills: ["Modeling", "Sexually Skilled"], mental: ["Competitive", "Creative", "Intelligent"], physical: ["Voluptuous"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], genitals: [] }, willingToTrade: { skills: ["Gardening", "Painting"], mental: ["Shy", "Nurturing"], physical: ["Petite", "Soft", "Freckled", "Youthful"], bodyParts: [], chestSize: ["small"], buttSize: ["small"], genitals: [], job: true }, reluctantToTrade: { skills: ["Baking", "Cooking"], mental: ["Kind", "Patient", "Creative"], physical: ["Warm Tone", "Quick"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Muscular", "Tall", "Scarred", "Ugly"], bodyParts: [], chestSize: ["flat masculine", "giant"], buttSize: ["flat masculine", "giant"], genitals: [] } }, "Dennis Fungi": { desires: { skills: ["Music", "Performance", "Art"], mental: ["Creative", "Ambitious"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Yoga"], mental: ["Energetic"], physical: ["Flexible"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Dancing", "Teaching", "Athletics"], mental: ["Confident", "Outgoing", "Disciplined"], physical: ["Fit", "Athletic Build", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Clumsy", "Stiff"], physical: ["Overweight", "Weak", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["huge", "giant"], genitals: [] } }, "Yvela Mushroom": { desires: { skills: ["Performance", "Acting", "Music"], mental: ["Outgoing", "Creative"], physical: ["Attractive", "Flexible"], bodyParts: [], chestSize: ["small", "flat"], buttSize: ["small", "flat"], genitals: [] }, willingToTrade: { skills: ["Martial Arts"], mental: ["Competitive"], physical: [], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], genitals: [], job: true }, reluctantToTrade: { skills: ["Dancing", "Teaching", "Athletics", "Yoga"], mental: ["Confident", "Ambitious", "Disciplined"], physical: ["Fit", "Athletic Build", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Shy", "Submissive"], physical: ["Overweight", "Weak", "Clumsy", "Stiff", "Ugly"], bodyParts: [], chestSize: ["flat masculine"], buttSize: ["flat masculine"], genitals: [] } }, "Banana Banana": { desires: { skills: ["Customer Service", "Social Media"], mental: ["Creative", "Outgoing"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Music"], mental: ["Talkative"], physical: ["Youthful", "Quick"], bodyParts: [], chestSize: ["medium"], buttSize: ["medium"], genitals: [], job: true }, reluctantToTrade: { skills: ["Cooking", "Art"], mental: ["Friendly", "Optimistic", "Energetic", "Bubbly"], physical: ["Friendly Tone", "Fashionable"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cynical", "Rude", "Introverted"], physical: ["Ugly", "Mature", "Plain"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Xenis Aku": { desires: { skills: ["Navigation", "Mechanical Repair"], mental: ["Organized", "Patient"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: ["Introverted"], physical: ["Mature", "Relaxed"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Driving", "Customer Service", "First Aid"], mental: ["Calm", "Honest", "Reliable", "Thoughtful"], physical: ["Sturdy", "Calm Voice"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Unreliable", "Reckless", "Aggressive"], physical: ["Weak", "Clumsy", "Youthful"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Xanithar Galdenentri": { desires: { skills: ["Medicine", "Teaching"], mental: ["Wise", "Intelligent", "Analytical", "Calm", "Focused", "Disciplined"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: ["Magic Theory", "Persuasion", "Occult Expert", "Makeup", "Hair Styling", "High Heels Proficient", "Sexually Skilled", "Writing", "Languages", "Teaching", "Medicine"], mental: ["Crazy", "Trusting", "Fashionable", "Flirty", "Eccentric", "Intelligent", "Bookworm", "Lucky", "Sunfish", "Soul"], physical: ["Smooth Skin", "Underweight", "Mumbly Voice", "Freckled", "Scarred", "Mature"], bodyParts: ["age", "gender", "chest", "butt", "genitals", "skinTone", "hairColor", "hairLength"], chestSize: [], buttSize: [], genitals: [], name: true, job: false }, wontTradeFor: { skills: [], mental: ["Dull", "Foolish", "Simple"], physical: ["Muscular", "Attractive", "Youthful"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"], genitals: [] } }, "Trixie Rye": { desires: { skills: ["Management", "Business"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], genitals: [] }, willingToTrade: { skills: ["Dancing"], mental: ["Sly"], physical: ["Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], genitals: [], job: true }, reluctantToTrade: { skills: ["Serving", "High Heels Proficient", "Customer Service", "Persuasion"], mental: ["Confident", "Flirty", "Witty", "Outgoing"], physical: ["Attractive", "Voluptuous", "Graceful", "Charming Tone"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Honest"], physical: ["Ugly", "Plain", "Clumsy", "Stiff"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Butt Johnson": { desires: { skills: ["Gaming", "Coding", "Tech-Savvy", "Social Media", "Animation", "Video Editing"], mental: ["Focused", "Organized", "Confident", "Witty"], physical: ["Fit", "Attractive", "Lean", "Athletic Build"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Forklift Certified"], mental: ["Lazy", "Disorganized", "Forgetful", "Shy", "Awkward"], physical: ["Overweight", "Plain", "Blemished", "Unkempt"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Gaming", "Coding", "Tech-Savvy"], mental: ["Nerd", "Introverted", "Obsessive"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, neverTrade: { skills: ["Social Media"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: true }, wontTradeFor: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Revna McKraken": { desires: { /* She ONLY wants these specific traits for vanity and efficiency */ skills: ["High Heels Proficient", "Modeling", "Dancing", "Management", "Athletics", "Tech-Savvy", "Coding"], mental: ["Alluring", "Witty", "Efficient", "Quick Learner", "Shrewd"], physical: ["Smooth Skin", "Sharp Features", "Soft", "Flexible", "Fashionable"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { /* She's a vampire - she NEVER gives anything away */ skills: ["Sexually Skilled", "Stealth", "Persuasion", "Acting", "Languages", "Product Knowledge", "Martial Arts", "Gardening", "Writing", "Medicine", "Combat", "High Heels Proficient", "Modeling", "Dancing", "Management", "Athletics", "Tech-Savvy", "Coding", "Occult Expert"], mental: ["Charming", "Diplomatic", "Bookworm", "Seductive", "Intelligent", "Moody", "Sly", "Confident", "Creative", "Patient", "Perceptive", "Deceitful", "Goth", "Alluring", "Witty", "Efficient", "Quick Learner", "Shrewd"], physical: ["Pale Skin", "Attractive", "Graceful", "Voluptuous", "Quick Reflexes", "Smooth Skin", "Sharp Features", "Soft", "Flexible", "Fashionable", "Definitely not a Vampire"], voiceTraits: ["Silky Voice"], bodyParts: ["gender", "skinTone", "hairColor", "hairLength", "age", "genitals"], chestSize: ["medium"], buttSize: ["medium"], genitals: ["vagina"], name: true, job: true }, wontTradeFor: { /* She ONLY accepts what she desires - everything else is rejected */ /* All skills EXCEPT her desires */ skills: ["Sexually Skilled", "Stealth", "Persuasion", "Acting", "Languages", "Product Knowledge", "Martial Arts", "Gardening", "Writing", "Medicine", "Combat", "Occult Expert", "Math Skills", "Plumbing", "Swimmer", "Swimming", "Makeup", "Cooking", "Photography", "Maid", "Singing", "Serving", "Hair Styling", "Cleaning", "Trading", "Driving", "Lock Picking", "First Aid", "Construction", "Heavy Lifting", "Social Media", "Baking", "Public Speaking", "Art", "Painting", "Music", "Guitar", "Piano", "Teaching", "Sales", "Accounting", "Legal Knowledge", "Foreign Language", "Languages", "Yoga", "Retail", "Troubleshooting", "Forklift Certified", "Inventory Management", "Customer Service", "Were-Creature", "Sunfish", "Criminal Deluxe", "Oral Expert", "Anal Expert", "Rough Sex Enthusiast", "Sensual Lover", "BDSM Enthusiast - Dom", "BDSM Enthusiast - Sub", "Roleplay Expert", "Dirty Talker", "Exhibitionist", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master"], /* All mental traits EXCEPT her desires */ mental: ["Charming", "Diplomatic", "Bookworm", "Seductive", "Intelligent", "Moody", "Sly", "Confident", "Creative", "Patient", "Perceptive", "Deceitful", "Goth", "Swift", "Silver-Tongued", "Bimbo", "Pensive", "Jock", "Naturally Gifted", "Extroverted", "Introverted", "Bitchy", "Kind", "Honest", "Dominant", "Submissive", "Shy", "Aggressive", "Passive", "Optimistic", "Pessimistic", "Cruel", "Empathetic", "Stubborn", "Jealous", "Supportive", "Friendly", "Competitive", "Logical", "Lazy", "Hardworking", "Arrogant", "Humble", "Paranoid", "Trusting", "Ambitious", "Complacent", "Dull", "Brave", "Cowardly", "Mature", "Impatient", "Patient", "Wise", "Foolish", "Analytical", "Outgoing", "Curious", "Calm", "Energetic", "Thoughtful", "Chill", "Nonchalant", "Organized", "Resourceful", "Focused", "Disciplined", "Determined", "Steadfast", "Considerate", "Polite", "Funny", "Reassuring", "Loyal", "Talkative", "Direct", "Negotiator", "Crafty", "Workaholic", "High Stamina", "Flirty", "Warm", "Lucky", "Blunt", "Perfectionist", "Overthinker", "Unpredictable", "Risk Taker", "Impulsive", "Cynical", "Quiet", "Awkward", "Tone Deaf", "Tease", "Clingy", "Sensitive", "Corporate Drone", "Forgetful", "Disorganized", "Selfish", "Erratic", "Obsessive", "Insecure", "Short Tempered", "Rude", "Unreliable", "Slow Learner", "Reckless", "Cold", "Insensitive", "Unskilled", "Unlucky", "Nerd", "Geek", "Prep", "Tomboy", "Femboy", "Diva", "High Energy", "Deep Thinker", "Monotone Expression", "Sarcastic", "Artistic", "Relaxed", "Humorous", "Detail-Oriented", "Customer-Focused", "Punctual", "Naive", "Delinquent", "Musky", "Perverted", "Gambling Addiction"], /* All physical traits EXCEPT her desires */ physical: ["Pale Skin", "Attractive", "Graceful", "Voluptuous", "Quick Reflexes", "Definitely not a Vampire", "Tall", "Short", "Curvy", "Lean", "Muscular", "Pierced", "Youthful", "Mature", "Tan Skin", "Dark Skin", "Plain", "Ugly", "Fit", "Overweight", "Underweight", "Strong", "Clumsy", "Weak", "Stiff", "Freckled", "Blemished", "Tattooed", "Athletic Build", "Petite", "Broad-shouldered", "Quick", "Sturdy", "Scarred", "Short Hair", "Long Hair", "Fast", "Slow", "Were-Creature", "Sunfish"], /* All voice traits */ voiceTraits: ["Silky Voice", "Smooth Voice", "Soft-Spoken", "Warm Tone", "Gentle Voice", "Soothing Tone", "Clear Enunciation", "Articulate Speech", "Smooth Talker", "Friendly Tone", "Charismatic Voice", "Steady Voice", "Pleasant Cadence", "Calm Voice", "Expressive Voice", "Animated Tone", "Lively Tone", "Charming Tone", "Hushed Intimate Voice", "Balanced Neutral Tone", "Sing-Songy Voice", "Eager Tone", "Bouncy Tone", "Melodic Voice", "Clear Pronunciation", "Even-Paced Voice", "Understated Voice", "Soft Monologue Style", "Fast Talker", "Rapid-Fire Speech", "Deep Voice", "High-Pitched Tone", "Raspy Voice", "Gravelly Voice", "Croaky Voice", "Breathy Voice", "Nasally Tone", "Stoic Tone", "Measured Speech", "Choppy Speech", "Interruptive Tone", "Sharp Voice", "Snappy Tone", "Flat Voice", "Monotone", "Deadpan Delivery", "Detached Voice", "Emotionless Tone", "Slow Calm Voice", "Lazy Drawl", "Mumbly Voice", "Stuttering Speech", "Grim Tone", "Robotic Tone", "Flat Uninterested Voice", "Whiny Voice", "Slurred Speech", "Shaky Voice", "Gaelic Accent"], /* All body parts */ bodyParts: ["gender", "skinTone", "hairColor", "hairLength", "age", "genitals", "chest", "butt"], /* All chest sizes */ chestSize: ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"], /* All butt sizes */ buttSize: ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"], /* All genital types */ genitals: ["small penis", "penis", "big penis", "tight vagina", "vagina", "loose vagina"] } }, "Purple Wood": { desires: { skills: ["Languages", "Coding", "Math Skills"], mental: ["Intelligent", "Analytical", "Logical", "Wise"], physical: [], bodyParts: [], chestSize: ["medium", "large"], buttSize: ["huge", "giant"], genitals: [] }, willingToTrade: { skills: [], mental: ["Bimbo", "Moody"], physical: ["Pierced"], bodyParts: [], chestSize: ["small"], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["Art", "Music", "Painting", "Writing"], mental: ["Creative", "Introverted", "Goth"], physical: ["Attractive", "Tattooed", "Graceful"], bodyParts: [], chestSize: [], buttSize: ["huge"], genitals: [] }, neverTrade: { skills: [], mental: [], physical: ["Pale Skin"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Cruel", "Optimistic", "Prep"], physical: ["Plain", "Fashionable", "Muscular"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Luna Snow": { desires: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: ["Art", "Music", "Guitar"], mental: ["Stubborn", "Artistic", "Wise", "Intelligent", "Lucky", "Bookworm", "Creative", "Calm", "Funny", "Charming", "Charismatic Voice", "Warm"], physical: ["Short", "Attractive", "Youthful", "Curvy", "Fit"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: true, job: true }, wontTradeFor: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Luna Snow": { desires: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: ["Art", "Music", "Guitar"], mental: ["Stubborn", "Artistic", "Wise", "Intelligent", "Lucky", "Bookworm", "Creative", "Calm", "Funny", "Charming", "Charismatic Voice", "Warm"], physical: ["Short", "Attractive", "Youthful", "Curvy", "Fit"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: true, job: true }, wontTradeFor: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Boris Shorthead": { desires: { skills: ["Heavy Lifting", "Construction", "Athletics"], mental: ["Stubborn", "Aggressive", "Dominant"], physical: ["Tall", "Muscular", "Strong"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Public Speaking", "First Aid"], mental: ["Blunt", "Loyal"], physical: ["Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Combat", "Driving"], mental: ["Disciplined", "Brave"], physical: ["Muscular", "Strong"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: ["Short"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Submissive", "Cowardly"], physical: ["Weak", "Clumsy", "Petite"], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"], genitals: [] } }, "Mareregererrer Mayonnaise": { desires: { skills: ["Management", "Legal Knowledge", "Persuasion"], mental: ["Ambitious", "Shrewd", "Diplomatic"], physical: ["Attractive", "Fashionable"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["First Aid", "Persuasion"], mental: ["Direct", "Analytical"], physical: ["Sharp Features"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Combat", "Driving"], mental: ["Confident", "Determined"], physical: ["Athletic Build", "Fit"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Foolish", "Reckless"], physical: ["Ugly", "Weak", "Overweight"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Poggies Name420": { desires: { skills: ["Modeling", "Makeup", "Dancing", "Sexually Skilled"], mental: ["Seductive", "Flirty", "Alluring", "Charming"], physical: ["Attractive", "Curvy", "Voluptuous", "Fashionable"], bodyParts: [], chestSize: ["medium", "large", "huge"], buttSize: ["huge", "giant", "gigantic"], genitals: [] }, willingToTrade: { skills: ["High Heels Proficient", "Dancing"], mental: ["Energetic", "Flirty"], physical: ["Graceful", "Smooth Skin"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Combat", "Driving"], mental: ["Confident", "Unpredictable"], physical: ["Petite"], bodyParts: [], chestSize: [], buttSize: ["giant"], genitals: [] }, neverTrade: { skills: [], mental: ["Femboy"], physical: ["Long Hair", "Femboy"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: true }, wontTradeFor: { skills: [], mental: ["Boring", "Dull", "Cold"], physical: ["Ugly", "Muscular", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: ["flat", "small"], genitals: [] } }, "Sunny Flipflop": { desires: { skills: ["Medicine", "Stealth", "Persuasion"], mental: ["Shrewd", "Analytical", "Diplomatic"], physical: ["Intimidating", "Scarred"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Driving", "First Aid"], mental: ["Ambitious"], physical: ["Athletic Build"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Combat", "Legal Knowledge", "Management", "Public Speaking", "Persuasion"], mental: ["Confident", "Disciplined", "Brave", "Honest", "Loyal"], physical: ["Muscular", "Strong", "Fit", "Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: ["big penis"] }, neverTrade: { skills: [], mental: ["Hardworking", "Organized"], physical: ["Dark Skin"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: true }, wontTradeFor: { skills: [], mental: ["Deceitful", "Cowardly", "Lazy", "Corrupt"], physical: ["Weak", "Clumsy", "Overweight"], bodyParts: [], chestSize: ["giant"], buttSize: [], genitals: [] } }, "Bongo Bongo": { desires: { skills: ["Management", "Sales", "Martial Arts"], mental: ["Confident", "Ambitious", "Witty"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["large", "huge"], genitals: [] }, willingToTrade: { skills: ["Product Knowledge", "Inventory Management"], mental: ["Patient", "Polite"], physical: ["Sharp Features"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: ["Customer Service", "Combat", "First Aid"], mental: ["Friendly", "Brave", "Disciplined", "Organized"], physical: ["Fit", "Quick Reflexes"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: [], mental: [], physical: ["Pale Skin", "Long Hair"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Rude", "Disorganized", "Lazy"], physical: ["Ugly", "Clumsy", "Blemished"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Cid Cranberry": { desires: { skills: ["Sexually Skilled", "Stealth", "Lock Picking"], mental: ["Lucky", "Curious", "Romantic"], physical: ["Flexible", "Strong", "Short"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: ["Navigation", "Acting"], mental: ["Blunt", "Arrogant", "Honest", "Bad Luck"], physical: ["Clumsy", "Fit"], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: true }, reluctantToTrade: { skills: ["High Stamina", "Combat", "Art"], mental: ["Brave"], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: ["Roleplay Expert", "Maid"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], name: false, job: false }, wontTradeFor: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] } }, "Roisin Sullivan": { desires: { skills: ["BDSM Enthusiast - Dom", "Occult Expert", "Persuasion"], mental: ["Analytical", "Chill", "Considerate", "Creative", "Friendly", "Funny", "Hardworking", "High Stamina", "Humorous", "Mature", "Perverted", "Sarcastic", "Seductive", "Were-Creature"], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: ["Cold", "Disorganized", "Forgetful", "Impatient", "Insecure", "Reckless", "Sensitive", "Stubborn"], physical: [], bodyParts: [], chestSize: ["gigantic"], buttSize: ["gigantic"], genitals: [], job: false }, reluctantToTrade: { skills: ["Forklift Certified"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, neverTrade: { skills: ["Athletics", "Baking", "Combat", "Driving", "Gardening", "Heavy Lifting", "Swimmer"], mental: ["Alluring", "Ambitious", "Blunt", "Competitive", "Confident", "Delinquent", "Determined", "Dominant", "Efficient", "Extroverted", "Lucky", "Risk Taker", "Steadfast"], physical: ["Athletic Build", "Attractive", "Fast", "Fit", "Flexible", "Long Hair", "Perceptive", "Quick Reflexes", "Relaxed", "Smooth Skin", "Strong", "Sturdy", "Tall", "Youthful"], bodyParts: ["chest", "butt", "genitals"], chestSize: ["huge"], buttSize: ["large"], genitals: ["tight vagina"], voiceTraits: ["Gaelic Accent"], name: true, job: true }, wontTradeFor: { skills: ["Anal Expert", "BDSM Enthusiast - Sub", "Dancing", "High Heels Proficient", "Maid", "Oral Expert", "Social Media"], mental: ["Awkward", "Bimbo", "Bookworm", "Corrupt", "Cynical", "Flirty", "Introverted", "Kind", "Loyal", "Musky", "Negotiator", "Nonchalant", "Paranoid", "Quiet", "Shy", "Sunfish", "Tease", "Tone Deaf", "Unlucky", "Bad Luck", "Unpredictable", "Unskilled"], physical: ["Blemished", "Clumsy", "Definitely not a Vampire", "Monotone Expression", "Overweight", "Petite", "Plain", "Short", "Slow", "Soft", "Stiff", "Ugly", "Underweight", "Voluptuous", "Weak"], bodyParts: [], chestSize: ["gigantic", "giant", "large chest", "average chest", "small chest", "flat chest", "flat masculine", "masculine chest"], buttSize: ["gigantic", "giant", "large butt", "average butt", "small butt", "flat butt", "flat masculine", "masculine butt"], genitals: [] } } }>> <!-- QUESHA_JOB_LOCK_START --> <<set setup.npcTradingPreferences["Quesha Epo"] = { neverTrade: { name: true, job: true, bodyParts: [], physical: [], mental: [], skills: [] }, desires: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, refuseToTrade: [] }>> <!-- QUESHA_JOB_LOCK_END --> <!-- CLAIR_TRADE_LOCK_START --> <<set setup.npcTradingPreferences["Clair"] = { neverTrade: { name: true, job: true, bodyParts: [], physical: [], mental: [], skills: [] }, desires: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], genitals: [] }, refuseToTrade: [] }>> <!-- CLAIR_TRADE_LOCK_END --> /* ================================== */ /* === NPC TRADING PREFERENCE FUNCTIONS === */ /* ================================== */ /* Function to check if NPC has trading preferences defined */ <<set setup.getNPCPreferences = function(npcNameOrObject) { /* If passed an NPC object, use their permanent ID */ if (typeof npcNameOrObject === 'object' && npcNameOrObject.permanentId) { return setup.npcTradingPreferences[npcNameOrObject.permanentId] || null; } /* Otherwise treat as name string */ return setup.npcTradingPreferences[npcNameOrObject] || null; }>> /* Function to calculate preference-based trade chance modifier */ <<set setup.calculatePreferenceModifier = function(npc, playerPackage, npcPackage) { var preferences = setup.getNPCPreferences(npc); if (!preferences) return 0; var modifier = 0; /* Check what player is OFFERING that NPC desires */ if (preferences.desires) { if (playerPackage.skills && preferences.desires.skills) { playerPackage.skills.forEach(function(skill) { if (preferences.desires.skills.includes(skill)) { modifier += 30; } }); } if (playerPackage.mental && preferences.desires.mental) { playerPackage.mental.forEach(function(trait) { if (preferences.desires.mental.includes(trait)) { modifier += 15; } }); } if (playerPackage.physical && preferences.desires.physical) { playerPackage.physical.forEach(function(trait) { if (preferences.desires.physical.includes(trait)) { modifier += 15; } }); } if (playerPackage.bodyParts && preferences.desires.bodyParts) { playerPackage.bodyParts.forEach(function(part) { if (preferences.desires.bodyParts.includes(part.name)) { modifier += 20; } }); } } /* Check what player is REQUESTING that NPC is reluctant to trade */ if (preferences.reluctantToTrade) { if (npcPackage.skills && preferences.reluctantToTrade.skills) { npcPackage.skills.forEach(function(skill) { if (preferences.reluctantToTrade.skills.includes(skill)) { modifier -= 20; } }); } if (npcPackage.mental && preferences.reluctantToTrade.mental) { npcPackage.mental.forEach(function(trait) { if (preferences.reluctantToTrade.mental.includes(trait)) { modifier -= 15; } }); } if (npcPackage.physical && preferences.reluctantToTrade.physical) { npcPackage.physical.forEach(function(trait) { if (preferences.reluctantToTrade.physical.includes(trait)) { modifier -= 50; } }); } if (npcPackage.bodyParts && preferences.reluctantToTrade.bodyParts) { npcPackage.bodyParts.forEach(function(part) { if (preferences.reluctantToTrade.bodyParts.includes(part.name)) { modifier -= 25; } }); } } /* Entrancement: reluctance melts for the entranced NPC today */ if (setup.witchSpells && npc && setup.witchSpells.sandmanActiveFor(npc.name) && modifier < 0) { modifier = 0; } return modifier; }>> /* Function to check if trade is blocked by NPC's "never trade" or "wont trade for" rules */ <<set setup.isTradeBlocked = function(npc, playerPackage, npcPackage) { /* Flona Vulri cannot be bartered with at all: traits stay visible but the trade button is grayed out and no trade of any kind can complete. */ if (npc && npc.name === "Flona Vulri") return true; /* Clair trades nothing, ever: a dream entity has nothing detachable to give. */ if (npc && (npc.name === "Clair" || npc.originalName === "Clair")) return true; /* Clair FORM: while wearing Clair's shape the player cannot trade at all. */ if (State.variables.clairFormActive) return true; var preferences = setup.getNPCPreferences(npc); if (!preferences) return false; /* Check "never trade" - things NPC won't give away (only check npcPackage - what NPC actually has and is offering) */ if (preferences.neverTrade) { var neverTrade = preferences.neverTrade; /* Check if player is requesting NPC's name */ if (neverTrade.name && npcPackage.name && npcPackage.name.length > 0) { return true; } /* Check if player is requesting NPC's job */ if (neverTrade.job && npcPackage.job !== null && npcPackage.job !== undefined) { return true; } /* ONLY block if the NPC is actually offering these items (they're in npcPackage) */ if (npcPackage.skills && neverTrade.skills) { for (var i = 0; i < npcPackage.skills.length; i++) { if (neverTrade.skills.includes(npcPackage.skills[i])) { return true; } } } if (npcPackage.mental && neverTrade.mental) { for (var i = 0; i < npcPackage.mental.length; i++) { if (neverTrade.mental.includes(npcPackage.mental[i])) { return true; } } } if (npcPackage.physical && neverTrade.physical) { for (var i = 0; i < npcPackage.physical.length; i++) { if (neverTrade.physical.includes(npcPackage.physical[i])) { return true; } } } if (npcPackage.bodyParts && neverTrade.bodyParts) { for (var i = 0; i < npcPackage.bodyParts.length; i++) { if (neverTrade.bodyParts.includes(npcPackage.bodyParts[i].name)) { return true; } } } /* Check chest sizes in NPC package */ if (npcPackage.bodyParts && neverTrade.chestSize) { for (var i = 0; i < npcPackage.bodyParts.length; i++) { if (npcPackage.bodyParts[i].name === "chest") { var npcChestSize = npc.bodyParts.chest; if (neverTrade.chestSize.includes(npcChestSize)) { return true; } } } } /* Check butt sizes in NPC package */ if (npcPackage.bodyParts && neverTrade.buttSize) { for (var i = 0; i < npcPackage.bodyParts.length; i++) { if (npcPackage.bodyParts[i].name === "butt") { var npcButtSize = npc.bodyParts.butt; if (neverTrade.buttSize.includes(npcButtSize)) { return true; } } } } /* Check genitals in NPC package */ if (npcPackage.bodyParts && neverTrade.genitals) { for (var i = 0; i < npcPackage.bodyParts.length; i++) { if (npcPackage.bodyParts[i].name === "genitals") { var npcGenitals = npc.bodyParts.genitals; if (neverTrade.genitals.includes(npcGenitals)) { return true; } } } } } /* Check "wont trade for" - things NPC won't accept from player (only check playerPackage) */ if (preferences.wontTradeFor) { var wontTradeFor = preferences.wontTradeFor; if (playerPackage.skills && wontTradeFor.skills) { for (var i = 0; i < playerPackage.skills.length; i++) { if (wontTradeFor.skills.includes(playerPackage.skills[i])) { return true; } } } if (playerPackage.mental && wontTradeFor.mental) { for (var i = 0; i < playerPackage.mental.length; i++) { if (wontTradeFor.mental.includes(playerPackage.mental[i])) { return true; } } } if (playerPackage.physical && wontTradeFor.physical) { for (var i = 0; i < playerPackage.physical.length; i++) { if (wontTradeFor.physical.includes(playerPackage.physical[i])) { return true; } } } if (playerPackage.bodyParts && wontTradeFor.bodyParts) { for (var i = 0; i < playerPackage.bodyParts.length; i++) { if (wontTradeFor.bodyParts.includes(playerPackage.bodyParts[i].name)) { return true; } } } /* Check chest sizes in player package */ if (playerPackage.bodyParts && wontTradeFor.chestSize) { for (var i = 0; i < playerPackage.bodyParts.length; i++) { if (playerPackage.bodyParts[i].name === "chest") { var v = State.variables; var playerChestSize = v.bodyParts.chest; if (wontTradeFor.chestSize.includes(playerChestSize)) { return true; } } } } /* Check butt sizes in player package */ if (playerPackage.bodyParts && wontTradeFor.buttSize) { for (var i = 0; i < playerPackage.bodyParts.length; i++) { if (playerPackage.bodyParts[i].name === "butt") { var v = State.variables; var playerButtSize = v.bodyParts.butt; if (wontTradeFor.buttSize.includes(playerButtSize)) { return true; } } } } /* Check genitals in player package */ if (playerPackage.bodyParts && wontTradeFor.genitals) { for (var i = 0; i < playerPackage.bodyParts.length; i++) { if (playerPackage.bodyParts[i].name === "genitals") { var v = State.variables; var playerGenitals = v.bodyParts.genitals; if (wontTradeFor.genitals.includes(playerGenitals)) { return true; } } } } } return false; }>> <<set setup.flona = setup.flona || {}>> <<set setup.flona.TRANSFORMATION_TRAITS = ["Werecat","Werewolf","Werebunny","Werefox","Weresheep","Cerberus","Succubus","Imp","Hucow","Kitsune","Youko","Trophy Wife","Gym Bunny","E-Girl","Punk","Gyaru","Siren","Living Doll","Dominatrix","Slut","Himbo","Angel","Naiad","Automaton","Banshee","Cheshire Cat","Cupid","Dark Angel","Honeybee","Jinko","Kakuen","Lizardman","Ocelomeh","Pyrow","Raiju","Salamander","Satyros","Vampire","Anubis","Pharaoh","Witch","Oni","Half-Dragon Gyaru"]>> <<set setup.flona.playerHasAnyTransformation = function() { var V = State.variables; var list = setup.flona.TRANSFORMATION_TRAITS; var phys = V.physicalTraits || []; var ment = V.mentalTraits || []; for (var i = 0; i < list.length; i++) { if (phys.indexOf(list[i]) !== -1) return true; if (ment.indexOf(list[i]) !== -1) return true; } return false; }>> <<set setup.flona.playerIsTrueSelf = function() { var V = State.variables; /* possession, lifeswap, and witch-absorbed are all covered here. */ /* If setup.oni is not yet initialised, skip the body check (treat as own body). */ if (typeof setup.oni === "object" && typeof setup.oni.isPlayerInOwnBody === "function" && !setup.oni.isPlayerInOwnBody()) return false; if (V.witchFormActive === true) return false; if (setup.flona.playerHasAnyTransformation()) return false; return true; }>> <<set setup.flona.homeLocation = function() { return State.variables.discoveredFlonaTent ? "FlonaTent" : "TundraOfAeternus"; }>> <<set setup.flona.isPresentAt = function(passageName) { if (!setup.flona.playerIsTrueSelf()) return false; return passageName === setup.flona.homeLocation(); }>> /* Function to calculate preference-based value adjustment */ <<set setup.calculatePreferenceValueAdjustment = function(npc, playerPackage, npcPackage, baseValue) { var preferences = setup.getNPCPreferences(npc); if (!preferences) return baseValue; var multiplier = 1.0; /* Items player is offering that NPC desires = reduce required payment */ if (preferences.desires) { if (playerPackage.skills && preferences.desires.skills) { playerPackage.skills.forEach(function(skill) { if (preferences.desires.skills.includes(skill)) { multiplier *= 0.85; /* 15% discount per desired item */ } }); } if (playerPackage.mental && preferences.desires.mental) { playerPackage.mental.forEach(function(trait) { if (preferences.desires.mental.includes(trait)) { multiplier *= 0.85; } }); } if (playerPackage.physical && preferences.desires.physical) { playerPackage.physical.forEach(function(trait) { if (preferences.desires.physical.includes(trait)) { multiplier *= 0.85; } }); } } /* Items NPC is reluctant to trade = increase required payment. Entrancement waives this premium for the entranced NPC today. */ var sandmanEntranced = !!(setup.witchSpells && npc && setup.witchSpells.sandmanActiveFor(npc.name)); if (preferences.reluctantToTrade && !sandmanEntranced) { if (npcPackage.skills && preferences.reluctantToTrade.skills) { npcPackage.skills.forEach(function(skill) { if (preferences.reluctantToTrade.skills.includes(skill)) { multiplier *= 1.3; /* 30% premium for reluctant items */ } }); } if (npcPackage.mental && preferences.reluctantToTrade.mental) { npcPackage.mental.forEach(function(trait) { if (preferences.reluctantToTrade.mental.includes(trait)) { multiplier *= 1.3; } }); } if (npcPackage.physical && preferences.reluctantToTrade.physical) { npcPackage.physical.forEach(function(trait) { if (preferences.reluctantToTrade.physical.includes(trait)) { multiplier *= 1.3; } }); } } return Math.round(baseValue * multiplier); }>>
/* ---------------------------------- */ /* --- TRADE EXECUTION FUNCTION --- */ /* ---------------------------------- */ /* Helper function to check and assign gender-mismatch traits */ <<set setup.updateGenderMismatchTraits = function(character) { /* If no character passed, assume player */ if (!character) { character = State.variables; } var gender = character.bodyParts.gender; var genitals = character.bodyParts.genitals; var traits = character.physicalTraits; /* Remove both special traits first */ traits.delete("Cuntboy"); traits.delete("Dickgirl"); /* Check for mismatch and add appropriate trait */ if (gender === "male" && (genitals === "tight vagina" || genitals === "vagina" || genitals === "loose vagina")) { if (!traits.includes("Cuntboy")) { traits.push("Cuntboy"); } } else if (gender === "female" && (genitals === "small penis" || genitals === "penis" || genitals === "big penis")) { if (!traits.includes("Dickgirl")) { traits.push("Dickgirl"); } } }>> <<set setup.attemptTrade = function(npc, playerPackage, npcPackage) { var v = State.variables; /* Cerberus can never be traded away to an NPC (it is still storable in Trait Storage, which is a separate code path). Strip it defensively in case a malformed package slips past the trade-UI filters. */ if (playerPackage && playerPackage.physical) { while (playerPackage.physical.indexOf("Cerberus") !== -1) { playerPackage.physical.splice(playerPackage.physical.indexOf("Cerberus"), 1); } } /* Calculate trade chance with relationship and preference adjustments */ var playerValue = setup.calculateTradeValue(playerPackage, true); var npcValue = setup.calculateTradeValue(npcPackage, false); /* Apply preference-based adjustments FIRST (willing/reluctant/desires) */ var adjustedNpcValue = setup.calculatePreferenceValueAdjustment(npc, playerPackage, npcPackage, npcValue); /* THEN apply relationship-based threshold reduction */ var relLevel = (v.relationships[npc.name]) ? v.relationships[npc.name].level : 1; if (relLevel === 2) { adjustedNpcValue = Math.floor(adjustedNpcValue * 0.95); /* 5% discount */ } else if (relLevel === 3) { adjustedNpcValue = Math.floor(adjustedNpcValue * 0.90); /* 10% discount */ } else if (relLevel === 4) { adjustedNpcValue = Math.floor(adjustedNpcValue * 0.85); /* 15% discount */ } else if (relLevel >= 5) { adjustedNpcValue = Math.floor(adjustedNpcValue * 0.80); /* 20% discount (cap) */ } /* ===== SKILL TREE: Apply Trade Value Reduction ===== */ var skillTreeReduction = setup.skillTree.getEffect("tradeValueReduction"); if (skillTreeReduction > 0) { adjustedNpcValue = Math.max(0, adjustedNpcValue - skillTreeReduction); } /* Calculate chance with adjusted value */ var tradeChance = setup.calculateTradeChance(playerValue, adjustedNpcValue, npc, playerPackage, npcPackage); /* Roll for success */ var roll = Math.random() * 100; var success = roll <= tradeChance; /* Initialize result object */ var result = { success: success, playerGave: { name: [], physical: [], mental: [], skills: [], bodyParts: [], job: null }, playerReceived: { name: [], physical: [], mental: [], skills: [], bodyParts: [], job: null }, npcGave: { physical: [], mental: [], skills: [], bodyParts: [], job: null }, npcReceived: { physical: [], mental: [], skills: [], bodyParts: [], job: null } }; if (success) { /* Find the NPC in the main array */ var npcIndex = -1; for (var i = 0; i < v.npcs.length; i++) { if (v.npcs[i].name === npc.name) { npcIndex = i; break; } } if (npcIndex === -1) { return result; } /* Work directly with the NPC in the array */ var targetNPC = v.npcs[npcIndex]; /* Check if we're trading with Roisin (do this early) */ var isRoisin = (targetNPC.name === "Roisin Sullivan" || targetNPC.name.includes("Roisin")); /* RECORD WHAT PLAYER IS GIVING (before any swaps) */ if (playerPackage.name && playerPackage.name.length > 0) { playerPackage.name.forEach(function(nameItem) { result.playerGave.name.push({type: nameItem.type, value: nameItem.value}); }); } if (playerPackage.physical) { playerPackage.physical.forEach(function(trait) { result.playerGave.physical.push(trait); }); } if (playerPackage.mental) { playerPackage.mental.forEach(function(trait) { result.playerGave.mental.push(trait); }); } if (playerPackage.skills) { playerPackage.skills.forEach(function(skill) { result.playerGave.skills.push(skill); }); } if (playerPackage.bodyParts) { playerPackage.bodyParts.forEach(function(part) { var partValue = part.name === "chest" ? v.bodyParts.chest : part.name === "butt" ? v.bodyParts.butt : part.name === "gender" ? v.bodyParts.gender : part.name === "genitals" ? v.bodyParts.genitals : part.name === "skinTone" ? v.appearance.skinTone : part.name === "hairColor" ? v.appearance.hairColor : part.name === "hairLength" ? v.appearance.hairLength : part.name === "age" ? v.appearance.age : ""; result.playerGave.bodyParts.push({name: part.name, value: partValue}); }); } if (playerPackage.job !== null && playerPackage.job !== undefined) { var playerOldJob = v.jobs && v.jobs.length > 0 ? v.jobs[0] : "Unemployed"; result.playerGave.job = playerOldJob; } /* RECORD WHAT PLAYER IS RECEIVING (before any swaps) */ if (npcPackage.name && npcPackage.name.length > 0) { npcPackage.name.forEach(function(nameItem) { result.playerReceived.name.push({type: nameItem.type, value: nameItem.value}); }); } if (npcPackage.physical) { npcPackage.physical.forEach(function(trait) { result.playerReceived.physical.push(trait); }); } if (npcPackage.mental) { npcPackage.mental.forEach(function(trait) { result.playerReceived.mental.push(trait); }); } if (npcPackage.skills) { npcPackage.skills.forEach(function(skill) { result.playerReceived.skills.push(skill); }); } if (npcPackage.bodyParts) { npcPackage.bodyParts.forEach(function(part) { var npcOriginalValue = part.name === "chest" ? targetNPC.bodyParts.chest : part.name === "butt" ? targetNPC.bodyParts.butt : part.name === "gender" ? targetNPC.bodyParts.gender : part.name === "genitals" ? targetNPC.bodyParts.genitals : part.name === "skinTone" ? targetNPC.appearance.skinTone : part.name === "hairColor" ? targetNPC.appearance.hairColor : part.name === "hairLength" ? targetNPC.appearance.hairLength : part.name === "age" ? targetNPC.appearance.age : ""; result.playerReceived.bodyParts.push({name: part.name, value: npcOriginalValue}); }); } if (playerPackage.job !== null && playerPackage.job !== undefined) { var npcOldJob = targetNPC.jobs && targetNPC.jobs.length > 0 ? targetNPC.jobs[0] : "Unemployed"; result.playerReceived.job = npcOldJob; } /* NOW PERFORM THE ACTUAL SWAPS */ /* Names */ /* Defense in depth: possession blocks the name UI in isItemBlocked, but guard the actual swap too so any stale package contents are still ignored while the player is wearing the cuff. */ if (playerPackage.name && playerPackage.name.length > 0 && !v.possessionActive) { /* Store the old name for schedule update */ var oldNPCName = targetNPC.name; /* Extract NPC name parts at the start */ var npcNameParts = targetNPC.name.split(" "); var npcFirst = npcNameParts[0] || ""; var npcLast = npcNameParts.slice(1).join(" ") || ""; /* Perform swaps */ playerPackage.name.forEach(function(nameItem) { if (nameItem.type === "firstName") { var headKey = nameItem.head || "center"; var tempFirst = setup.getCerberusHeadName(headKey); setup.setCerberusHeadName(headKey, npcFirst); npcFirst = tempFirst; } else if (nameItem.type === "lastName") { var tempLast = v.lastName; v.lastName = npcLast; npcLast = tempLast; } }); /* Rebuild NPC name with both parts */ var newNPCName; if (npcLast && npcLast.trim() !== "") { newNPCName = npcFirst + " " + npcLast; } else { newNPCName = npcFirst; } /* Update the NPC's name in the array EXPLICITLY */ targetNPC.name = newNPCName; v.npcs[npcIndex].name = newNPCName; /* CRITICAL: Update the location schedule key with the new name */ if (v.npcLocationSchedules && v.npcLocationSchedules[oldNPCName]) { v.npcLocationSchedules[newNPCName] = v.npcLocationSchedules[oldNPCName]; delete v.npcLocationSchedules[oldNPCName]; } /* CRITICAL: Update old schedule system if it exists */ if (v.npcSchedules && v.npcSchedules[oldNPCName]) { v.npcSchedules[newNPCName] = v.npcSchedules[oldNPCName]; delete v.npcSchedules[oldNPCName]; } /* CRITICAL: Update the relationship key with the new name using helper function */ setup.updateNPCRelationshipKey(oldNPCName, newNPCName); /* CRITICAL: Update metNPCs array - remove ALL instances of old name, add new name once */ v.metNPCs = v.metNPCs.filter(function(name) { return name !== oldNPCName; }); if (!v.metNPCs.includes(newNPCName)) { v.metNPCs.push(newNPCName); } /* CRITICAL: Update $tradingWithNPC reference */ v.tradingWithNPC = v.npcs[npcIndex]; } /* Physical traits - player gives to NPC */ if (playerPackage.physical) { playerPackage.physical.forEach(function(trait) { /* Witch form: cannot trade away Witch trait */ if (v.witchFormActive && trait === "Witch") return; /* Check if this is a transformation trait being traded away */ if (setup.isTransformationTrait && setup.isTransformationTrait(trait)) { /* Revert the transformation (removes granted traits, clears activeTransformation) */ setup.revertFullTransformation(trait); } v.physicalTraits.delete(trait); /* Handle Futanari trait trade - only auto-swap genitals if genitals are NOT also being traded */ if (trait === "Futanari") { var alsoTradingGenitals = playerPackage.bodyParts && playerPackage.bodyParts.some(function(p) { return p.name === "genitals"; }); if (!alsoTradingGenitals) { var partnerGenitals = targetNPC.bodyParts.genitals || "vagina"; v.bodyParts.genitals = partnerGenitals; targetNPC.bodyParts.genitals = "both"; if (setup.updateGenderMismatchTraits) { setup.updateGenderMismatchTraits(v); setup.updateGenderMismatchTraits(targetNPC); } } } /* Check for conflicts with NPC's existing traits */ var conflict = setup.getConflictingTrait(trait, targetNPC.physicalTraits); if (conflict) { targetNPC.physicalTraits.delete(conflict); /* Track what NPC lost due to conflict */ result.npcGave.physical.push(conflict); } if (!targetNPC.physicalTraits.includes(trait)) { targetNPC.physicalTraits.push(trait); /* Track what NPC received */ result.npcReceived.physical.push(trait); /* If a transformation trait was just given to the NPC, fully transform them — body parts, gender, hair, and granted traits — so the NPC matches the TF instead of just having the trait as a label. Static/fixture NPCs are protected by setup.isNPCTransformable. */ if (setup.isTransformationTrait && setup.isTransformationTrait(trait) && typeof setup.applyTransformationToNPC === "function") { setup.applyTransformationToNPC(targetNPC, trait); } /* Auto-adjust body parts if it's a body type trait (skip for TF traits — applyTransformationToNPC already set body parts per the TF recipe). */ else if (setup.bodyTypeRequirements[trait]) { setup.adjustBodyPartsForTrait(trait, false, targetNPC); } } }); } /* Track deferred Bimbo activation: when the player gives the Bimbo trait to the NPC, the gigantic-body override must NOT be applied until AFTER the body-parts swap below. Otherwise the swap copies the NPC's gigantic bimbo chest/butt onto the player. */ var npcGainsBimbo = false; /* Mental traits - player gives to NPC */ if (playerPackage.mental) { playerPackage.mental.forEach(function(trait) { /* Special handling for Bimbo trait - deactivate for player */ if (trait === "Bimbo") { setup.deactivateBimboTrait(v); } /* Check if it's the character creation trait */ if (trait === v.characterCreationTrait) { v.characterCreationTrait = null; } else { v.mentalTraits.delete(trait); } /* Check for conflicts with NPC's existing traits */ var conflict = setup.getConflictingTrait(trait, targetNPC.mentalTraits); if (conflict) { targetNPC.mentalTraits.delete(conflict); /* Track what NPC lost due to conflict */ result.npcGave.mental.push(conflict); } if (!targetNPC.mentalTraits.includes(trait)) { targetNPC.mentalTraits.push(trait); /* Track what NPC received */ result.npcReceived.mental.push(trait); /* Special handling for Bimbo trait - defer activation until AFTER the body-parts swap (see npcGainsBimbo). Applying the gigantic override here would leak it into the swap and give the player gigantic chest/butt. */ if (trait === "Bimbo") { npcGainsBimbo = true; } } }); } /* Skills - player gives to NPC */ if (playerPackage.skills) { playerPackage.skills.forEach(function(skill) { v.skills.delete(skill); if (!targetNPC.skills.includes(skill)) { targetNPC.skills.push(skill); /* Track what NPC received */ result.npcReceived.skills.push(skill); } }); } /* If the NPC is giving the Bimbo trait AWAY in this trade, deactivate its bimbo overlay BEFORE the body-parts swap so the player receives the NPC's real pre-bimbo chest/butt instead of the gigantic override. (Mirror of the player-side deactivation above. Idempotent with the later deactivate call in the npc-gives-mental block.) */ if (npcPackage.mental && npcPackage.mental.indexOf("Bimbo") !== -1) { setup.deactivateBimboTrait(targetNPC); } /* Body parts swap */ if (playerPackage.bodyParts) { playerPackage.bodyParts.forEach(function(part) { if (part.name === "chest" || part.name === "butt" || part.name === "gender" || part.name === "genitals") { /* Block gender swap to male for all TFs except Himbo */ if (part.name === "gender" && targetNPC.bodyParts.gender === "male" && setup.isMaleGenderBlocked()) return; /* Witch form: cannot swap gender or genitals */ if (v.witchFormActive && (part.name === "gender" || part.name === "genitals")) return; /* Voluptuous Succubus: cannot swap chest or butt */ if (v.physicalTraits && v.physicalTraits.indexOf("Voluptuous Succubus") !== -1 && (part.name === "chest" || part.name === "butt")) return; /* Block genital swap to male genitals for blocked transformations */ var npcGen = targetNPC.bodyParts[part.name] || ""; if (part.name === "genitals" && (npcGen === "penis" || npcGen === "big penis" || npcGen === "small penis") && setup.isFutanariBlocked()) return; /* Track old and new values for transformation descriptions */ var npcOldValue = targetNPC.bodyParts[part.name]; var npcNewValue = v.bodyParts[part.name]; var temp = v.bodyParts[part.name]; v.bodyParts[part.name] = targetNPC.bodyParts[part.name]; targetNPC.bodyParts[part.name] = temp; /* Track what NPC received (with old and new values for description) */ result.npcReceived.bodyParts.push({ name: part.name, oldValue: npcOldValue, newValue: npcNewValue }); /* Sync $gender variable after swapping bodyParts.gender */ if (part.name === "gender") { v.gender = v.bodyParts.gender; } /* Update gender-mismatch traits after swapping gender or genitals */ if (part.name === "gender" || part.name === "genitals") { setup.updateGenderMismatchTraits(v); setup.updateGenderMismatchTraits(targetNPC); } /* Sync Futanari trait with genitals after swap */ if (part.name === "genitals") { setup.checkFutanariConsistency(); setup.checkFutanariConsistency(targetNPC); } } else if (part.name === "skinTone" || part.name === "hairColor" || part.name === "age") { /* Track old and new values */ var npcOldValue = targetNPC.appearance[part.name]; var npcNewValue = v.appearance[part.name]; var temp = v.appearance[part.name]; v.appearance[part.name] = targetNPC.appearance[part.name]; targetNPC.appearance[part.name] = temp; /* If swapping age, also swap Youthful/Mature traits (these are independent physical traits, NOT the age value) */ if (part.name === "age") { var playerHadMature = v.physicalTraits.includes("Mature"); var playerHadYouthful = v.physicalTraits.includes("Youthful"); var npcHadMature = targetNPC.physicalTraits.includes("Mature"); var npcHadYouthful = targetNPC.physicalTraits.includes("Youthful"); /* Remove old traits from both */ v.physicalTraits.delete("Mature"); v.physicalTraits.delete("Youthful"); targetNPC.physicalTraits.delete("Mature"); targetNPC.physicalTraits.delete("Youthful"); /* Swap: player gets NPC's traits, NPC gets player's traits */ if (npcHadMature) v.physicalTraits.push("Mature"); if (npcHadYouthful) v.physicalTraits.push("Youthful"); if (playerHadMature) targetNPC.physicalTraits.push("Mature"); if (playerHadYouthful) targetNPC.physicalTraits.push("Youthful"); } /* Track what NPC received */ result.npcReceived.bodyParts.push({ name: part.name, oldValue: npcOldValue, newValue: npcNewValue }); } else if (part.name === "hairLength") { /* Track old and new values */ var npcOldValue = targetNPC.appearance.hairLength; var npcNewValue = v.appearance.hairLength; /* Swap hair length */ var tempHairLength = v.appearance.hairLength; v.appearance.hairLength = targetNPC.appearance.hairLength; targetNPC.appearance.hairLength = tempHairLength; /* Track what NPC received */ result.npcReceived.bodyParts.push({ name: part.name, oldValue: npcOldValue, newValue: npcNewValue }); /* Hair length traits are kept for bonus calculations but filtered from display */ /* So we need to swap them too */ var playerHadShort = v.physicalTraits.includes("Short Hair"); var playerHadLong = v.physicalTraits.includes("Long Hair"); var npcHadShort = targetNPC.physicalTraits.includes("Short Hair"); var npcHadLong = targetNPC.physicalTraits.includes("Long Hair"); /* Remove old traits */ v.physicalTraits.delete("Short Hair"); v.physicalTraits.delete("Long Hair"); targetNPC.physicalTraits.delete("Short Hair"); targetNPC.physicalTraits.delete("Long Hair"); /* Swap the traits */ if (npcHadShort) v.physicalTraits.push("Short Hair"); if (npcHadLong) v.physicalTraits.push("Long Hair"); if (playerHadShort) targetNPC.physicalTraits.push("Short Hair"); if (playerHadLong) targetNPC.physicalTraits.push("Long Hair"); } }); } /* Now that the body-parts swap is complete, apply the NPC's deferred Bimbo activation (gigantic chest/butt override). Doing this after the swap ensures the player received the NPC's real parts, not the override. */ if (npcGainsBimbo) { setup.activateBimboTrait(targetNPC); } /* NPC gives traits/skills to player */ if (npcPackage.physical) { npcPackage.physical.forEach(function(trait) { /* Witch form: cannot receive any transformation traits */ if (v.witchFormActive && setup.isTransformationTrait && setup.isTransformationTrait(trait)) { return; } /* Block Futanari trait for blocked transformations */ if (trait === "Futanari" && setup.isFutanariBlocked()) { /* NPC keeps the trait - don't remove it */ return; } /* If the NPC is giving up a TF trait, undo their transformation first so their body/gender/appearance goes back to pre-TF state. Mirrors what the player side does via revertFullTransformation above. */ if (setup.isTransformationTrait && setup.isTransformationTrait(trait) && typeof setup.revertTransformationFromNPC === "function") { setup.revertTransformationFromNPC(targetNPC, trait); } targetNPC.physicalTraits.delete(trait); /* Track what NPC gave away */ result.npcGave.physical.push(trait); /* Check for conflicts with player's existing traits */ var conflict = setup.getConflictingTrait(trait, v.physicalTraits); if (conflict) { v.physicalTraits.delete(conflict); } if (!v.physicalTraits.includes(trait)) { v.physicalTraits.push(trait); /* Handle Futanari trait received - only auto-swap genitals if genitals are NOT also being traded */ if (trait === "Futanari") { var alsoTradingGenitals = npcPackage.bodyParts && npcPackage.bodyParts.some(function(p) { return p.name === "genitals"; }); if (!alsoTradingGenitals) { var playerOldGenitals = v.bodyParts.genitals || "vagina"; v.bodyParts.genitals = "both"; targetNPC.bodyParts.genitals = playerOldGenitals; if (setup.updateGenderMismatchTraits) { setup.updateGenderMismatchTraits(v); setup.updateGenderMismatchTraits(targetNPC); } } } /* Check if this is a transformation trait being received - apply silently (no cutscene) */ if (setup.isTransformationTrait && setup.isTransformationTrait(trait)) { setup.applyTransformationSilent(trait); } /* Auto-adjust body parts if it's a body type trait (only if not a transformation) */ else if (setup.bodyTypeRequirements[trait]) { setup.adjustBodyPartsForTrait(trait, true); } } }); } if (npcPackage.mental) { npcPackage.mental.forEach(function(trait) { /* Witch form: cannot receive Bimbo trait */ if (v.witchFormActive && trait === "Bimbo") return; /* Special handling for Bimbo trait - deactivate for NPC */ if (trait === "Bimbo") { setup.deactivateBimboTrait(targetNPC); } targetNPC.mentalTraits.delete(trait); /* Track what NPC gave away */ result.npcGave.mental.push(trait); /* Check for conflicts with player's existing traits */ var conflict = setup.getConflictingTrait(trait, v.mentalTraits); if (conflict) { /* If conflict is the character creation trait, remove it */ if (conflict === v.characterCreationTrait) { v.characterCreationTrait = null; } else { v.mentalTraits.delete(conflict); } } /* Add to mental traits (character creation traits become regular traits when received) */ if (!v.mentalTraits.includes(trait)) { v.mentalTraits.push(trait); /* Special handling for Bimbo trait - activate for player */ if (trait === "Bimbo") { setup.activateBimboTrait(v); } } }); } if (npcPackage.skills) { npcPackage.skills.forEach(function(skill) { targetNPC.skills.delete(skill); /* Track what NPC gave away */ result.npcGave.skills.push(skill); if (!v.skills.includes(skill)) { v.skills.push(skill); } }); } /* SPECIAL HANDLING FOR Roisin'S EVOLUTION TRAITS */ /* This runs AFTER all trait transfers are complete */ if (isRoisin) { setup.DEBUG && console.log("=== Roisin EVOLUTION TRAIT CHECK ==="); setup.DEBUG && console.log("Physical traits BEFORE cleanup:", targetNPC.physicalTraits); setup.DEBUG && console.log("Chest BEFORE cleanup:", targetNPC.bodyParts.chest); setup.DEBUG && console.log("Butt BEFORE cleanup:", targetNPC.bodyParts.butt); /* Check if any of her evolution traits were traded away (player received them) */ if (npcPackage.physical) { npcPackage.physical.forEach(function(trait) { /* Reset body parts when evolution size traits are removed */ if (trait === "Gigantic Chest") { targetNPC.bodyParts.chest = "huge"; targetNPC.physicalTraits.delete("Gigantic Chest"); targetNPC.physicalTraits.delete("Giant Chest"); targetNPC.physicalTraits.delete("Huge"); setup.DEBUG && console.log("✓ Roisin traded away Gigantic Chest TRAIT - reset to 'huge'"); } else if (trait === "Gigantic Butt") { targetNPC.bodyParts.butt = "large"; targetNPC.physicalTraits.delete("Gigantic Butt"); targetNPC.physicalTraits.delete("Giant Butt"); targetNPC.physicalTraits.delete("Large Butt"); targetNPC.physicalTraits.delete("Large"); setup.DEBUG && console.log("✓ Roisin traded away Gigantic Butt TRAIT - reset to 'large'"); } else if (trait === "Giant Chest") { targetNPC.bodyParts.chest = "huge"; targetNPC.physicalTraits.delete("Giant Chest"); targetNPC.physicalTraits.delete("Huge"); setup.DEBUG && console.log("✓ Roisin traded away Giant Chest TRAIT - reset to 'huge'"); } else if (trait === "Giant Butt") { targetNPC.bodyParts.butt = "large"; targetNPC.physicalTraits.delete("Giant Butt"); targetNPC.physicalTraits.delete("Large Butt"); targetNPC.physicalTraits.delete("Large"); setup.DEBUG && console.log("✓ Roisin traded away Giant Butt TRAIT - reset to 'large'"); } }); } /* ALSO check if body parts were swapped and clean up mismatched size traits */ if (npcPackage.bodyParts) { npcPackage.bodyParts.forEach(function(part) { if (part.name === "chest") { /* Player took her chest body part, clean up her size traits */ targetNPC.physicalTraits.delete("Gigantic Chest"); targetNPC.physicalTraits.delete("Giant Chest"); targetNPC.physicalTraits.delete("Huge"); setup.DEBUG && console.log("✓ Roisin's chest body part was swapped - cleaned all chest size traits"); } else if (part.name === "butt") { /* Player took her butt body part, clean up her size traits */ targetNPC.physicalTraits.delete("Gigantic Butt"); targetNPC.physicalTraits.delete("Giant Butt"); targetNPC.physicalTraits.delete("Large Butt"); targetNPC.physicalTraits.delete("Large"); setup.DEBUG && console.log("✓ Roisin's butt body part was swapped - cleaned all butt size traits"); } }); } /* Log evolution skills when traded away */ if (npcPackage.skills) { npcPackage.skills.forEach(function(skill) { if (skill === "Sunfish") { setup.DEBUG && console.log("✓ Roisin traded away Sunfish skill"); } else if (skill === "Occult Expert") { setup.DEBUG && console.log("✓ Roisin traded away Occult Expert skill"); } }); } /* Log evolution mental traits when traded away */ if (npcPackage.mental) { npcPackage.mental.forEach(function(trait) { if (trait === "Lucky") { setup.DEBUG && console.log("✓ Roisin traded away Lucky trait"); } }); } setup.DEBUG && console.log("Physical traits AFTER cleanup:", targetNPC.physicalTraits); setup.DEBUG && console.log("Chest AFTER cleanup:", targetNPC.bodyParts.chest); setup.DEBUG && console.log("Butt AFTER cleanup:", targetNPC.bodyParts.butt); setup.DEBUG && console.log("=== END Roisin CHECK ==="); } /* Job swap */ if (playerPackage.job !== null && playerPackage.job !== undefined) { var playerOldJob = v.jobs && v.jobs.length > 0 ? v.jobs[0] : "Unemployed"; var npcOldJob = targetNPC.jobs && targetNPC.jobs.length > 0 ? targetNPC.jobs[0] : "Unemployed"; result.npcReceived.job = playerOldJob; result.npcGave.job = npcOldJob; /* Update player's job to what NPC had */ if (npcOldJob !== "Unemployed") { v.jobs = [npcOldJob]; v.homeless = false; } else { v.jobs = []; } /* Update NPC's job - replace only the FIRST job, keep others */ if (playerOldJob !== "Unemployed") { if (targetNPC.jobs.length > 1) { /* NPC has multiple jobs - replace the first one */ targetNPC.jobs[0] = playerOldJob; } else { /* NPC has one or no jobs - set as single job */ targetNPC.jobs = [playerOldJob]; } } else { /* Player gave Unemployed - remove first job but keep others */ if (targetNPC.jobs.length > 1) { targetNPC.jobs.shift(); /* Remove first job */ } else { targetNPC.jobs = []; } } /* Update NPC schedule to match new job (fixes named NPCs with custom schedules) */ var npcNewJob = targetNPC.jobs && targetNPC.jobs.length > 0 ? targetNPC.jobs[0] : "Unemployed"; setup.updateNPCScheduleForJob(targetNPC.name, npcNewJob); } /* Update the reference */ v.tradingWithNPC = targetNPC; /* DYNAMIC BEHAVIOR UPDATE: Recalculate personality and update behavior based on new traits */ setup.updateNPCBehavior(targetNPC); /* Calculate BASE relationship points BEFORE applying artifact multiplier */ /* This now includes skill tree tradeRelationshipBonus when NPC receives desired items */ var baseRelationshipPoints = setup.addTradeRelationshipBonus(npc, playerPackage, npcPackage); var finalRelationshipPoints = baseRelationshipPoints; /* Gentle Giant's Heart / Naiad 8x is applied centrally in addRelationshipPoints; do NOT pre-multiply here. */ /* Add the modified relationship points */ if (finalRelationshipPoints !== 0) { setup.addRelationshipPoints(npc.name, finalRelationshipPoints); } /* Store relationship points in result for display */ result.relationshipChange = ((v.currentArtifact === "The Gentle Giant's Heart" || (v.physicalTraits && v.physicalTraits.includes("Naiad"))) ? finalRelationshipPoints * 8 : finalRelationshipPoints); result.hasArtifactBonus = ((v.currentArtifact === "The Gentle Giant's Heart" || (v.physicalTraits && v.physicalTraits.includes("Naiad"))) && baseRelationshipPoints !== 0); /* Decrease trades remaining */ v.tradesRemainingToday -= 1; /* Clear trade packages */ v.playerTradePackage = {stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: []}; v.npcTradePackage = {stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: []}; } else { /* Trade failed */ v.failedTradesWithToday.push(npc.name); v.tradesRemainingToday -= 1; result.relationshipChange = 0; result.hasArtifactBonus = false; } return result; }>>
/* ---------------------------------- */ /* --- JOB SCHEDULES (CONSTANT DATA) --- */ /* ---------------------------------- */ <<set setup.jobSchedules = { "Unemployed": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening", "night"], alwaysAvailable: true }, "Street Performer": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["afternoon", "evening"], alwaysAvailable: false }, "Package Courier": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Construction Worker": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Dock Worker": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Security Guard": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: false }, "Baker": { days: ["Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Maid": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Fitness Shop Clerk": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: false }, "Tech Store Clerk": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: false }, "Adult Store Clerk": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["afternoon", "evening", "night"], alwaysAvailable: false }, "Beauty Salon Stylist": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: false }, "Ecentric Shop Worker": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: false }, "Brothel Worker": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: false }, "Brothel Owner": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["afternoon", "evening", "night"], alwaysAvailable: false }, "City Mayor": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Mayor's Secretary": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: false }, "Stripper": { days: ["Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: false }, "Prostitute": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: false }, "Model": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Bouncer": { days: ["Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: false }, "Porn Star": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["afternoon", "evening"], alwaysAvailable: false }, "Social Media Influencer": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: false }, "Black Market Dealer": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["night"], alwaysAvailable: false }, "Police Officer": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening", "night"], alwaysAvailable: false }, "Clinic Assistant": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Data Analyst": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: false }, "Negotiator": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["afternoon", "evening"], alwaysAvailable: false }, "Enforcer": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: false } }>> /* ---------------------------------- */ /* --- UPDATE NPC SCHEDULE FOR JOB --- */ /* ---------------------------------- */
/* ---------------------------------- */ /* --- PLAYER DIALOGUE GENERATION --- */ /* ---------------------------------- */ <<set setup.getPlayerDialogue = function(topic) { var v = State.variables; var dialogues = []; if (topic === "compliment") { /* Layer 1: Primary personality modifiers */ if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Seductive")) { if (v.mentalTraits.includes("Confident")) { dialogues.push("You know, you're looking absolutely stunning today... and I bet you know it too."); dialogues.push("Damn, you're gorgeous. I'm not even trying to be subtle here."); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("Um... you're really... really attractive... I hope that's not too forward..."); dialogues.push("I've been thinking... you're beautiful... sorry if that's weird..."); } else { dialogues.push("You're looking absolutely stunning today..."); dialogues.push("I have to say, you're really attractive. Like, really attractive."); dialogues.push("Has anyone ever told you how gorgeous you are?"); } } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward") || v.mentalTraits.includes("Insecure")) { if (v.mentalTraits.includes("Kind")) { dialogues.push("Um... I just wanted to say... you seem really nice... and you look nice too..."); dialogues.push("Sorry if this is awkward, but... I think you're a really good person..."); } else if (v.mentalTraits.includes("Honest")) { dialogues.push("I'm not good at this, but... honestly, you're pretty great..."); dialogues.push("This is hard to say, but... I think you're cool. Really cool."); } else { dialogues.push("Um... you look... you look really nice today..."); dialogues.push("I just wanted to say... you're... you're pretty cool..."); dialogues.push("Sorry if this is weird, but... I think you're really great..."); } } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Charming")) { if (v.mentalTraits.includes("Friendly") || v.mentalTraits.includes("Warm")) { dialogues.push("You're looking fantastic today! Seriously, you've got such great energy!"); dialogues.push("I just have to say - you're an amazing person and it shows!"); } else if (v.mentalTraits.includes("Arrogant")) { dialogues.push("You know, for most people I wouldn't bother, but you're actually impressive."); dialogues.push("I don't give compliments often, but you're worthy of one. You look good."); } else { dialogues.push("You're looking great today! Seriously, you've got style."); dialogues.push("I appreciate what you bring to the table. You're a good person."); dialogues.push("Just wanted to let you know - you're pretty awesome."); } } else if (v.mentalTraits.includes("Direct") || v.mentalTraits.includes("Blunt") || v.mentalTraits.includes("Honest")) { if (v.mentalTraits.includes("Rude")) { dialogues.push("You don't look terrible. That's something."); dialogues.push("I guess you look okay. Better than most people here."); } else if (v.mentalTraits.includes("Kind")) { dialogues.push("I'm just being honest - you're a really good person and I respect that."); dialogues.push("Straight up, you're great. That's just the truth."); } else { dialogues.push("You look good. That's all."); dialogues.push("I respect you. Thought you should know."); dialogues.push("You're a solid person. Just being honest."); } } else if (v.mentalTraits.includes("Friendly") || v.mentalTraits.includes("Warm") || v.mentalTraits.includes("Kind")) { if (v.mentalTraits.includes("Energetic") || v.mentalTraits.includes("Talkative")) { dialogues.push("Oh my gosh, I just have to tell you - you're such a wonderful person! Like, genuinely amazing!"); dialogues.push("You're so great! Every time I see you it just makes my day better! You're the best!"); } else { dialogues.push("Hey, I just wanted to say you're a really great person!"); dialogues.push("You always brighten up the room, you know that?"); dialogues.push("I really enjoy spending time with you. You're awesome!"); } } else if (v.mentalTraits.includes("Sarcastic") || v.mentalTraits.includes("Witty")) { dialogues.push("I'm shocked to say this, but... you're actually pretty cool. Who knew?"); dialogues.push("Against all odds, you've managed to be impressive. Congratulations."); dialogues.push("Well, well... looks like someone's doing something right. Good for you."); } else if (v.mentalTraits.includes("Polite") || v.mentalTraits.includes("Diplomatic")) { dialogues.push("If I may say so, you carry yourself very well. It's quite admirable."); dialogues.push("I wanted to express my appreciation for your character. You're quite remarkable."); dialogues.push("Please allow me to say - you're a truly commendable individual."); } else if (v.mentalTraits.includes("Nonchalant") || v.mentalTraits.includes("Chill")) { dialogues.push("Yeah, you're pretty cool. Just thought I'd mention it."); dialogues.push("You're alright. Better than alright, actually."); dialogues.push("Gotta say, you're a good person to know."); } else { dialogues.push("I think you're really cool, honestly."); dialogues.push("You seem like a good person. Just thought I'd say that."); dialogues.push("You're pretty great, you know?"); } } else if (topic === "insult") { /* Insults based on personality */ if (v.mentalTraits.includes("Bitchy") || v.mentalTraits.includes("Rude")) { if (v.mentalTraits.includes("Arrogant")) { dialogues.push("You're pathetic. Like, genuinely beneath me. It's almost sad."); dialogues.push("I've met garbage with more class than you. And I'm not even exaggerating."); } else if (v.mentalTraits.includes("Sarcastic")) { dialogues.push("Oh wow, you're just SO impressive. Really. I'm in awe of your mediocrity."); dialogues.push("Congratulations on being the most disappointing person I've met today. And that's saying something."); } else { dialogues.push("You know what? You're kind of pathetic, honestly."); dialogues.push("Wow, you're even more annoying than I thought."); dialogues.push("Do everyone a favor and shut up for once."); } } else if (v.mentalTraits.includes("Aggressive") || v.mentalTraits.includes("Short Tempered")) { if (v.mentalTraits.includes("Dominant")) { dialogues.push("You're really pissing me off right now! Know your place!"); dialogues.push("I'm done with your shit! You need to back the hell off!"); } else if (v.mentalTraits.includes("Impulsive") || v.mentalTraits.includes("Reckless")) { dialogues.push("You know what?! FUCK YOU! I don't need this!"); dialogues.push("That's IT! You're a complete asshole and I'm DONE!"); } else { dialogues.push("You're really pissing me off right now!"); dialogues.push("I'm sick of your attitude!"); dialogues.push("You know what your problem is? Everything."); } } else if (v.mentalTraits.includes("Cruel") || v.mentalTraits.includes("Cold") || v.mentalTraits.includes("Insensitive")) { if (v.mentalTraits.includes("Calm")) { dialogues.push("You're worthless. Completely worthless. And that's just an objective fact."); dialogues.push("I don't know why anyone tolerates you. I certainly don't plan to."); } else if (v.mentalTraits.includes("Blunt")) { dialogues.push("You're a waste of space. That's not an insult, it's an observation."); dialogues.push("Honestly? You're garbage. Pure garbage."); } else { dialogues.push("You're worthless. Completely worthless."); dialogues.push("I don't know why anyone tolerates you."); dialogues.push("You're a waste of space."); } } else if (v.mentalTraits.includes("Sarcastic") || v.mentalTraits.includes("Witty")) { if (v.mentalTraits.includes("Arrogant")) { dialogues.push("Oh wow, you're just SO impressive. Really. I'm trembling with awe at your incompetence."); dialogues.push("Bravo. Truly. You've somehow managed to be even more disappointing than I expected."); } else if (v.mentalTraits.includes("Cynical")) { dialogues.push("Congratulations on being the most mediocre person I've met. And I meet a lot of mediocre people."); dialogues.push("Your personality is about as exciting as watching paint dry. Actually, paint drying is more interesting."); } else { dialogues.push("Oh wow, you're just SO impressive. Really."); dialogues.push("Congratulations on being the most mediocre person I've met today."); dialogues.push("Your personality is about as exciting as watching paint dry."); } } else if (v.mentalTraits.includes("Blunt") || v.mentalTraits.includes("Direct")) { if (v.mentalTraits.includes("Honest")) { dialogues.push("You're annoying. That's just the truth."); dialogues.push("I don't like you. I'm just being honest here."); } else { dialogues.push("You're annoying. Plain and simple."); dialogues.push("I don't like you. At all."); } } else if (v.mentalTraits.includes("Passive Aggressive") || v.mentalTraits.includes("Jealous")) { dialogues.push("Oh, how nice for you. Must be so easy being you. So... easy."); dialogues.push("Wow, you're just perfect, aren't you? Absolutely perfect. *Clearly sarcastic*"); dialogues.push("I'm SO happy for you. Really. Can't you tell how happy I am?"); } else if (v.mentalTraits.includes("Moody") || v.mentalTraits.includes("Erratic")) { dialogues.push("You know what? I'm DONE with you! You're terrible!"); dialogues.push("Ugh! You're SO annoying! I can't even deal with you right now!"); dialogues.push("Why are you like this?! You're the WORST!"); } else { dialogues.push("You're really annoying, you know that?"); dialogues.push("I don't like you. At all."); dialogues.push("You're kind of terrible, honestly."); } } else if (topic === "opinion") { /* Asking their opinion */ if (v.mentalTraits.includes("Insecure") || v.mentalTraits.includes("Anxious")) { if (v.mentalTraits.includes("Shy")) { dialogues.push("Um... can I ask... what do you think of me? I'm... I'm really nervous to hear it..."); dialogues.push("I've been wondering... do you think I'm... okay? As a person? Sorry if that's weird..."); } else if (v.mentalTraits.includes("Sensitive")) { dialogues.push("Please be gentle, but... what do you honestly think of me? I'm worried..."); dialogues.push("I need to know... what's your opinion of me? I can handle it... I think..."); } else { dialogues.push("So... what do you think of me? Be honest... I can take it..."); dialogues.push("I've been wondering... do you think I'm okay? As a person?"); dialogues.push("Can I ask... what's your honest opinion of me? I'm a bit nervous to hear it..."); } } else if (v.mentalTraits.includes("Arrogant") || v.mentalTraits.includes("Vain")) { if (v.mentalTraits.includes("Confident")) { dialogues.push("So, what do you think of me? And don't hold back - I already know I'm impressive, but I want to hear you say it."); dialogues.push("Give me your assessment. I'm obviously great, but I'm curious what you specifically appreciate about me."); } else if (v.mentalTraits.includes("Dominant")) { dialogues.push("Tell me what you think of me. I expect honesty, and I expect it to be positive."); dialogues.push("Your opinion of me - give it. Make it good."); } else { dialogues.push("So, what do you think of me? And don't hold back - I know I'm impressive."); dialogues.push("I'm curious what your assessment of me is. I already know I'm great, but go ahead."); dialogues.push("Give me your honest opinion of me. Though I'm sure it's positive."); } } else if (v.mentalTraits.includes("Curious") || v.mentalTraits.includes("Analytical")) { if (v.mentalTraits.includes("Direct")) { dialogues.push("What's your objective assessment of me? I'm collecting data."); dialogues.push("I need your honest evaluation. What do you think of me?"); } else if (v.mentalTraits.includes("Thoughtful")) { dialogues.push("I'm genuinely curious about your perception of me. How do you see me as a person?"); dialogues.push("I've been contemplating self-perception versus external perception. What's your honest view of me?"); } else { dialogues.push("I'm genuinely curious - what's your honest assessment of me as a person?"); dialogues.push("From your perspective, what kind of person do you think I am?"); dialogues.push("I'd like to know your objective opinion of me, if you don't mind sharing."); } } else if (v.mentalTraits.includes("Direct") || v.mentalTraits.includes("Blunt")) { if (v.mentalTraits.includes("Honest")) { dialogues.push("What do you think of me? And I want the truth, not politeness."); dialogues.push("Give it to me straight - what's your real opinion of me?"); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("What do you think of me? Don't sugarcoat it. I can handle honesty."); dialogues.push("Your opinion of me. Now. No bullshit."); } else { dialogues.push("What do you think of me? Don't sugarcoat it."); dialogues.push("Give it to me straight - what's your opinion of me?"); dialogues.push("Be honest. What do you think about me?"); } } else if (v.mentalTraits.includes("Friendly") || v.mentalTraits.includes("Warm")) { if (v.mentalTraits.includes("Talkative") || v.mentalTraits.includes("Outgoing")) { dialogues.push("Hey! I'd absolutely love to know what you think of me! Be totally honest - I really want to know!"); dialogues.push("Ooh, ooh! Tell me what you think about me! I'm so curious and I promise I won't be offended!"); } else if (v.mentalTraits.includes("Kind")) { dialogues.push("I'd really appreciate hearing what you think of me. Your opinion matters to me!"); dialogues.push("If you don't mind sharing, I'd love to know your thoughts about me as a person."); } else { dialogues.push("Hey, I'd love to know what you think of me! Honest opinions only!"); dialogues.push("So, what's your take on me? I'm genuinely interested!"); dialogues.push("I'm curious - how do you see me as a person?"); } } else if (v.mentalTraits.includes("Nonchalant") || v.mentalTraits.includes("Chill")) { dialogues.push("So what do you think of me? Just curious."); dialogues.push("What's your take on me?"); dialogues.push("Your opinion of me - what is it?"); } else if (v.mentalTraits.includes("Polite") || v.mentalTraits.includes("Diplomatic")) { dialogues.push("If I may ask, what is your opinion of me? I value your perspective."); dialogues.push("I would appreciate hearing your thoughts about me, if you're comfortable sharing."); dialogues.push("May I inquire as to your assessment of my character?"); } else { dialogues.push("What's your honest opinion of me?"); dialogues.push("So... what do you think of me?"); dialogues.push("I'm curious what you think about me."); } } else if (topic === "job") { /* Asking about their job */ if (v.mentalTraits.includes("Curious") || v.mentalTraits.includes("Interested")) { if (v.mentalTraits.includes("Energetic") || v.mentalTraits.includes("Talkative")) { dialogues.push("Oh! What do you do for work?! I'm SO curious! Tell me everything!"); dialogues.push("I've been dying to know - what's your job? What's it like? Is it fun?!"); } else if (v.mentalTraits.includes("Analytical")) { dialogues.push("I'm quite interested in learning about your occupation. What field are you in?"); dialogues.push("What's your professional role? I'd like to understand more about what you do."); } else { dialogues.push("So what do you do for work? I'm really curious!"); dialogues.push("Tell me about your job! What's it like?"); dialogues.push("I'd love to hear about what you do for a living!"); } } else if (v.mentalTraits.includes("Nonchalant") || v.mentalTraits.includes("Chill")) { dialogues.push("So, what's your job?"); dialogues.push("What do you do for work?"); dialogues.push("You working anywhere?"); } else if (v.mentalTraits.includes("Professional") || v.mentalTraits.includes("Businesslike")) { dialogues.push("What's your current occupation?"); dialogues.push("May I ask what line of work you're in?"); dialogues.push("What's your professional role?"); } else if (v.mentalTraits.includes("Nosy") || v.mentalTraits.includes("Gossipy")) { dialogues.push("Okay, so I've been dying to know - what do you do for work?"); dialogues.push("Spill! What's your job? I need to know!"); dialogues.push("Come on, tell me - where do you work?"); } else if (v.mentalTraits.includes("Direct") || v.mentalTraits.includes("Blunt")) { dialogues.push("What's your job?"); dialogues.push("Where do you work?"); dialogues.push("What do you do?"); } else if (v.mentalTraits.includes("Polite") || v.mentalTraits.includes("Diplomatic")) { dialogues.push("If you don't mind my asking, what is your occupation?"); dialogues.push("May I inquire about your line of work?"); dialogues.push("What do you do professionally, if I may ask?"); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("So... um... what do you do for work? If you don't mind me asking..."); dialogues.push("I was wondering... what's your job?"); dialogues.push("Can I ask... what do you do?"); } else { dialogues.push("What do you do for work?"); dialogues.push("So, what's your job?"); dialogues.push("What kind of work do you do?"); } } else if (topic === "trading") { /* Asking about trading */ if (v.mentalTraits.includes("Shrewd") || v.mentalTraits.includes("Sly")) { if (v.mentalTraits.includes("Confident")) { dialogues.push("Let's talk business. I'm curious about your trading preferences. What catches your eye?"); dialogues.push("I think we could make some mutually beneficial arrangements. What interests you?"); } else if (v.mentalTraits.includes("Careful") || v.mentalTraits.includes("Cautious")) { dialogues.push("I'm exploring potential trading opportunities. What might you be interested in?"); dialogues.push("Hypothetically speaking, what would appeal to you in a trade?"); } else { dialogues.push("I'm curious about what you might be willing to trade. What interests you?"); dialogues.push("Let's talk business. What are you looking for in a trade?"); dialogues.push("So, hypothetically speaking... what would you be willing to trade?"); } } else if (v.mentalTraits.includes("Direct") || v.mentalTraits.includes("Blunt")) { if (v.mentalTraits.includes("Businesslike")) { dialogues.push("Trading. Are you interested? What are your terms?"); dialogues.push("Let's discuss trading. What do you want?"); } else { dialogues.push("Are you interested in trading? What do you want?"); dialogues.push("Let's cut to the chase - what would you trade for?"); dialogues.push("Trading. You interested? What are you after?"); } } else if (v.mentalTraits.includes("Friendly") || v.mentalTraits.includes("Warm")) { if (v.mentalTraits.includes("Enthusiastic") || v.mentalTraits.includes("Energetic")) { dialogues.push("Hey! I was thinking - are you interested in trading? What kind of things would you love to get?!"); dialogues.push("Ooh! Trading! Are you into it? What are you looking for? I'm so curious!"); } else { dialogues.push("Hey, I was wondering if you'd ever be interested in trading? What kind of things appeal to you?"); dialogues.push("So, just curious - are you open to trading? What would you be looking for?"); dialogues.push("I'd love to know what you're interested in trading for!"); } } else if (v.mentalTraits.includes("Cautious") || v.mentalTraits.includes("Careful")) { if (v.mentalTraits.includes("Analytical")) { dialogues.push("I'm evaluating trading possibilities. What parameters would interest you?"); dialogues.push("From a practical standpoint, what would you consider for a trade?"); } else { dialogues.push("I wanted to ask... would you ever consider trading? What might you be interested in?"); dialogues.push("Just exploring options here - what would you potentially trade for?"); dialogues.push("Hypothetically, what kind of trades would interest you?"); } } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("Um... so... I was wondering about trading? What would you... be interested in?"); dialogues.push("I wanted to ask... are you... open to trading? What do you like?"); dialogues.push("This might be awkward but... trading? Are you interested?"); } else if (v.mentalTraits.includes("Polite") || v.mentalTraits.includes("Diplomatic")) { dialogues.push("If you'd be amenable, I'd like to discuss trading possibilities. What might interest you?"); dialogues.push("Might I inquire about your trading preferences? What appeals to you?"); dialogues.push("Would you be open to discussing potential trades? What would you find valuable?"); } else { dialogues.push("Are you interested in trading? What are you looking for?"); dialogues.push("What would you be willing to trade for?"); dialogues.push("I'm curious about your trading preferences. What interests you?"); } } else if (topic === "smalltalk") { /* Small talk */ if (v.mentalTraits.includes("Outgoing") || v.mentalTraits.includes("Talkative") || v.mentalTraits.includes("Energetic")) { if (v.mentalTraits.includes("Friendly")) { dialogues.push("Hey there! So! How's everything been going? What's new with you? Tell me everything!"); dialogues.push("Oh my gosh, hi! Let's just chat! How have you been? What's happening in your life?!"); } else if (v.mentalTraits.includes("Enthusiastic")) { dialogues.push("So! What's up?! How's life?! What have you been doing?!"); dialogues.push("Hey! Let's talk! What's been going on with you?!"); } else { dialogues.push("So! How's everything been going? What's new with you?"); dialogues.push("Hey! Let's chat! How have you been? What's going on?"); dialogues.push("I'm in the mood to just talk! How's life treating you?"); } } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { if (v.mentalTraits.includes("Kind")) { dialogues.push("Um... so... how have you been? I hope everything's okay..."); dialogues.push("I was just... wondering how things are going for you..."); } else if (v.mentalTraits.includes("Anxious")) { dialogues.push("So... um... the weather's been... okay... hasn't it? Sorry, I'm not good at this..."); dialogues.push("I... uh... how are things? Sorry if this is awkward..."); } else { dialogues.push("So... um... how are things?"); dialogues.push("I was just... wondering how you've been..."); dialogues.push("The weather's been... nice... hasn't it?"); } } else if (v.mentalTraits.includes("Nonchalant") || v.mentalTraits.includes("Chill")) { dialogues.push("What's up? How's it going?"); dialogues.push("So, what's new?"); dialogues.push("How've you been?"); } else if (v.mentalTraits.includes("Polite") || v.mentalTraits.includes("Diplomatic")) { dialogues.push("Good day! How have you been faring lately?"); dialogues.push("I hope things have been going well for you?"); dialogues.push("How are you doing these days?"); } else if (v.mentalTraits.includes("Direct") || v.mentalTraits.includes("Blunt")) { dialogues.push("How are you?"); dialogues.push("What's new?"); dialogues.push("Everything good?"); } else if (v.mentalTraits.includes("Sarcastic")) { dialogues.push("So... lovely weather we're having. Riveting stuff."); dialogues.push("How about that local sports team? Really giving it their all, I'm sure."); dialogues.push("What's new? Besides the crushing monotony of existence?"); } else if (v.mentalTraits.includes("Bitchy") || v.mentalTraits.includes("Rude")) { dialogues.push("So... we're really doing small talk? Fine. How are you or whatever."); dialogues.push("What's up. And don't bore me with your life story."); dialogues.push("How's it going. Keep it short."); } else { dialogues.push("So, how's everything going?"); dialogues.push("What's been happening with you?"); dialogues.push("How are things?"); } } /* === NEW CONVERSATION TOPICS === */ else if (topic === "flirt") { /* Flirting dialogue - based on player personality */ /* Check for highly sexual traits for more explicit dialogue */ var hasExplicitTraits = v.mentalTraits.includes("Nymphomaniac") || v.mentalTraits.includes("Lustful") || v.mentalTraits.includes("Perverted") || v.mentalTraits.includes("Lewd"); var hasSeductiveTraits = v.mentalTraits.includes("Seductive") || v.mentalTraits.includes("Flirty"); /* EXPLICIT SEXUAL FLIRTING - requires Nymphomaniac/Lustful/Perverted/Lewd traits */ if (hasExplicitTraits) { if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Dominant")) { dialogues.push("*eyes roam your body hungrily* I want you. Right now. I've been thinking about all the things I want to do to you..."); dialogues.push("*moves very close* I can't stop thinking about how good you'd feel... how good you'd taste..."); dialogues.push("*whispers seductively* Let's stop pretending. I know you want me too. I can see it in your eyes..."); } else if (v.mentalTraits.includes("Submissive")) { dialogues.push("*looks up at you with need* I... I want you so badly. Please... I'll do anything you want..."); dialogues.push("*whimpers* I can't stop thinking about you... about being yours... please use me..."); dialogues.push("*trembling* I need you. My body aches for your touch. I'll be good, I promise..."); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("*blushing intensely* I... I have these thoughts about you... really dirty thoughts... I'm sorry..."); dialogues.push("*can barely speak* Y-you make me feel... things... *voice drops* ...I want you so much..."); dialogues.push("*fidgeting nervously* I know I shouldn't say this but... I fantasize about you... a lot..."); } else { dialogues.push("*breathing heavily* I want you. I've been imagining what we could do together... alone..."); dialogues.push("*bites lip* I can't control myself around you. You make me so... worked up..."); dialogues.push("*intense gaze* Let's find somewhere private. I need to feel you against me..."); } } /* SEDUCTIVE FLIRTING - Seductive/Flirty traits (moderately sensual) */ else if (hasSeductiveTraits) { if (v.mentalTraits.includes("Confident")) { dialogues.push("*leans in with a smile* You know, I can't help but notice how attractive you are..."); dialogues.push("I've been watching you, and I have to say... you're absolutely captivating."); dialogues.push("*smirks* Has anyone ever told you that you have the most gorgeous eyes?"); } else if (v.mentalTraits.includes("Playful")) { dialogues.push("*twirls hair* So... do you come here often? Because I'd definitely remember someone like you."); dialogues.push("You're cute. Like, really cute. I just thought you should know."); dialogues.push("*winks* Is it hot in here, or is it just you?"); } else { dialogues.push("*moves closer* I've been thinking about you... a lot, actually."); dialogues.push("There's something about you that I find absolutely irresistible."); dialogues.push("I can't help it... I'm drawn to you."); } } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { if (v.mentalTraits.includes("Romantic")) { dialogues.push("I... um... I think you're really... *blushes* ...beautiful. Sorry, was that weird?"); dialogues.push("*fidgets nervously* I've wanted to tell you... you're... you're really special to me..."); dialogues.push("This is embarrassing but... I can't stop thinking about you..."); } else { dialogues.push("Um... so... you're... you're really... *trails off* ...attractive..."); dialogues.push("I... uh... *face turns red* ...you look nice. Really nice."); dialogues.push("*stares at feet* I like you... like, LIKE you like you... sorry..."); } } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Charming")) { if (v.mentalTraits.includes("Smooth")) { dialogues.push("I have to be honest with you - I find you incredibly attractive."); dialogues.push("There's something magnetic about you. I had to say something."); dialogues.push("I'm not usually this forward, but... you've caught my attention."); } else { dialogues.push("You know, you're really good-looking. Just putting that out there."); dialogues.push("I'd be lying if I said I wasn't attracted to you."); dialogues.push("Can I just say... you're absolutely stunning."); } } else if (v.mentalTraits.includes("Playful") || v.mentalTraits.includes("Mischievous")) { dialogues.push("*grins* So... are you always this cute, or did you do something special today?"); dialogues.push("Hey, I've got a question - are you a magician? Because whenever I look at you, everyone else disappears."); dialogues.push("I was trying to think of a clever pick-up line, but honestly? You're just really hot."); } else if (v.mentalTraits.includes("Direct") || v.mentalTraits.includes("Blunt")) { dialogues.push("Look, I'm just going to say it - I'm attracted to you."); dialogues.push("I'm not going to play games. I think you're hot. There it is."); dialogues.push("I find you attractive. Thought you should know."); } else if (v.mentalTraits.includes("Romantic")) { dialogues.push("I know this might seem sudden, but... I feel a connection with you."); dialogues.push("There's something special about you. I can't explain it, but I feel drawn to you."); dialogues.push("Every time I see you, my heart beats a little faster..."); } else { dialogues.push("So... I think you're really attractive..."); dialogues.push("I've been wanting to tell you... I like you. A lot."); dialogues.push("You're pretty amazing, you know that?"); } } else if (topic === "debate") { if (v.mentalTraits.includes("Nerd") || v.mentalTraits.includes("Intelligent")) { if (v.mentalTraits.includes("Enthusiastic")) { dialogues.push("Oh! I'd love to hear your thoughts on this! What's your take on the nature of reality?"); dialogues.push("Have you ever considered the philosophical implications of consciousness? I have SO many thoughts!"); } else { dialogues.push("I'd love to have an intellectual discussion with you. What topics interest you?"); dialogues.push("Let's explore some ideas together. What's your perspective on...?"); } } else if (v.mentalTraits.includes("Analytical") || v.mentalTraits.includes("Curious")) { dialogues.push("I've been analyzing some interesting problems. Want to discuss them?"); dialogues.push("Let's examine this from multiple angles. What do you think about...?"); } else { dialogues.push("Want to have an intellectual discussion about something?"); dialogues.push("I've been thinking about some interesting ideas. Want to debate?"); } } else if (topic === "fitness") { if (v.mentalTraits.includes("Jock") || v.mentalTraits.includes("Athletic")) { if (v.mentalTraits.includes("Competitive")) { dialogues.push("So, you work out? What's your PR? I bet I can beat it!"); dialogues.push("Let's talk gains! What's your training routine?"); } else { dialogues.push("So, you into fitness? What's your workout routine like?"); dialogues.push("Let's talk sports! What are you into?"); } } else { dialogues.push("So, are you into fitness or sports at all?"); dialogues.push("What kind of physical activities do you enjoy?"); } } else if (topic === "gossip") { if (v.mentalTraits.includes("Gossipy") || v.mentalTraits.includes("Nosy")) { dialogues.push("Oh my GOD, have you heard what's been going on?! I have SO much to tell you!"); dialogues.push("*whispers* Have you heard what's been going on around here?"); } else { dialogues.push("So... heard any good gossip lately?"); dialogues.push("What's the word around here? Anything interesting happening?"); } } else if (topic === "darkTopics") { if (v.mentalTraits.includes("Goth") || v.mentalTraits.includes("Pessimistic")) { dialogues.push("Let's discuss something real. What do you think happens when we die?"); dialogues.push("The world is a cruel place. Don't you ever just... feel the weight of it?"); } else if (v.mentalTraits.includes("Philosophical")) { dialogues.push("I've been contemplating mortality. What are your thoughts on death?"); dialogues.push("The nature of suffering... why do we experience pain?"); } else { dialogues.push("Can we talk about something deeper? Something... darker?"); dialogues.push("What's the darkest thought you've ever had? I won't judge."); } } else if (topic === "beSubmissive") { if (v.mentalTraits.includes("Submissive") || v.mentalTraits.includes("Timid")) { dialogues.push("*looks down* Whatever you want to talk about... I'll follow your lead..."); dialogues.push("You're in charge here. I'm just... happy to go along with whatever you want."); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("Um... you seem like you know what you're doing. I'll... I'll follow you."); } else { dialogues.push("You know what? You lead. I'll follow."); dialogues.push("Guide me. I want to hear what you have to say."); } } else if (topic === "takeCharge") { if (v.mentalTraits.includes("Dominant") || v.mentalTraits.includes("Bossy")) { dialogues.push("Alright, here's what we're going to do. Listen up."); dialogues.push("I'll handle this. Just follow my lead and everything will be fine."); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("I've got this. Let me take the lead for a moment."); dialogues.push("Trust me on this one. I know what I'm doing."); } else { dialogues.push("Can I take the lead on this one?"); dialogues.push("Let me guide this conversation for a bit."); } } else if (topic === "playAlong") { if (v.mentalTraits.includes("Bimbo") || v.mentalTraits.includes("Airhead")) { dialogues.push("Oh my gosh, YES! Let's totally do that! Whatever it is!"); dialogues.push("Like, that sounds SO fun! I'm totally in!"); } else if (v.mentalTraits.includes("Bubbly") || v.mentalTraits.includes("Enthusiastic")) { dialogues.push("YES! I'm SO into whatever you're into! Let's GO!"); } else { dialogues.push("Okay, I'm playing along! This is fun!"); dialogues.push("Ha! I'm totally with you on this!"); } } else if (topic === "fashion") { if (v.mentalTraits.includes("Prep") || v.mentalTraits.includes("Vain")) { dialogues.push("So, I couldn't help but notice your style. Let's talk fashion!"); dialogues.push("Fashion is everything, don't you think? What's your signature look?"); } else { dialogues.push("So, what's your style like? I'm curious!"); dialogues.push("Let's talk fashion! What do you usually wear?"); } } else if (topic === "advice") { if (v.mentalTraits.includes("Insecure") || v.mentalTraits.includes("Anxious")) { dialogues.push("I... I really need some advice. I don't know what to do..."); } else if (v.mentalTraits.includes("Friendly")) { dialogues.push("Hey, can I ask you something? I could really use some advice!"); } else { dialogues.push("Can I ask you for some advice?"); dialogues.push("I've been thinking about something and I'd appreciate your input."); } } else if (topic === "secrets") { if (v.mentalTraits.includes("Trusting") || v.mentalTraits.includes("Open")) { dialogues.push("I feel like I can trust you... Can I tell you something?"); } else if (v.mentalTraits.includes("Mischievous")) { dialogues.push("Want to hear something you definitely shouldn't know?"); } else { dialogues.push("Can I share a secret with you?"); dialogues.push("I trust you enough to tell you this. Can you keep a secret?"); } } else if (topic === "support") { if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Caring")) { dialogues.push("Hey, I just wanted to check in on you. How are you really doing?"); dialogues.push("I'm here for you, you know that right? Whatever you're going through."); } else { dialogues.push("Hey, I just wanted you to know I'm here if you need support."); dialogues.push("You can count on me, you know. I've got your back."); } } else if (topic === "plan") { if (v.mentalTraits.includes("Enthusiastic") || v.mentalTraits.includes("Energetic")) { dialogues.push("Oh my gosh, we should totally hang out! What do you want to do?!"); dialogues.push("Let's make plans! I have SO many ideas!"); } else { dialogues.push("Hey, want to make some plans to hang out?"); dialogues.push("We should do something together sometime. What sounds fun?"); } } else if (topic === "deep") { if (v.mentalTraits.includes("Philosophical") || v.mentalTraits.includes("Thoughtful")) { dialogues.push("I want to go deeper. What truly matters to you in life?"); dialogues.push("Let's have a real conversation. What are your deepest fears and hopes?"); } else { dialogues.push("Can we have a deeper conversation? I want to really know you."); dialogues.push("Let's talk about something meaningful. What matters most to you?"); } } else if (topic === "confide") { if (v.mentalTraits.includes("Anxious") || v.mentalTraits.includes("Worried")) { dialogues.push("I... I've been so worried lately. Can I talk to you about it?"); } else { dialogues.push("Can I confide something in you? I've been worried about..."); dialogues.push("There's something that's been bothering me. I trust you with this."); } } else if (topic === "bestFriend") { if (v.mentalTraits.includes("Emotional") || v.mentalTraits.includes("Sentimental")) { dialogues.push("You know you're my best friend, right? I... I don't know what I'd do without you."); } else if (v.mentalTraits.includes("Playful")) { dialogues.push("You know you're stuck with me forever, right? Best friends for life!"); } else { dialogues.push("You're my best friend. I just wanted you to know that."); dialogues.push("I'm so glad we're this close. You mean the world to me."); } } else if (topic === "tease") { if (v.mentalTraits.includes("Playful") || v.mentalTraits.includes("Mischievous")) { dialogues.push("*grins* Sooo... did you forget how to use a mirror this morning, or...?"); dialogues.push("Hey, I'm just saying... you're kinda dorky. In the best way, obviously!"); } else if (v.mentalTraits.includes("Sarcastic")) { dialogues.push("Oh, you're SO impressive. Really. Truly. *barely conceals smirk*"); } else { dialogues.push("*smiles* I'm just teasing you! Don't take it too seriously!"); dialogues.push("I have to give you a hard time. It's too easy!"); } } else if (topic === "challenge") { if (v.mentalTraits.includes("Argumentative") || v.mentalTraits.includes("Confrontational")) { dialogues.push("I don't think you're right about that. Let me tell you why..."); dialogues.push("Actually, I completely disagree. Here's my counter-argument..."); } else if (v.mentalTraits.includes("Bold") || v.mentalTraits.includes("Confident")) { dialogues.push("I'm going to push back on that. I don't think you're seeing the full picture."); } else { dialogues.push("I'm not sure I agree with that. What if we looked at it this way?"); dialogues.push("Can I challenge that idea? I see it differently."); } } else if (topic === "pushBoundaries") { if (v.mentalTraits.includes("Bold") || v.mentalTraits.includes("Daring")) { dialogues.push("Let's take this further... I want to push past the usual limits."); dialogues.push("I'm feeling adventurous. Want to see how far we can take this?"); } else if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Seductive")) { dialogues.push("*moves closer* I think we should... explore some new territory..."); dialogues.push("*intense gaze* I want more. Don't you?"); } else { dialogues.push("I think we should take this further. What do you think?"); dialogues.push("I'm ready for more if you are..."); } } /* === Shared Trait Options (Phase 2B) === */ else if (topic === "geekOut") { if (v.mentalTraits.includes("Intellectual")) { dialogues.push("Okay, hear me out — what if parallel universes are just different save files?"); dialogues.push("I've been reading about quantum computing and it's absolutely wild."); } else if (v.mentalTraits.includes("Creative")) { dialogues.push("Have you seen the latest indie games? The art direction is incredible."); dialogues.push("I had this idea for a story — want me to bounce it off you?"); } else { dialogues.push("Okay, nerd talk — what's your current obsession?"); dialogues.push("So I found this really cool thing online and I HAVE to tell someone."); dialogues.push("Quick — favorite sci-fi franchise. Go!"); } } else if (topic === "workoutTalk") { if (v.mentalTraits.includes("Competitive")) { dialogues.push("Bet I can out-rep you on bench. What do you say?"); dialogues.push("We should hit the gym sometime. I'll show you my routine."); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("Been crushing my PRs lately. You lifting?"); dialogues.push("Nothing beats that post-workout high, am I right?"); } else { dialogues.push("What's your workout routine like? I'm always looking for new ideas."); dialogues.push("Do you prefer cardio or weights? I'm a gym rat for sure."); dialogues.push("We should work out sometime! Spot each other."); } } else if (topic === "fashionBond") { if (v.mentalTraits.includes("Vain") || v.mentalTraits.includes("Stylish")) { dialogues.push("Your outfit is giving EVERYTHING right now. Where did you get that?"); dialogues.push("We need a shopping trip. Your style is almost as good as mine."); } else { dialogues.push("I love your look! You always put yourself together so well."); dialogues.push("Have you been keeping up with the latest trends? Some of them are wild."); dialogues.push("We should go shopping together sometime. I bet we'd have fun."); } } else if (topic === "darkHumor") { if (v.mentalTraits.includes("Sarcastic")) { dialogues.push("You know what's funny? Everything, if you're cynical enough."); dialogues.push("Life is a comedy for those who think and a tragedy for those who feel. I choose comedy."); } else if (v.mentalTraits.includes("Pessimistic")) { dialogues.push("At least we can laugh about how terrible everything is, right?"); dialogues.push("The world's on fire but at least the memes are good."); } else { dialogues.push("Want to hear something morbidly hilarious?"); dialogues.push("I've got the darkest joke. You ready?"); dialogues.push("Sometimes you just gotta laugh at the void, you know?"); } } else if (topic === "flirtPlayfully") { if (v.mentalTraits.includes("Seductive")) { dialogues.push("*slow smile* You know, you and me? We've got this... energy."); dialogues.push("*leans in* I can never tell if we're flirting or just being us."); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("Alright, let's be real — you and I both know there's something here."); dialogues.push("I like how easy it is with you. No pretending."); } else { dialogues.push("*playful grin* So... are we going to keep pretending we're not flirting?"); dialogues.push("You make it way too easy being charming, you know that?"); dialogues.push("*winks* I think we both know what's going on here."); } } /* === Mood-Gated Options (Phase 2B) === */ else if (topic === "askWhatsWrong") { if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Empathetic")) { dialogues.push("Hey... you don't seem like yourself. Want to talk about it?"); dialogues.push("I can tell something's off. I'm here if you need me, okay?"); } else if (v.mentalTraits.includes("Dominant") || v.mentalTraits.includes("Assertive")) { dialogues.push("Something's bothering you. Tell me what's going on."); dialogues.push("You look like you're carrying the weight of the world. Spill it."); } else { dialogues.push("Hey, are you doing okay? You seem a little down."); dialogues.push("What's wrong? You don't look like your usual self."); dialogues.push("I noticed you seem a bit off. Everything alright?"); } } else if (topic === "matchEnergy") { if (v.mentalTraits.includes("Playful") || v.mentalTraits.includes("Energetic")) { dialogues.push("YES! I love this energy! What are we hyped about?!"); dialogues.push("Your vibe is contagious — I'm getting pumped just being near you!"); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("I can feel the good vibes! What's got you so fired up?"); dialogues.push("That energy is incredible — let's ride this wave!"); } else { dialogues.push("You seem really happy! It's making me smile just seeing you like this."); dialogues.push("Wow, you're practically glowing! What's the good news?"); dialogues.push("I want whatever you're having — that excitement is infectious!"); } } else if (topic === "calmDown") { if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Patient")) { dialogues.push("Hey, take a breath. I'm here. Whatever it is, we'll figure it out."); dialogues.push("It's okay. Just breathe. You don't have to deal with this alone."); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Assertive")) { dialogues.push("I get that you're upset, but let's not let it ruin the day. Deep breath."); dialogues.push("Hey — look at me. It's going to be fine. Let's talk through it."); } else { dialogues.push("Whoa, easy there. Want to talk about what's got you so worked up?"); dialogues.push("I can see you're frustrated. Let me help if I can."); dialogues.push("Let's take it easy for a second. What happened?"); } } /* --- MEMORY-GATED TOPICS --- */ else if (topic === "reminisce") { if (v.mentalTraits.includes("Sentimental") || v.mentalTraits.includes("Romantic")) { dialogues.push("You know what I was just thinking about? The day we first met. Feels like forever ago."); dialogues.push("I keep thinking back on when we first started talking. We've come a long way, huh?"); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Bold")) { dialogues.push("Hey, remember when we first met? I knew right away we'd end up being close."); dialogues.push("We've known each other for a while now. Wild how far we've come since day one."); } else { dialogues.push("Do you remember when we first started talking? It feels like ages ago."); dialogues.push("I was just thinking about when we first met. A lot has changed since then, right?"); dialogues.push("How long have we known each other now? Feels like it's been a while."); } } else if (topic === "insideJoke") { if (v.mentalTraits.includes("Humorous") || v.mentalTraits.includes("Witty")) { dialogues.push("Okay okay okay — you know what I'm about to say, right? *barely holding it together*"); dialogues.push("Don't even look at me like that, you KNOW what I'm thinking about right now."); } else if (v.mentalTraits.includes("Playful") || v.mentalTraits.includes("Mischievous")) { dialogues.push("*trying not to laugh* You're thinking what I'm thinking, right?"); dialogues.push("Hey... *nudges* ...you remember THAT thing? *grins*"); } else { dialogues.push("*starts laughing* Sorry, I just — I just thought of our thing."); dialogues.push("Remember that thing only we get? *trying not to crack up*"); dialogues.push("No one else would get this, but... *starts grinning*"); } } else if (topic === "apologize") { if (v.mentalTraits.includes("Humble") || v.mentalTraits.includes("Kind")) { dialogues.push("Listen, I owe you an apology. I've said some things I shouldn't have, and I'm sorry."); dialogues.push("I haven't been fair with how I've treated you. I want you to know I'm genuinely sorry."); } else if (v.mentalTraits.includes("Proud") || v.mentalTraits.includes("Stubborn")) { dialogues.push("Look... this isn't easy for me. But I was wrong. I shouldn't have been so harsh."); dialogues.push("I'm not great at this, but... I'm sorry. For real. I messed up."); } else { dialogues.push("Hey, I wanted to say sorry for being a jerk sometimes. I didn't mean all of that."); dialogues.push("I owe you an apology. I haven't always been nice, and you didn't deserve that."); dialogues.push("Can we talk? I feel bad about some things I've said. I want to make it right."); } } else if (topic === "thankGifts") { if (v.mentalTraits.includes("Warm") || v.mentalTraits.includes("Grateful")) { dialogues.push("I just wanted to say — all those gifts you've accepted from me? It really means a lot."); dialogues.push("You never make me feel weird about giving you stuff. That means the world."); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("Um, so... I know I give you stuff a lot. Thanks for never making it weird."); dialogues.push("I hope you don't think I'm trying too hard with all the gifts. I just like making you smile."); } else { dialogues.push("Hey, thanks for always accepting my gifts. I know it's kind of my thing at this point."); dialogues.push("You're always so gracious when I give you things. I appreciate that."); dialogues.push("I really enjoy picking out gifts for you. Thanks for always being cool about it."); } } else if (topic === "noticedChange") { if (v.mentalTraits.includes("Perceptive") || v.mentalTraits.includes("Observant")) { dialogues.push("I've been watching you lately... something has shifted. You seem different, in a way I can't quite pin down."); dialogues.push("Call me perceptive, but something about you has changed. I noticed it right away."); } else if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Warm") || v.mentalTraits.includes("Empathetic")) { dialogues.push("Hey, I noticed you've been a little different lately. In a good way, I think."); dialogues.push("Something about you feels different. I noticed, and I think it's great."); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Bold")) { dialogues.push("Something about you has changed. I can tell."); dialogues.push("You're different lately. Don't try and deny it — I can see it plain as day."); } else { dialogues.push("Have you changed recently? Something feels different about you."); dialogues.push("I don't know what it is, but something about you seems... different. In a good way."); dialogues.push("Maybe I'm imagining things, but you seem like you've been changing lately."); } } /* --- NPC SOCIAL TOPICS (Phase 7) --- */ else if (topic === "askAboutNPC") { var targetName = v.socialTarget || "them"; if (v.mentalTraits.includes("Gossipy") || v.mentalTraits.includes("Social")) { dialogues.push("So what's the deal with " + targetName + "? I've been dying for the scoop."); dialogues.push("Okay, give me the dirt on " + targetName + ". What are they really like?"); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("Um... what do you think of " + targetName + "? Just curious..."); dialogues.push("I was wondering... do you know " + targetName + " well? What are they like?"); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Direct")) { dialogues.push("Give me the rundown on " + targetName + ". What's your honest opinion?"); dialogues.push("What's " + targetName + " really like? Don't sugarcoat it."); } else { dialogues.push("So what do you think of " + targetName + "? I'm curious."); dialogues.push("Hey, do you know " + targetName + "? What are they like?"); dialogues.push("I've been wondering about " + targetName + ". What's your take on them?"); } } else if (topic === "positiveGossip") { var targetName = v.socialTarget || "them"; if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Diplomatic")) { dialogues.push("You know " + targetName + "? They're actually really great. You should give them a chance."); dialogues.push("I wanted you to know — " + targetName + " said some really nice things about you."); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Charming")) { dialogues.push("Trust me on this — " + targetName + " is good people. You'd like them."); dialogues.push("Between us? " + targetName + " is solid. One of the best around here."); } else { dialogues.push("Hey, I think " + targetName + " is pretty cool. Have you two ever hung out?"); dialogues.push("I've gotten the impression that " + targetName + " is a really good person."); dialogues.push("Just thought you should know — " + targetName + " seems like a genuine person."); } } else if (topic === "negativeGossip") { var targetName = v.socialTarget || "them"; if (v.mentalTraits.includes("Sly") || v.mentalTraits.includes("Manipulative")) { dialogues.push("Between you and me... " + targetName + " was saying some not-so-nice things lately. Just thought you should know."); dialogues.push("I shouldn't be telling you this, but... " + targetName + " has been talking behind people's backs."); } else if (v.mentalTraits.includes("Gossipy") || v.mentalTraits.includes("Outgoing")) { dialogues.push("Okay don't tell anyone I said this, but " + targetName + "? Kind of a jerk, honestly."); dialogues.push("Have you noticed how " + targetName + " acts? I'm not the only one who thinks it's weird, right?"); } else { dialogues.push("I don't usually say stuff like this, but... " + targetName + " has been rubbing me the wrong way."); dialogues.push("Look, I'm not trying to start drama, but " + targetName + "... they're not who you think they are."); dialogues.push("I hate being like this, but... I think you should watch out for " + targetName + "."); } } else if (topic === "introduceNPCs") { var targetName = v.socialTarget || "someone"; if (v.mentalTraits.includes("Social") || v.mentalTraits.includes("Outgoing")) { dialogues.push("Hey, you should totally meet " + targetName + "! I think you two would really hit it off."); dialogues.push("I know someone you'd love — " + targetName + "! You're gonna thank me for this."); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("Um, this might sound random, but... have you ever met " + targetName + "? I think you'd get along."); dialogues.push("I was thinking... maybe you and " + targetName + " should hang out sometime? Just an idea..."); } else { dialogues.push("There's someone I think you'd get along with — " + targetName + ". Want me to arrange something?"); dialogues.push("You know who you'd vibe with? " + targetName + ". You two should meet."); dialogues.push("I think you and " + targetName + " would really click. You should give it a shot."); } } else if (topic === "takeSides") { var targetName = v.socialTarget || "them"; if (v.mentalTraits.includes("Loyal") || v.mentalTraits.includes("Supportive")) { dialogues.push("I think you're right about " + targetName + ". They were out of line."); dialogues.push("I've got your back on this. What " + targetName + " did wasn't cool."); } else if (v.mentalTraits.includes("Dominant") || v.mentalTraits.includes("Aggressive")) { dialogues.push("You know what? Forget " + targetName + ". They don't deserve your time."); dialogues.push("I'm on your side. If " + targetName + " has a problem with that, they can deal with me."); } else { dialogues.push("For what it's worth, I think you're in the right here. " + targetName + " was wrong."); dialogues.push("I just want you to know — I believe your side of things when it comes to " + targetName + "."); dialogues.push("I've been thinking about your situation with " + targetName + ", and honestly? You're justified."); } } else if (topic === "mendRelationship") { var targetName = v.socialTarget || "them"; if (v.mentalTraits.includes("Diplomatic") || v.mentalTraits.includes("Empathetic")) { dialogues.push("Have you considered giving " + targetName + " another chance? Maybe things aren't as bad as they seem."); dialogues.push("I know things are rough between you and " + targetName + ", but I think there's still hope."); } else if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Warm")) { dialogues.push("Life's short, you know? Maybe it's worth patching things up with " + targetName + "."); dialogues.push("I care about both of you. It hurts seeing you and " + targetName + " like this."); } else { dialogues.push("Look, I know you and " + targetName + " have issues, but maybe you could talk it out?"); dialogues.push("What if you gave " + targetName + " one more chance? People can surprise you."); dialogues.push("Have you thought about making up with " + targetName + "? Holding grudges is exhausting."); } } else if (topic === "romanticNudge") { var targetName = v.socialTarget || "them"; if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Romantic")) { dialogues.push("Don't you think " + targetName + " is kind of cute? I've seen how they look at you..."); dialogues.push("Okay, hear me out — you and " + targetName + "? I'm getting major sparks vibes."); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("This is embarrassing but... do you ever think about " + targetName + " like... you know... romantically?"); dialogues.push("Please don't make this weird, but... I think " + targetName + " might be into you..."); } else { dialogues.push("I've been thinking... you and " + targetName + " would make a great couple."); dialogues.push("Has anyone ever told you that you and " + targetName + " would be cute together?"); dialogues.push("Just putting it out there — " + targetName + " seems like your type."); } } /* --- ROMANCE TOPICS (Phase 9) --- */ else if (topic === "confessFeelings") { if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Bold")) { dialogues.push("Look, I'm just gonna say it — I have feelings for you. Real ones."); dialogues.push("I'm not great at dancing around things, so... I like you. More than a friend."); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("*takes a deep breath* I... this is really hard for me, but... I think I have feelings for you."); dialogues.push("*fidgets nervously* So, um... I've been wanting... I mean, I like you. Like, really like you."); } else if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Romantic")) { dialogues.push("*smiles softly* I think you already know, but... I want us as more than friends."); dialogues.push("Every time we hang out, I catch myself wishing it was a date. So... can it be?"); } else { dialogues.push("I've been thinking a lot about us, and... I think I have feelings for you."); dialogues.push("This might change things between us, but I need you knowing — I like you as more than a friend."); dialogues.push("I've been wanting this for a while now... I have feelings for you."); } } else if (topic === "holdHands") { if (v.mentalTraits.includes("Romantic") || v.mentalTraits.includes("Warm")) { dialogues.push("*gently reaches for their hand, intertwining fingers*"); dialogues.push("*softly takes their hand and gives it a squeeze*"); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("*nervously brushes their hand with trembling fingers*"); dialogues.push("*hesitantly reaches over, barely touching their fingers*"); } else { dialogues.push("*casually takes their hand while walking*"); dialogues.push("*reaches over and wraps their hand around yours*"); } } else if (topic === "kissNPC") { if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Bold")) { dialogues.push("*leans in close, eyes locked on their lips* Come here..."); dialogues.push("*cups their face and pulls them into a kiss*"); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("*leans forward slowly, heart pounding, and presses a gentle kiss against their lips*"); dialogues.push("*blushes deeply* Can I... *kisses them softly before finishing the sentence*"); } else if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Seductive")) { dialogues.push("*bites lip playfully before leaning in for a slow, deliberate kiss*"); dialogues.push("*traces a finger along their jawline before pulling them into a kiss*"); } else { dialogues.push("*leans in and kisses them softly*"); dialogues.push("*moves closer and presses a warm kiss against their lips*"); } } else if (topic === "romanticDate") { if (v.mentalTraits.includes("Romantic") || v.mentalTraits.includes("Charming")) { dialogues.push("I know this great spot — just the two of us. What do you say?"); dialogues.push("I've been planning something special for us. Wanna go somewhere nice?"); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("Would you maybe... want hanging out? Just us? Like a... date?"); dialogues.push("*fidgets* I thought maybe we could go somewhere together... if you want?"); } else { dialogues.push("Hey, wanna go do something fun together? Just us."); dialogues.push("I'm in the mood for a date. You down?"); dialogues.push("We should go somewhere together. What do you think?"); } } else if (topic === "askExclusive") { if (v.mentalTraits.includes("Confident")) { dialogues.push("I don't want anyone else. I want this — us — exclusively. What do you say?"); dialogues.push("I'm all in on us. Are you? I want us being exclusive."); } else if (v.mentalTraits.includes("Romantic")) { dialogues.push("Being with you feels right. I want us being just ours — nobody else. Will you be mine?"); dialogues.push("*takes both their hands* I want this — just you and me. Exclusively."); } else { dialogues.push("I've been thinking... I want us being exclusive. Just you and me."); dialogues.push("So, I really like where this is going. And I want it being just us. What do you think?"); } } else if (topic === "makeOutNPC") { if (v.mentalTraits.includes("Dominant")) { dialogues.push("*pulls them close by the waist* Come here. I want you."); dialogues.push("*pushes them gently against the wall and kisses them deeply*"); } else if (v.mentalTraits.includes("Seductive") || v.mentalTraits.includes("Flirty")) { dialogues.push("*runs fingers through their hair and pulls them into a deep, lingering kiss*"); dialogues.push("*whispers against their lips* I can't get enough of you..."); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("*heart racing, leans in and lets the kiss deepen, hands trembling slightly*"); } else { dialogues.push("*pulls them closer, deepening the kiss, hands exploring*"); dialogues.push("*wraps arms around them and kisses them hungrily*"); } } else if (topic === "initiateIntimacy") { if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Dominant")) { dialogues.push("*voice low, intense* I want you. Right now. Let's go somewhere private."); dialogues.push("*pulls them close, breath hot against their ear* I need you..."); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("*blushing deeply, barely above a whisper* I... want being closer... with you. Can we...?"); dialogues.push("*nervous but determined* I want us... I mean... would you want going somewhere more private?"); } else if (v.mentalTraits.includes("Romantic")) { dialogues.push("*gazes into their eyes* I want all of you tonight. Every part."); dialogues.push("*brushes hair from their face* I want being with you... completely."); } else { dialogues.push("Hey... wanna take this somewhere more private?"); dialogues.push("*smiles* I think we both know where this is heading... let's go."); } } else if (topic === "pillowTalk") { if (v.mentalTraits.includes("Romantic") || v.mentalTraits.includes("Empathetic")) { dialogues.push("*lying close together* What are we, really? What does this mean for you?"); dialogues.push("I love these moments — just us, nothing else. Tell me what you're thinking."); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("So... what do you like? I wanna know what drives you wild."); dialogues.push("Tell me what you want from us. I can handle the truth."); } else { dialogues.push("*nestled close* So... what do you enjoy most when we're together like this?"); dialogues.push("I want knowing what makes you happy. What do you like?"); } } else if (topic === "deeperBond") { if (v.mentalTraits.includes("Romantic")) { dialogues.push("You're my person. I've never felt this way about anyone. I want us being forever."); dialogues.push("*takes their hands, eyes shining* This... us... it's everything. I want the deepest bond possible with you."); } else if (v.mentalTraits.includes("Confident")) { dialogues.push("I'm not afraid of saying it — you're it for me. I want something deeper. Permanent."); } else { dialogues.push("I can't imagine my life without you anymore. I want us going deeper — soulmates, if you'll have me."); dialogues.push("What we have... it's the most important thing in my life. I want us being everything."); } } else if (topic === "endThings") { if (v.mentalTraits.includes("Kind") || v.mentalTraits.includes("Empathetic")) { dialogues.push("*looks down* This is really hard for me... but I think we need ending things between us. I'm sorry."); dialogues.push("I care about you so much, and that's why this hurts. But... I think we should go back being friends."); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Direct")) { dialogues.push("I need being honest with you — this isn't working for me anymore. I think we should end it."); } else { dialogues.push("I've been thinking a lot... and I think we should stop seeing each other like this."); dialogues.push("This is hard saying, but... I think it's best if we go back being just friends."); } } else if (topic === "inviteHomeFriend") { if (v.mentalTraits.includes("Outgoing") || v.mentalTraits.includes("Social Butterfly")) { dialogues.push("Hey! Want a come over and hang at my place? I've got snacks and zero plans."); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Introverted")) { dialogues.push("*fidgets* I was thinking... maybe you could come by my place? If you want. No pressure."); } else { dialogues.push("Want a come hang out at my place for a bit? Could be fun."); dialogues.push("Hey, I've got some free time — want a come over and just chill?"); dialogues.push("My place is pretty nice. Want a come see it?"); } } else if (topic === "inviteHomeRomantic") { if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Bold")) { dialogues.push("*smiles suggestively* Come back with me. I want you all for myself."); dialogues.push("My place. You and me. Right now."); } else if (v.mentalTraits.includes("Shy")) { dialogues.push("*blushing* Would you... want a come over? For, um... privacy?"); } else if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Seductive")) { dialogues.push("*traces a finger along their arm* Why don't we take this somewhere more... private?"); } else { dialogues.push("Want a come back with me? We could have some... privacy."); dialogues.push("I was thinking we could head back for my place. Just the two of us."); } } else if (topic === "whatsNew") { if (v.mentalTraits.includes("Outgoing") || v.mentalTraits.includes("Talkative")) { dialogues.push("So! What's been going on with you? Anything exciting happen? Tell me everything!"); dialogues.push("What's new?! Catch me up! I want to hear all about it!"); } else if (v.mentalTraits.includes("Shy") || v.mentalTraits.includes("Awkward")) { dialogues.push("So, um... anything new going on with you? ...If you want to share, that is."); dialogues.push("I was wondering... has anything interesting happened to you lately?"); } else if (v.mentalTraits.includes("Flirty") || v.mentalTraits.includes("Seductive")) { dialogues.push("So~ what's been keeping you busy? Besides looking that good, I mean."); dialogues.push("Tell me something new about yourself. I'm all ears... and eyes~"); } else if (v.mentalTraits.includes("Confident") || v.mentalTraits.includes("Bold")) { dialogues.push("What's new with you? Hit me with it."); dialogues.push("So, anything interesting happening in your life? Let's hear it."); } else { dialogues.push("What's new with you? Anything interesting happening?"); dialogues.push("So, what's been going on lately? Anything exciting?"); dialogues.push("Hey, what's new? I feel like we haven't really caught up."); } } /* Default fallback */ if (dialogues.length === 0) { dialogues.push("..."); } return dialogues[Math.floor(Math.random() * dialogues.length)]; }>> /* ====================================================================== */ /* ROISIN POSSESSION VOICE */ /* When the player is bound to the Sunfish Artifact, route a curated set */ /* of common topics through Roisin's Gaelic voice instead of the */ /* trait-derived player voice. */ /* ====================================================================== */ <<set setup.roisinPossessionVoice = { compliment: [ "Aye, you wear that well. Tell me you know it.", "Christ, look at you. Stop pretending you don't know.", "You're easy on the eye today. I am just saying.", "Mm. There you are, looking good as always." ], smalltalk: [ "Aye, what's the news with you?", "Tell me something good. I have time.", "How's your day been? Honestly.", "Right then. Talk to me." ], flirt: [ "Don't make me work for it. You know I can. I just don't want to.", "If you're going to look at me like that, do it properly.", "Careful. I bite when I'm bored.", "You're trouble. I like trouble." ], job: [ "Tell me about the work, then. What's keeping you busy?", "What is it you actually do all day?", "Out with it. The job. What's the worst bit?" ], trading: [ "What are you offering? Don't waste my time with rubbish.", "Show me what you've got. I'll tell you if it's worth a swap.", "Right. Lay it out." ], opinion: [ "Out with it. What do you make of me?", "Go on. Tell me. I can take it.", "Honest answer. What am I to you?" ], fitness: [ "You lift? Good. Tell me what you're hitting these days.", "Anyone who skips leg day is wasting my time.", "Best lift of the week. Go." ], advice: [ "What's chewing on you? Out with it.", "Tell me the problem. I'll give you the answer plain.", "Right. Lay it out and I'll tell you what I think." ], secrets: [ "Tell me. I keep secrets like a vault.", "Drop it on me. Goes nowhere.", "Whatever you've got, it's safe here." ], confide: [ "Right. Drop it. I'll keep it under my hat.", "You can tell me. I keep it close.", "Lean in. I'm listening." ], deep: [ "Talk to me. The deep stuff. I'm not afraid of it.", "Go on, then. Say what you're really thinking.", "Skip the small talk. The real thing." ], bestFriend: [ "Aye. Out with it. The whole of it.", "You and me. Talk to me like that.", "Right. Say the part you don't say to anyone else." ], tease: [ "You're cute when you're flustered. Keep going.", "Oh that's a face. Tell me what you're thinking.", "Don't look away. I caught it." ], challenge: [ "You think you can take me? Try.", "Go on. Push back. I love a fight.", "Prove it. I'll wait." ], workoutTalk: [ "Best lifts of the week. Go.", "Don't tell me you're skipping leg day. I'll know.", "What's your push day looking like?" ], askAboutNPC: [ "What's the word on someone? I want the real version.", "Tell me about a person. The honest read." ], positiveGossip: [ "Heard something good about a person. Want it?", "Got a nice bit of word. Lean in." ], negativeGossip: [ "There's some talk going round. Lean in.", "You hear what they did? Aye. Sit down." ], reminisce: [ "Remember that night? Tell me you remember.", "Aye, those were good days. Or were they?" ], apologize: [ "Right. I was out of line. I'll own it.", "That was my fault. I'm sorry." ], askWhatsWrong: [ "You're off today. Talk to me.", "Right. What's eating you?" ], matchEnergy: [ "Aye. Right there with you.", "Going to match you beat for beat." ], insult: [ "Don't test me. I will end you with a sentence.", "You're lucky I'm in a good mood. Move along." ] }>> /* Wrap setup.getPlayerDialogue so possession routes through Roisin's voice. */ <<set setup.roisinOriginalGetPlayerDialogue = setup.getPlayerDialogue>> <<set setup.getPlayerDialogue = function(topic) { var v = State.variables; if (v.possessionActive && setup.roisinPossessionVoice && setup.roisinPossessionVoice[topic]) { var pool = setup.roisinPossessionVoice[topic]; return pool[Math.floor(Math.random() * pool.length)]; } return setup.roisinOriginalGetPlayerDialogue(topic); }>> /* ---------------------------------- */ /* --- PLAYER TRAIT SPECIAL OPTIONS --- */ /* ---------------------------------- */ /* Get special dialogue options available based on player traits */ <<set setup.getPlayerTraitDialogueOptions = function(npc, context) { var v = State.variables; var options = []; var mentalTraits = v.mentalTraits || []; var physicalTraits = v.physicalTraits || []; /* Confident trait: Assert dominance option */ if (mentalTraits.includes("Confident")) { options.push({ id: "assert_dominance", label: "Assert Dominance", trait: "Confident", description: "Use your confidence to take charge of the conversation", effect: function() { return { relationshipChange: 3, npcResponse: "impressed" }; } }); } /* Flirty + Attractive: Special flirtation options */ if (mentalTraits.includes("Flirty") && physicalTraits.includes("Attractive")) { options.push({ id: "seductive_approach", label: "Seductive Approach", trait: "Flirty + Attractive", description: "Use your looks and charm to flirt boldly", effect: function() { return { relationshipChange: 5, npcResponse: "flustered" }; } }); } /* Intelligent: Analyze option to gain insights */ if (mentalTraits.includes("Intelligent")) { options.push({ id: "analyze", label: "Analyze", trait: "Intelligent", description: "Study the NPC to learn more about them", effect: function() { return { gainInsight: true, npcResponse: "noticed" }; } }); } /* Intimidating or Strong or Muscular: Intimidation option */ if (mentalTraits.includes("Intimidating") || physicalTraits.includes("Muscular") || physicalTraits.includes("Strong")) { options.push({ id: "intimidate", label: "Intimidate", trait: physicalTraits.includes("Muscular") ? "Muscular" : "Intimidating", description: "Use your presence to pressure the NPC", effect: function() { return { relationshipChange: -2, npcResponse: "fearful", complianceBonus: true }; } }); } /* Empathetic: Console option when NPC is upset */ if (mentalTraits.includes("Empathetic") || mentalTraits.includes("Kind")) { options.push({ id: "console", label: "Console", trait: mentalTraits.includes("Empathetic") ? "Empathetic" : "Kind", description: "Offer emotional support and comfort", effect: function() { return { relationshipChange: 4, npcResponse: "grateful" }; } }); } /* Bimbo: Unique ditzy dialogue options */ if (mentalTraits.includes("Bimbo")) { options.push({ id: "ditzy_charm", label: "Ditzy Charm", trait: "Bimbo", description: "Use your airheaded charm to disarm them", effect: function() { return { relationshipChange: 2, npcResponse: "amused" }; } }); } /* Manipulative: Manipulation option */ if (mentalTraits.includes("Manipulative") || mentalTraits.includes("Deceitful")) { options.push({ id: "manipulate", label: "Manipulate", trait: "Manipulative", description: "Subtly guide the conversation to your advantage", effect: function() { return { relationshipChange: 0, npcResponse: "manipulated", advantageGained: true }; } }); } /* Charming: Smooth talk option */ if (mentalTraits.includes("Charming")) { options.push({ id: "smooth_talk", label: "Smooth Talk", trait: "Charming", description: "Use your natural charm to win them over", effect: function() { return { relationshipChange: 4, npcResponse: "charmed" }; } }); } /* Ojou: Decree option — speak as though you expect to be obeyed */ if (physicalTraits.includes("Ojou")) { options.push({ id: "ojou_decree", label: "Decree", trait: "Ojou", description: "Speak with the calm certainty of someone used to being obeyed", effect: function() { return { relationshipChange: 3, npcResponse: "deferential" }; } }); } /* Dominant: Take control option */ if (mentalTraits.includes("Dominant")) { options.push({ id: "take_control", label: "Take Control", trait: "Dominant", description: "Assert your authority over the situation", effect: function() { return { relationshipChange: 2, npcResponse: "submitting" }; } }); } /* Submissive: Defer option */ if (mentalTraits.includes("Submissive")) { options.push({ id: "defer", label: "Defer", trait: "Submissive", description: "Show deference and let them lead", effect: function() { return { relationshipChange: 2, npcResponse: "pleased" }; } }); } return options; }>> /* Check if player has any special dialogue options available */ <<set setup.hasSpecialDialogueOptions = function(npc, context) { var options = setup.getPlayerTraitDialogueOptions(npc, context); return options.length > 0; }>> /* Execute a special dialogue option and return the result */ <<set setup.executeSpecialDialogueOption = function(optionId, npc) { var v = State.variables; var options = setup.getPlayerTraitDialogueOptions(npc, "talk"); for (var i = 0; i < options.length; i++) { if (options[i].id === optionId) { var result = options[i].effect(); /* Apply relationship change */ if (result.relationshipChange && result.relationshipChange !== 0) { setup.addRelationshipPoints(npc.name, result.relationshipChange); } return { success: true, option: options[i], result: result }; } } return { success: false }; }>>
/* ---------------------------------- */ /* --- PLAYER IMAGE GENERATION --- */ /* ---------------------------------- */ <<set setup.getPlayerFaceImage = function() { var v = State.variables; /* Initialize imageSettings if it doesn't exist */ if (!v.imageSettings) { v.imageSettings = { imagesEnabled: true, locationImagesEnabled: true, customImages: { face: "", chest: "", butt: "" } }; } /* Ensure locationImagesEnabled exists for backwards compatibility */ if (v.imageSettings.locationImagesEnabled === undefined) { v.imageSettings.locationImagesEnabled = true; } /* If images are disabled, return custom image or empty string */ if (!v.imageSettings.imagesEnabled) { return v.imageSettings.customImages.face || ""; } /* SUNFISH ARTIFACT POSSESSION PORTRAIT OVERRIDE */ /* While possessing Roisin, the player wears her face. Use her */ /* static portrait so sidebar and body screens show her image. */ if (v.possessionActive && v.lifeSwapPortraitSource === "Roisin Sullivan") { return "Images/NPCs/StaticNPCs/Roisin_Sullivan.webp"; } /* In Clair form, the player wears Clair's face (her portrait). */ if (v.clairFormActive && v.lifeSwapPortraitSource === "Clair") { return "Images/Faces/Laboratory/Clair_Portrait.webp"; } /* OJOU PORTRAIT OVERRIDE: face portrait uses the Laboratory folder image even though the trait is not lab-obtained. (The full-body image at Images/Transformation/Ojou_*.webp is resolved separately by setup.getPlayerFullBodyImage.) */ if (v.physicalTraits && v.physicalTraits.indexOf("Ojou") !== -1) { var ojouIsMature = v.appearance && v.appearance.age === "Mature Adult"; return "Images/Faces/Laboratory/Ojou_" + (ojouIsMature ? "Mature" : "Adult") + ".webp"; } /* SLIME PORTRAIT OVERRIDE: slime girls use the single Laboratory slime face. */ if (v.physicalTraits && v.physicalTraits.indexOf("Slime") !== -1) { return "Images/Faces/Laboratory/Slime.webp"; } /* LABORATORY TRANSFORMATION PORTRAIT OVERRIDE */ /* Maps trait names to exact file names in Images/Faces/Laboratory/ */ var labTransformations = [ "Voluptuous Succubus", "Oni", "Succubus", "Imp", "Cerberus", "Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep", "Hucow", "Trophy Wife", "Ojou", "Gym Bunny", "E-Girl", "Punk", "Gyaru", "Siren", "Living Doll", "Dominatrix", "Slut", "Himbo", "Angel", "Naiad", "Automaton", "Banshee", "Cheshire Cat", "Cupid", "Dark Angel", "Honeybee", "Jinko", "Kakuen", "Lizardman", "Ocelomeh", "Pyrow", "Raiju", "Salamander", "Satyros", "Vampire", "Kitsune", "Anubis", "Pharaoh", "Witch", "Femboy", "Half-Dragon Gyaru" ]; /* Map trait names to exact file name prefixes (matching actual files in Laboratory folder) */ var traitToFilePrefix = { "Voluptuous Succubus": "Large_Succubus", "Oni": "Oni_Female", "Succubus": "Succubus_Female", "Imp": "imp", "Cerberus": "Cerberus", "Werecat": "female_werecat", "Werewolf": "female_werewolf", "Werebunny": "female_werebunny", "Werefox": "Werefox_Female", "Weresheep": "Weresheep_Female", "Hucow": "Hucow_Female", "Trophy Wife": "TrophyWife_Female", "Gym Bunny": "gymbunny", "E-Girl": "egirl", "Punk": "Punk_Female", "Gyaru": "Gyaru_Female", "Siren": "Siren_Female", "Living Doll": "LivingDoll_Female", "Dominatrix": "Dominatrix_Female", "Slut": "Slut_Female", "Himbo": "Himbo_Male", "Angel": "Angel_Female", "Naiad": "Naiad_Female", "Automaton": "Automaton_Female", "Banshee": "Banshee_Female", "Cheshire Cat": "CheshireCat_Female", "Cupid": "Cupid_Female", "Dark Angel": "DarkAngel_Female", "Honeybee": "Honeybee_Female", "Jinko": "Jinko_Female", "Kakuen": "Kakuen_Female", "Lizardman": "Lizardman_Female", "Ocelomeh": "Ocelomeh_Female", "Pyrow": "Pyrow_Female", "Raiju": "Raiju_Female", "Salamander": "Salamander_Female", "Satyros": "Satyros_Female", "Vampire": "Vampire_Female", "Kitsune": "Kitsune_Female", "Anubis": "Anubis_Female", "Pharaoh": "Pharaoh_Female", "Witch": "Witch", "Femboy": "Femboy_Portrait", "Half-Dragon Gyaru": "Dragon_Gyaru" }; /* Map age suffix format for each transformation (some use _Adult, some use _adult) */ var traitToAgeSuffix = { "Voluptuous Succubus": { adult: "", mature: "" }, "Oni": { adult: "", mature: "" }, "Succubus": { adult: "_Adult", mature: "_Mature" }, "Imp": { adult: "_adult", mature: "_mature" }, "Cerberus": { adult: "", mature: "_Mature" }, "Werecat": { adult: "_adult", mature: "_mature" }, "Werewolf": { adult: "_adult", mature: "_mature" }, "Werebunny": { adult: "_adult", mature: "_mature" }, "Werefox": { adult: "_Adult", mature: "_Mature" }, "Weresheep": { adult: "_Adult", mature: "_Mature" }, "Hucow": { adult: "_Adult", mature: "_Mature" }, "Trophy Wife": { adult: "_Adult", mature: "_Mature" }, "Ojou": { adult: "_Adult", mature: "_Mature" }, "Gym Bunny": { adult: "_adult", mature: "_mature" }, "E-Girl": { adult: "_adult", mature: "_mature" }, "Punk": { adult: "_Adult", mature: "_Mature" }, "Gyaru": { adult: "_Adult", mature: "_Mature" }, "Siren": { adult: "_Adult", mature: "_Mature" }, "Living Doll": { adult: "_Adult", mature: "_Mature" }, "Dominatrix": { adult: "_Adult", mature: "_Mature" }, "Slut": { adult: "_Adult", mature: "_Mature" }, "Himbo": { adult: "_Adult", mature: "_Mature" }, "Angel": { adult: "_Adult", mature: "_Mature" }, "Naiad": { adult: "_Adult", mature: "_Mature" }, "Automaton": { adult: "_Adult", mature: "_Mature" }, "Banshee": { adult: "_Adult", mature: "_Mature" }, "Cheshire Cat": { adult: "_Adult", mature: "_Mature" }, "Cupid": { adult: "_Adult", mature: "_Mature" }, "Dark Angel": { adult: "_Adult", mature: "_Mature" }, "Honeybee": { adult: "_Adult", mature: "_Mature" }, "Jinko": { adult: "_Adult", mature: "_Mature" }, "Kakuen": { adult: "_Adult", mature: "_Mature" }, "Lizardman": { adult: "_Adult", mature: "_Mature" }, "Ocelomeh": { adult: "_Adult", mature: "_Mature" }, "Pyrow": { adult: "_Adult", mature: "_Mature" }, "Raiju": { adult: "_Adult", mature: "_Mature" }, "Salamander": { adult: "_Adult", mature: "_Mature" }, "Satyros": { adult: "_Adult", mature: "_Mature" }, "Vampire": { adult: "_Adult", mature: "_Mature" }, "Kitsune": { adult: "_Adult", mature: "_Mature" }, "Anubis": { adult: "_Adult", mature: "_Mature" }, "Pharaoh": { adult: "_Adult", mature: "_Mature" }, "Witch": { adult: "", mature: "" }, "Femboy": { adult: "", mature: "" }, "Half-Dragon Gyaru": { adult: "", mature: "" } }; var physTraits = v.physicalTraits || []; var mentTraits = v.mentalTraits || []; var allTraits = physTraits.concat(mentTraits); for (var i = 0; i < labTransformations.length; i++) { var transform = labTransformations[i]; if (allTraits.includes(transform)) { /* Witch portrait toggle: if player chose default portrait, skip witch portrait */ if (transform === "Witch" && v.witchUseWitchPortrait === false) { continue; } var labIsMature = v.appearance.age === "Mature Adult"; var ageKey = labIsMature ? "mature" : "adult"; if (transform === "Kitsune" && ageKey === "adult") { var kitsuneAdultColors = { "Black": 1, "Blonde": 1, "Blue": 1, "Brown": 1, "Pink": 1, "Red": 1, "Silver": 1 }; var kitHair = (v.appearance && v.appearance.hairColor) || ""; var kitColor = kitsuneAdultColors[kitHair] ? kitHair : "Silver"; return "Images/Faces/Laboratory/Kitsune_Female_Adult_" + kitColor + ".webp"; } var filePrefix = traitToFilePrefix[transform]; var ageSuffix = traitToAgeSuffix[transform][ageKey]; return "Images/Faces/Laboratory/" + filePrefix + ageSuffix + ".webp"; } } /* BIMBO TRAIT OVERRIDE - Check this BEFORE standard image generation */ if (v.mentalTraits && v.mentalTraits.includes("Bimbo")) { var isMature = v.appearance.age === 'Mature Adult'; if (isMature) { return 'Images/Faces/Bimbo/Bimbom.webp'; } else { return 'Images/Faces/Bimbo/Bimboa.webp'; } } /* LIFE SWAP PORTRAIT OVERRIDE - If player has swapped with an NPC, use NPC's portrait */ /* Only applies if lifeSwapPortraitSource exists and is NOT "player" (original player) */ if (v.lifeSwapPortraitSource && v.lifeSwapPortraitSource !== "player") { /* Check if player has custom images from the swap (the NPC gave them theirs) */ if (v.imageSettings.customImages && v.imageSettings.customImages.face) { return v.imageSettings.customImages.face; } /* Otherwise use the NPC's portrait path based on player's CURRENT gender and age */ var formattedSource = v.lifeSwapPortraitSource.replace(/ /g, "_").replace(/\u0027/g, ""); /* Determine portrait variant based on current gender and age */ var currentGender = v.bodyParts && v.bodyParts.gender ? v.bodyParts.gender.toLowerCase() : "female"; var currentAge = v.appearance && v.appearance.age ? v.appearance.age : "Adult"; var isMature = (currentAge === "Mature Adult" || currentAge === "Mature"); var isFemboy = v.mentalTraits && v.mentalTraits.includes("Femboy"); var portraitVariant; if (currentGender === "male") { if (isFemboy) { portraitVariant = isMature ? "femboy_mature" : "femboy_adult"; } else { portraitVariant = isMature ? "male_mature" : "male_adult"; } } else { portraitVariant = isMature ? "female_mature" : "female_adult"; } if (setup.cafe && setup.cafe.isPlayerInMaidOutfit && setup.cafe.isPlayerInMaidOutfit()) { portraitVariant = "maid_" + portraitVariant; } return 'Images/NPCs/' + formattedSource + '/' + portraitVariant + '.webp'; } /* Get basic appearance info */ var gender = v.bodyParts.gender === "male" ? "Male" : "Female"; var hairStyle = ""; /* "messy" no longer maps to a dedicated image file; fall through to normal hair */ var hairLength = v.appearance.hairLength === "long" ? "Long" : "Short"; var skinTone = v.appearance.skinTone.charAt(0).toUpperCase() + v.appearance.skinTone.slice(1); var hairColorMap = { "Black": "Black", "Brown": "Brown", "Blonde": "Blonde", "Red": "Red", "Platinum Blonde": "Platinum" }; var hairColor = hairColorMap[v.appearance.hairColor] || v.appearance.hairColor; var age = v.appearance.age === "Mature Adult" ? "Mature" : "Adult"; /* Build filename */ var filename = gender + "_" + hairStyle + hairLength + "_" + skinTone + "_" + hairColor + "_" + age + ".webp"; /* Return standard path */ return "Images/Faces/" + filename; }>> /* ---------------------------------- */ /* --- CHEST IMAGE GENERATION --- */ /* ---------------------------------- */ <<set setup.getPlayerChestImage = function() { var v = State.variables; /* Initialize imageSettings if it doesn't exist */ if (!v.imageSettings) { v.imageSettings = { imagesEnabled: true, locationImagesEnabled: true, customImages: { face: "", chest: "", butt: "" } }; } /* If images are disabled, return custom image or empty string */ if (!v.imageSettings.imagesEnabled) { return v.imageSettings.customImages.chest || ""; } /* Otherwise return default image path */ var skinTone = v.appearance.skinTone.charAt(0).toUpperCase() + v.appearance.skinTone.slice(1); var chestSizeMap = { "flat masculine": "Masculine_Flat", "flat": "Flat", "small": "Small", "medium": "Medium", "large": "Big", "huge": "Huge", "giant": "Giant", "gigantic": "Gigantic" }; var chestSize = chestSizeMap[v.bodyParts.chest.toLowerCase()] || "Flat"; var filename = chestSize + "_" + skinTone + ".webp"; return "Images/Chests/" + filename; }>> /* ---------------------------------- */ /* --- BUTT IMAGE GENERATION --- */ /* ---------------------------------- */ <<set setup.getPlayerButtImage = function() { var v = State.variables; /* Initialize imageSettings if it doesn't exist */ if (!v.imageSettings) { v.imageSettings = { imagesEnabled: true, locationImagesEnabled: true, customImages: { face: "", chest: "", butt: "" } }; } /* If images are disabled, return custom image or empty string */ if (!v.imageSettings.imagesEnabled) { return v.imageSettings.customImages.butt || ""; } /* Otherwise return default image path */ var skinTone = v.appearance.skinTone.charAt(0).toUpperCase() + v.appearance.skinTone.slice(1); var buttSizeMap = { "flat masculine": "Masculine_Flat", "flat": "Flat", "small": "Small", "medium": "Medium", "large": "Big", "huge": "Huge", "giant": "Giant", "gigantic": "Gigantic" }; var buttSize = buttSizeMap[v.bodyParts.butt.toLowerCase()] || "Flat"; var filename = buttSize + "_" + skinTone + ".webp"; return "Images/Butts/" + filename; }>>
/* ======================================== TRANSFORMATION TEXT FUNCTIONS - COMPLETE Comprehensive descriptions for every size change Single result image per transformation 8 sizes for chest/butt (including flatmasculine) Age-based bimbo images ======================================== */ /* ---------------------------------- */ /* --- REQUIRED ARRAYS --- */ /* ---------------------------------- */ <<if !setup.chestSizeOrder>> <<set setup.chestSizeOrder = ["flatmasculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]>> <</if>> <<if !setup.buttSizeOrder>> <<set setup.buttSizeOrder = ["flatmasculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]>> <</if>> /* ---------------------------------- */ /* --- CHEST TRANSFORMATIONS --- */ /* ---------------------------------- */ <<set setup.getChestTransformationText = function(oldSize, newSize) { var imageHTML = ""; /* Safety check for undefined values */ if (!oldSize || !newSize) { return "Chest transformation cannot be processed - missing size information."; } if (!setup.chestSizeOrder) { setup.chestSizeOrder = ["flatmasculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]; } var oldS = oldSize.toLowerCase().replace(/\s+/g, ''); var newS = newSize.toLowerCase().replace(/\s+/g, ''); if (oldS === newS) { return "Your chest remains unchanged."; } /* Single result image - just the final size */ if (typeof $imageSettings !== "undefined" && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled) { var imagePath = "Images/PostSwap/Chest_" + newS + ".webp"; imageHTML = '<div style="text-align: center; margin: 20px 0;">'; imageHTML += '<img src="' + imagePath + '" style="max-width: 60%; border-radius: 10px; border: 2px solid #FF69B4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Chest Result">'; imageHTML += '</div>'; } /* Get the transformation key */ var key = oldS + "_to_" + newS; /* Define all transformation descriptions */ var transformations = { /* FROM FLAT MASCULINE */ "flatmasculine_to_flat": [ "Your chest tingles subtly as the masculine firmness softens slightly. The hard, muscular flatness gives way to a smoother, softer flatness—still without curves, but less aggressively masculine. The change is subtle but noticeable." ], "flatmasculine_to_small": [ "A warm tingling spreads across your chest as subtle swells begin to form. The hard masculine flatness softens as small, sensitive mounds push outward, creating the first hints of feminine curves. Your nipples harden as they adjust to their new prominence.", "You feel a pleasant warmth as your masculine chest begins to transform. Delicate flesh swells gently outward, forming small, pert breasts. The transformation from masculine flatness to modest femininity is gentle but unmistakable." ], "flatmasculine_to_medium": [ "Heat blooms across your chest as your masculine flatness transforms dramatically. Your breasts swell outward with steady pressure, expanding from hard muscle into full, rounded curves that fill your palms. The transformation from masculine to feminine leaves you breathless.", "You gasp as your masculine chest surges forward, hard muscle softening and swelling. Medium-sized breasts emerge with surprising weight, their soft curves bouncing gently with each breath. The transformation from flat masculinity to feminine fullness is profound." ], "flatmasculine_to_large": [ "Your masculine chest explodes outward with overwhelming sensation. The hard, flat muscle transforms rapidly into large, heavy breasts that surge into existence. Your back arches involuntarily as the substantial weight settles, nipples hardening atop the impressive mounds.", "An intense pressure builds in your masculine chest before releasing in a rush of feminizing growth. Your breasts swell dramatically, expanding from hard flatness to large, bouncing curves that demand attention. You moan as the weight becomes deliciously apparent." ], "flatmasculine_to_huge": [ "Overwhelming heat surges through your chest as your masculine flatness transforms extremely. Huge breasts explode outward, the hard muscle becoming enormous, heavy orbs that bounce and sway. The massive weight pulls at your shoulders, nipples thick and prominent.", "Your masculine chest erupts with sensation as a profound change overtakes you. Huge breasts swell into existence, expanding dramatically from flat hardness until they dominate your torso. You gasp and moan as the enormous weight settles." ], "flatmasculine_to_giant": [ "Your masculine chest surges outward in an overwhelming wave of transformation. Giant breasts explode into existence, massive and heavy, swelling until they dominate your entire frame. You cry out at the extreme weight, the transformation from masculine flatness to extreme femininity shocking.", "An almost unbearable pressure radiates through your masculine chest before releasing in a flood of growth. Your breasts expand to giant proportions from hard flatness, the massive orbs bouncing with substantial weight. The transformation is both shocking and intensely arousing." ], "flatmasculine_to_gigantic": [ "Your masculine chest erupts with the most extreme transformation possible. Gigantic breasts explode outward from hard muscle, growing to truly enormous proportions. The massive, heavy orbs swing and bounce with overwhelming weight, completely reshaping your silhouette.", "An incredible pressure builds in your masculine chest before bursting forth in extreme growth. Your breasts expand to gigantic size from flat hardness, the enormous mounds dominating your entire torso. You moan loudly as the extreme weight settles." ], /* FROM FLAT */ "flat_to_flatmasculine": [ "Your chest tingles as it firms and hardens slightly. The soft flatness becomes more muscular, more aggressively masculine. The subtle change leaves your chest harder and more defined, though still without curves." ], "flat_to_small": [ "A warm tingling spreads across your chest as subtle swells begin to form. Small, sensitive mounds push outward, creating the first hints of feminine curves. Your nipples harden as they adjust to their new prominence.", "You feel a pleasant warmth as your chest begins to bud. Delicate flesh swells gently outward, forming small, pert breasts. The transformation is gentle but unmistakable, leaving you with modest, sensitive curves.", "Your flat chest tingles intensely as new tissue begins to develop. Slowly but surely, small breasts emerge, pushing outward with youthful firmness. You gasp at the novel weight and sensitivity." ], "flat_to_medium": [ "Heat blooms across your chest as substantial growth begins. Your breasts swell outward with steady pressure, expanding from nothing into full, rounded curves that fill your palms. The transformation leaves you breathless.", "You gasp as your chest surges forward, flesh multiplying and swelling. Medium-sized breasts emerge with surprising weight, their soft curves bouncing gently with each breath. Nipples peak prominently atop the new mounds.", "Intense tingling radiates through your chest as it transforms dramatically. Your breasts grow from flat to full and round, the newly formed curves jiggling softly. The substantial weight feels both strange and arousing." ], "flat_to_large": [ "Your chest explodes outward with overwhelming sensation. Large, heavy breasts surge into existence, the transformation rapid and profound. Your back arches involuntarily as the substantial weight settles, nipples hardening atop the impressive mounds.", "An intense pressure builds in your chest before releasing in a rush of growth. Your breasts swell dramatically, expanding from nothing to large, bouncing curves that demand attention. You moan as the weight becomes deliciously apparent.", "You cry out as your chest transforms dramatically. Flesh multiplies rapidly, creating large, heavy breasts that hang with enticing weight. The transformation is total—where there was flatness now sits impressive, jiggling femininity." ], "flat_to_huge": [ "Overwhelming heat surges through your chest as an extreme transformation begins. Your breasts explode outward, growing into huge, heavy orbs that bounce and sway. The massive weight pulls at your shoulders, nipples thick and prominent.", "Your chest erupts with sensation as a profound change overtakes you. Huge breasts swell into existence, expanding dramatically until they dominate your torso. You gasp and moan as the enormous weight settles, soft flesh spilling abundantly.", "An intense pressure builds to an overwhelming crescendo as your chest transforms completely. Huge, heavy breasts emerge with shocking speed, their substantial mass jiggling with every movement. The transformation leaves you panting and sensitized." ], "flat_to_giant": [ "Your chest surges outward in an overwhelming wave of transformation. Giant breasts explode into existence, massive and heavy, swelling until they dominate your entire frame. You cry out at the extreme weight, nipples peaked atop the enormous mounds.", "An almost unbearable pressure radiates through your chest before releasing in a flood of growth. Your breasts expand to giant proportions, the massive orbs bouncing and swaying with substantial weight. The transformation is both shocking and intensely arousing.", "You feel your chest transforming dramatically as giant breasts surge forth. The massive curves expand rapidly, growing heavier and fuller until they hang impressively. Your back arches under the extreme new weight, sensation overwhelming you." ], "flat_to_gigantic": [ "Your chest erupts with the most extreme transformation possible. Gigantic breasts explode outward, growing to truly enormous proportions. The massive, heavy orbs swing and bounce with overwhelming weight, completely reshaping your silhouette.", "An incredible pressure builds in your chest before bursting forth in extreme growth. Your breasts expand to gigantic size, the enormous mounds dominating your entire torso. You moan loudly as the extreme weight settles, flesh abundant and soft.", "Your chest transforms in the most profound way imaginable. Gigantic breasts surge into existence, expanding rapidly to truly extreme proportions. The massive weight pulls intensely at your frame, each movement causing them to bounce and sway dramatically." ], /* FROM SMALL */ "small_to_flatmasculine": [ "A cool, pulling sensation spreads through your chest as your small breasts begin to shrink and harden. The soft mounds flatten completely, becoming hard, muscular, and aggressively masculine. The feminine curves disappear entirely, replaced by firm muscle." ], "small_to_flat": [ "A cool, pulling sensation spreads through your chest as your small breasts begin to shrink. The soft mounds gradually flatten, flesh receding until your chest is completely smooth. The sensitivity fades with the curves.", "You feel your breasts diminishing, the small swells pulling inward and flattening. The transformation is thorough—soft curves disappear entirely, leaving you with a flat, smooth chest. The feminine weight vanishes completely.", "Tingling spreads through your chest as your small breasts reduce gradually. The delicate mounds flatten steadily until no trace of them remains. Your chest returns to a completely flat state." ], "small_to_medium": [ "Warmth blooms across your chest as your small breasts begin to swell. They expand steadily, growing fuller and rounder until they reach a nice handful. The increased weight is pleasant and noticeable.", "You gasp as your breasts grow from small to medium, flesh swelling outward with steady pressure. The transformation leaves you with nicely rounded curves that bounce gently. Your nipples harden atop the fuller mounds.", "Your chest tingles as growth begins. Your small breasts expand pleasantly, filling out into medium-sized curves that feel substantial in your hands. The added weight and sensitivity makes you shiver." ], "small_to_large": [ "Intense heat radiates through your chest as dramatic growth begins. Your small breasts swell rapidly, expanding into large, heavy curves that bounce with their new weight. The transformation is substantial and arousing.", "You moan as your breasts surge forward dramatically. They grow from small to large, the flesh multiplying until you have impressive, jiggling curves. The considerable weight settles heavily, nipples peaked with stimulation.", "Your chest transforms significantly as your breasts expand. The small mounds swell into large, bouncing breasts that demand attention. You gasp at the dramatic increase in weight and sensitivity." ], "small_to_huge": [ "Your chest explodes with sensation as extreme growth overtakes you. Your small breasts expand massively, swelling into huge, heavy orbs that hang with substantial weight. The transformation is profound and intense.", "Overwhelming pressure builds in your chest before releasing in a surge of growth. Your breasts expand from small to huge, the massive curves bouncing and swaying. You cry out at the extreme increase in weight.", "You feel your breasts transforming dramatically, growing from small to huge. The enormous expansion leaves you with massive, jiggling curves that dominate your torso. The weight is extreme and arousing." ], "small_to_giant": [ "An overwhelming transformation overtakes your chest. Your small breasts explode outward, expanding into giant, heavy orbs that swing with massive weight. The extreme growth leaves you moaning and breathless.", "Intense pressure radiates through your chest as your breasts undergo extreme growth. They expand from small to giant proportions, the enormous mounds bouncing heavily. You gasp at the shocking transformation.", "Your chest surges dramatically as your breasts grow to giant size. The massive expansion creates enormous, swaying curves that completely reshape your silhouette. The extreme weight pulls intensely at your frame." ], "small_to_gigantic": [ "Your chest erupts with the most extreme transformation possible. Your small breasts explode into gigantic proportions, the enormous orbs swelling with overwhelming weight. The transformation is shocking and intensely arousing.", "Incredible pressure builds before bursting forth in extreme growth. Your breasts expand from small to gigantic, the massive mounds dominating your entire body. You cry out as the extreme weight settles.", "Your chest transforms in the most profound way. Your small breasts surge into gigantic curves, expanding to truly enormous size. The massive weight bounces and sways with every movement, leaving you panting." ], /* FROM MEDIUM */ "medium_to_flatmasculine": [ "A pulling sensation courses through your chest as your breasts shrink rapidly and harden. The medium curves diminish and firm, receding entirely until your chest is hard, muscular, and masculine. All feminine softness transforms into firm muscle." ], "medium_to_flat": [ "A pulling sensation courses through your chest as your breasts begin to shrink rapidly. The medium-sized curves diminish steadily, receding entirely until your chest is completely flat. All feminine softness vanishes.", "You feel your breasts reducing significantly, the medium mounds pulling inward and flattening. The transformation is complete—rounded curves disappear, leaving you with a smooth, firm chest. The weight and sensitivity fade entirely.", "Your chest tingles as your breasts shrink dramatically. The medium-sized curves flatten thoroughly, all traces of feminine shape disappearing. Your chest returns to a flat state." ], "medium_to_small": [ "Cool tingling spreads through your chest as your breasts begin to shrink. The medium curves reduce pleasantly, becoming smaller and perkier. You end up with cute, modest breasts that sit high on your chest.", "You feel your breasts diminishing slightly, the medium mounds reducing to small, pert swells. The transformation is gentle but noticeable, leaving you with dainty, sensitive curves.", "Your chest shifts as your breasts shrink from medium to small. The curves reduce steadily, becoming more modest and youthful. The reduced weight feels lighter and firmer." ], "medium_to_large": [ "Warmth spreads across your chest as your breasts begin to swell. The medium curves expand steadily, growing heavier and fuller. You end up with large, impressive breasts that bounce enticingly.", "You gasp as your breasts grow noticeably, the medium mounds expanding into large, heavy curves. The increased weight settles pleasantly, flesh jiggling with each breath. Your nipples harden atop the fuller breasts.", "Your chest tingles as growth begins. Your medium breasts swell into large, attention-grabbing curves that hang with pleasant weight. The transformation leaves you feeling voluptuous and sensitive." ], "medium_to_huge": [ "Intense heat radiates through your chest as dramatic growth begins. Your medium breasts expand rapidly, swelling into huge, heavy orbs that bounce with substantial weight. The transformation is extreme and arousing.", "You moan as your breasts surge forward significantly. They grow from medium to huge, the flesh multiplying until you have massive, jiggling curves. The considerable weight settles heavily, pulling at your shoulders.", "Your chest transforms dramatically as your breasts expand. The medium mounds swell into huge, swaying breasts that dominate your torso. You gasp at the extreme increase in weight and sensitivity." ], "medium_to_giant": [ "Your chest erupts with sensation as profound growth overtakes you. Your medium breasts expand massively, swelling into giant, heavy orbs that hang with extreme weight. The transformation is shocking and intense.", "Overwhelming pressure builds in your chest before releasing in a surge of growth. Your breasts expand from medium to giant, the enormous curves bouncing and swaying. You cry out at the massive increase in weight.", "You feel your breasts transforming dramatically, growing from medium to giant. The enormous expansion leaves you with massive, jiggling curves that completely reshape your silhouette. The weight is extreme." ], "medium_to_gigantic": [ "Your chest explodes with the most extreme transformation. Your medium breasts expand into gigantic proportions, the enormous orbs swelling with overwhelming weight. The change is total and intensely arousing.", "Incredible pressure radiates through your chest before bursting forth in extreme growth. Your breasts expand from medium to gigantic, the massive mounds dominating your entire body. You gasp at the shocking transformation.", "Your chest undergoes the most profound change possible. Your medium breasts surge into gigantic curves, expanding to truly enormous size. The massive weight bounces heavily, leaving you breathless." ], /* FROM LARGE */ "large_to_flatmasculine": [ "An intense pulling sensation courses through your chest as your large breasts shrink dramatically and harden. The heavy curves diminish and firm rapidly, receding entirely until your chest is hard, muscular, and masculine. The transformation is profound and complete." ], "large_to_flat": [ "An intense pulling sensation courses through your chest as your large breasts shrink dramatically. The heavy curves diminish rapidly, receding entirely until your chest is completely flat. The transformation is profound and complete.", "You feel your breasts reducing massively, the large mounds pulling inward and flattening entirely. The transformation is extreme—bouncing curves disappear completely, leaving you with a smooth, firm chest. All weight vanishes.", "Your chest tingles intensely as your breasts shrink dramatically. The large, heavy curves flatten thoroughly, every trace of feminine shape disappearing. Your chest returns to a completely flat state." ], "large_to_small": [ "Cool tingling spreads through your chest as your breasts shrink considerably. The large curves reduce significantly, becoming small, pert swells. The dramatic reduction in weight feels almost dizzying.", "You feel your breasts diminishing substantially, the large mounds reducing to small, modest curves. The transformation is significant—you lose considerable weight and volume, ending with delicate, sensitive breasts.", "Your chest shifts dramatically as your breasts shrink from large to small. The curves reduce extensively, becoming much more modest and youthful. The greatly reduced weight feels remarkably lighter." ], "large_to_medium": [ "A pulling sensation spreads through your chest as your large breasts begin to shrink. The heavy curves reduce to a more moderate size, becoming medium-sized and manageable. The reduced weight is noticeable but pleasant.", "You feel your breasts diminishing somewhat, the large mounds reducing to medium, rounded curves. The transformation is clear—you lose some weight and volume, but retain attractive feminine shape.", "Your chest tingles as your breasts shrink from large to medium. The impressive curves reduce to a more modest size, less heavy but still nicely rounded. The reduced weight feels more comfortable." ], "large_to_huge": [ "Warmth blooms across your chest as your large breasts begin to swell further. They expand steadily, growing even heavier and fuller. You end up with huge, impressive breasts that bounce and sway dramatically.", "You gasp as your breasts grow significantly, the large mounds expanding into huge, heavy curves. The increased weight becomes quite substantial, flesh jiggling heavily with each breath. Your nipples peak prominently.", "Your chest tingles as dramatic growth begins. Your large breasts swell into huge, dominating curves that hang with considerable weight. The transformation leaves you feeling extremely voluptuous." ], "large_to_giant": [ "Intense heat radiates through your chest as extreme growth begins. Your large breasts expand massively, swelling into giant, heavy orbs that bounce with enormous weight. The transformation is profound and arousing.", "You moan as your breasts surge forward dramatically. They grow from large to giant, the flesh multiplying until you have massive, swaying curves. The extreme weight settles heavily, pulling at your frame.", "Your chest transforms significantly as your breasts expand. The large mounds swell into giant, attention-commanding breasts that dominate your entire torso. You gasp at the massive increase in weight." ], "large_to_gigantic": [ "Your chest erupts with sensation as the most extreme growth overtakes you. Your large breasts expand into gigantic proportions, the enormous orbs swelling with overwhelming weight. The transformation is shocking and intense.", "Overwhelming pressure builds in your chest before releasing in a surge of extreme growth. Your breasts expand from large to gigantic, the massive curves bouncing heavily. You cry out at the incredible transformation.", "You feel your breasts transforming dramatically, growing from large to gigantic. The enormous expansion creates truly massive, swaying curves. The extreme weight bounces and jiggles with overwhelming presence." ], /* FROM HUGE */ "huge_to_flatmasculine": [ "An extreme pulling sensation courses through your chest as your huge breasts shrink and harden dramatically. The massive curves diminish and firm completely, receding entirely until your chest is hard, muscular, and masculine. The loss of weight is shocking." ], "huge_to_flat": [ "An extreme pulling sensation courses through your chest as your huge breasts shrink dramatically. The massive curves diminish completely, receding entirely until your chest is flat. The loss of weight is shocking.", "You feel your breasts reducing massively, the huge mounds pulling inward and flattening entirely. The transformation is extreme—heavy, bouncing curves disappear completely, leaving you with a smooth, firm chest.", "Your chest experiences intense tingling as your breasts shrink dramatically. The huge, heavy curves flatten thoroughly, every trace of the massive mounds disappearing. Your chest returns to complete flatness." ], "huge_to_small": [ "Intense pulling spreads through your chest as your breasts shrink extremely. The huge curves reduce dramatically to small, pert swells. The massive reduction in weight feels almost disorienting—you go from heavy and bouncing to delicate and modest.", "You feel your breasts diminishing enormously, the huge mounds reducing to small, dainty curves. The transformation is extreme—you lose massive weight and volume, ending with subtle, sensitive breasts.", "Your chest shifts dramatically as your breasts shrink from huge to small. The massive curves reduce extensively, becoming tiny and youthful. The drastically reduced weight feels remarkably lighter." ], "huge_to_medium": [ "Strong pulling sensations course through your chest as your huge breasts begin to shrink considerably. The massive curves reduce to a more moderate medium size. The significant reduction in weight is both noticeable and relieving.", "You feel your breasts diminishing substantially, the huge mounds reducing to medium, manageable curves. The transformation is significant—you lose considerable weight and volume, but retain pleasant feminine shape.", "Your chest tingles as your breasts shrink from huge to medium. The massive curves reduce significantly to a more modest size. The greatly reduced weight feels much more comfortable and manageable." ], "huge_to_large": [ "Cool tingling spreads through your chest as your huge breasts shrink somewhat. The massive curves reduce to large, still impressive breasts. The reduction in weight is noticeable—lighter but still substantial and bouncing.", "You feel your breasts diminishing moderately, the huge mounds reducing to large, heavy curves. The transformation is clear—you lose some of the extreme weight, but retain impressive, attention-grabbing size.", "Your chest shifts as your breasts shrink from huge to large. The massive curves reduce to a somewhat smaller (but still substantial) size. The reduced weight feels more manageable while remaining voluptuous." ], "huge_to_giant": [ "Warmth spreads across your chest as your huge breasts begin to swell even further. They expand steadily, growing into giant, massively heavy orbs. The increased weight becomes extreme and dominating.", "You gasp as your breasts grow notably, the huge mounds expanding into giant, enormous curves. The weight becomes truly extreme, flesh jiggling massively with each breath. Your back arches under the burden.", "Your chest tingles as extreme growth begins. Your huge breasts swell into giant, completely dominating curves that swing with massive weight. The transformation pushes you to new extremes." ], "huge_to_gigantic": [ "Intense heat radiates through your chest as the ultimate growth begins. Your huge breasts expand into gigantic proportions, the enormous orbs swelling with the most extreme weight possible. The transformation is overwhelming.", "You moan loudly as your breasts surge forward to maximum size. They grow from huge to gigantic, the flesh multiplying until you have truly massive, swaying curves. The weight is almost unbearable—heavy and ever-present.", "Your chest transforms dramatically as your breasts expand to their absolute limit. The huge mounds swell into gigantic, world-dominating breasts. You cry out at the extreme final transformation." ], /* FROM GIANT */ "giant_to_flatmasculine": [ "An overwhelming pulling sensation courses through your chest as your giant breasts shrink and harden completely. The enormous curves diminish and firm entirely, receding until your chest is hard, muscular, and masculine. The extreme loss of weight is shocking and disorienting." ], "giant_to_flat": [ "An overwhelming pulling sensation courses through your chest as your giant breasts shrink completely. The enormous curves diminish entirely, receding until your chest is flat. The extreme loss of weight is shocking and disorienting.", "You feel your breasts reducing massively, the giant mounds pulling inward and vanishing entirely. The transformation is the most extreme possible—enormous, swaying curves disappear completely, leaving you with a smooth, firm chest.", "Your chest experiences overwhelming tingling as your breasts shrink dramatically. The giant, massive curves flatten thoroughly and completely. Your chest returns to absolute flatness—the change is total." ], "giant_to_small": [ "Extreme pulling spreads through your chest as your breasts shrink to the opposite extreme. The giant curves reduce dramatically to small, pert swells. The massive reduction from enormous to delicate is almost surreal.", "You feel your breasts diminishing incredibly, the giant mounds reducing to small, dainty curves. The transformation is extreme—you lose massive weight and volume, going from dominating to modest.", "Your chest undergoes an extreme transformation as your breasts shrink from giant to small. The enormous curves reduce drastically, becoming tiny and youthful. The weight difference is staggering." ], "giant_to_medium": [ "Strong pulling sensations course through your chest as your giant breasts shrink dramatically. The enormous curves reduce to medium size—a significant transformation. You lose extreme weight and dominance.", "You feel your breasts diminishing greatly, the giant mounds reducing to medium, manageable curves. The transformation is major—you lose most of the extreme weight, ending at a more moderate size.", "Your chest tingles intensely as your breasts shrink from giant to medium. The massive curves reduce significantly to a modest, everyday size. The loss of extreme weight is palpable." ], "giant_to_large": [ "Pulling sensations spread through your chest as your giant breasts shrink considerably. The enormous curves reduce to large, still impressive breasts. You lose some extreme weight but retain substantial size.", "You feel your breasts diminishing noticeably, the giant mounds reducing to large, heavy curves. The transformation is clear—less extreme weight, but still impressive and attention-grabbing.", "Your chest shifts as your breasts shrink from giant to large. The massive curves reduce to a somewhat smaller (though still substantial) size. The weight becomes more manageable." ], "giant_to_huge": [ "Cool tingling spreads through your chest as your giant breasts shrink moderately. The enormous curves reduce to huge, massively heavy breasts. The weight remains extreme but slightly less dominating.", "You feel your breasts diminishing somewhat, the giant mounds reducing to huge, still very substantial curves. The transformation reduces the most extreme proportions while keeping you very voluptuous.", "Your chest shifts as your breasts shrink from giant to huge. The enormous curves reduce slightly but remain massive and heavy. The weight is still extreme but marginally more manageable." ], "giant_to_gigantic": [ "Warmth spreads across your chest as your giant breasts swell to their absolute maximum. They expand further into gigantic, impossibly heavy orbs. The weight becomes the most extreme possible.", "You gasp as your breasts grow to their final size, the giant mounds expanding into gigantic, truly enormous curves. The weight becomes ultimate—flesh jiggling massively with overwhelming presence.", "Your chest tingles as the final growth begins. Your giant breasts swell into gigantic, absolutely dominating curves. The transformation takes you to the absolute extreme of size and weight." ], /* FROM GIGANTIC */ "gigantic_to_flatmasculine": [ "An absolutely overwhelming pulling sensation courses through your chest as your gigantic breasts shrink and harden completely. The impossibly enormous curves diminish and firm entirely, receding until your chest is hard, muscular, and masculine. The transformation is the most extreme possible." ], "gigantic_to_flat": [ "An absolutely overwhelming pulling sensation courses through your chest as your gigantic breasts shrink completely. The impossibly enormous curves diminish entirely, receding until your chest is flat. The transformation is the most extreme possible.", "You feel your breasts reducing from their maximum size, the gigantic mounds pulling inward and vanishing entirely. The transformation is total—enormous, heavily swaying curves disappear completely, leaving only smooth firmness.", "Your chest experiences the most intense tingling imaginable as your breasts shrink from maximum to nothing. The gigantic, world-dominating curves flatten thoroughly and completely. The loss of extreme weight is staggering." ], "gigantic_to_small": [ "Extreme pulling spreads through your chest as your breasts undergo the maximum possible reduction. The gigantic curves shrink dramatically to small, pert swells. The transformation from maximum to minimal is almost incomprehensible.", "You feel your breasts diminishing from their largest to smallest size, the gigantic mounds reducing to small, dainty curves. The loss of weight is extreme—from dominating your entire body to subtle swells.", "Your chest undergoes the ultimate transformation as your breasts shrink from gigantic to small. The enormous curves reduce drastically, becoming tiny and youthful. The weight difference is absolutely staggering." ], "gigantic_to_medium": [ "Overwhelming pulling sensations course through your chest as your gigantic breasts shrink dramatically. The impossibly large curves reduce to medium size—an extreme transformation. You lose massive weight and presence.", "You feel your breasts diminishing greatly, the gigantic mounds reducing to medium, everyday curves. The transformation is major—from extreme dominance to moderate normalcy.", "Your chest tingles intensely as your breasts shrink from gigantic to medium. The absolutely massive curves reduce significantly to a modest size. The loss of extreme weight changes everything." ], "gigantic_to_large": [ "Strong pulling sensations spread through your chest as your gigantic breasts shrink considerably. The enormous curves reduce to large, though still impressive breasts. You lose extreme size but retain substantial curves.", "You feel your breasts diminishing noticeably, the gigantic mounds reducing to large, heavy curves. The transformation is significant—less overwhelming weight, but still attention-grabbing and voluptuous.", "Your chest shifts as your breasts shrink from gigantic to large. The massive curves reduce substantially but remain impressive. The weight becomes much more manageable." ], "gigantic_to_huge": [ "Pulling sensations course through your chest as your gigantic breasts shrink moderately. The enormous curves reduce to huge, massively heavy breasts. The weight remains very extreme but less overwhelming.", "You feel your breasts diminishing somewhat, the gigantic mounds reducing to huge, still very substantial curves. The transformation reduces the absolute extreme while keeping you incredibly voluptuous.", "Your chest shifts as your breasts shrink from gigantic to huge. The absolutely enormous curves reduce but remain massive. The weight is still extreme but more bearable." ], "gigantic_to_giant": [ "Cool tingling spreads through your chest as your gigantic breasts shrink slightly. The enormous curves reduce to giant, extremely heavy breasts. The weight remains massive but marginally less extreme.", "You feel your breasts diminishing modestly, the gigantic mounds reducing to giant, still enormous curves. The transformation is subtle—from absolutely maximum to merely extreme.", "Your chest shifts as your breasts shrink from gigantic to giant. The impossibly large curves reduce slightly but remain massively heavy and dominating. The difference is noticeable but not dramatic." ] }; /* Get the appropriate transformation text */ var textArray = transformations[key]; if (!textArray || textArray.length === 0) { /* Fallback for any missing combinations */ return imageHTML + "Your chest tingles as it transforms from " + oldSize + " to " + newSize + "."; } /* Return image + random variation */ return imageHTML + textArray[Math.floor(Math.random() * textArray.length)]; }>> /* ---------------------------------- */ /* --- BUTT TRANSFORMATIONS --- */ /* ---------------------------------- */ <<set setup.getButtTransformationText = function(oldSize, newSize) { var imageHTML = ""; /* Safety check for undefined values */ if (!oldSize || !newSize) { return "Butt transformation cannot be processed - missing size information."; } if (!setup.buttSizeOrder) { setup.buttSizeOrder = ["flatmasculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]; } var oldS = oldSize.toLowerCase().replace(/\s+/g, ''); var newS = newSize.toLowerCase().replace(/\s+/g, ''); if (oldS === newS) { return "Your butt remains unchanged."; } /* Single result image - just the final size */ if (typeof $imageSettings !== "undefined" && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled) { var imagePath = "Images/PostSwap/Butt_" + newS + ".webp"; imageHTML = '<div style="text-align: center; margin: 20px 0;">'; imageHTML += '<img src="' + imagePath + '" style="max-width: 60%; border-radius: 10px; border: 2px solid #FF69B4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Butt Result">'; imageHTML += '</div>'; } /* Get the transformation key */ var key = oldS + "_to_" + newS; /* Define all transformation descriptions */ var transformations = { /* FROM FLAT MASCULINE */ "flatmasculine_to_flat": [ "Your rear tingles subtly as the hard, muscular flatness softens slightly. The firm masculine shape gives way to a smoother, softer flatness—still without curves, but less aggressively masculine." ], "flatmasculine_to_small": [ "A warm tingling spreads through your rear as subtle curves begin to form. Your hard, masculine flatness softens as small, pert cheeks push outward, creating the first hints of feminine curves. The transformation is modest but unmistakable.", "You feel pleasant warmth as your masculine behind begins to transform. Delicate curves emerge, forming a small, rounded butt that's firm and lifted. The new shape feels taut and youthful." ], "flatmasculine_to_medium": [ "Heat blooms through your rear as your masculine flatness transforms substantially. Your butt swells outward with steady pressure, expanding from hard muscle into full, rounded curves that jiggle pleasantly. The transformation from masculine to feminine leaves you breathless.", "You gasp as your hard, flat behind surges backward, muscle softening and swelling. A medium-sized butt emerges with surprising weight, the soft cheeks bouncing gently with each step. The transformation from flat masculinity to feminine fullness is profound." ], "flatmasculine_to_large": [ "Your masculine rear explodes outward with overwhelming sensation. The hard, flat muscle transforms rapidly into a large, heavy butt that surges into existence. Your hips sway involuntarily as the substantial weight settles, cheeks bouncing and jiggling with impressive presence.", "An intense pressure builds in your behind before releasing in a rush of feminizing growth. Your butt swells dramatically, expanding from hard flatness to large, bouncing curves that demand attention. You moan as the weight becomes deliciously apparent." ], "flatmasculine_to_huge": [ "Overwhelming heat surges through your rear as your masculine flatness transforms extremely. A huge butt explodes outward, the hard muscle becoming enormous, heavy globes that bounce and sway. The massive weight affects your entire posture.", "Your masculine behind erupts with sensation as a profound change overtakes you. A huge butt swells into existence, expanding dramatically from flat hardness until it dominates your lower body. You gasp and moan as the enormous weight settles." ], "flatmasculine_to_giant": [ "Your masculine rear surges outward in an overwhelming wave of transformation. A giant butt explodes into existence, massive and heavy, swelling until it dominates your entire lower body. You cry out at the extreme weight, the transformation from masculine flatness to extreme femininity shocking.", "An almost unbearable pressure radiates through your behind before releasing in a flood of growth. Your butt expands to giant proportions from hard flatness, the massive globes bouncing with substantial weight. The transformation is both shocking and intensely arousing." ], "flatmasculine_to_gigantic": [ "Your masculine rear erupts with the most extreme transformation possible. A gigantic butt explodes outward from hard muscle, growing to truly enormous proportions. The massive, heavy globes swing and bounce with overwhelming weight, completely reshaping your silhouette from behind.", "An incredible pressure builds in your behind before bursting forth in extreme growth. Your butt expands to gigantic size from flat hardness, the enormous cheeks dominating your entire lower body. You moan loudly as the extreme weight settles." ], /* FROM FLAT */ "flat_to_flatmasculine": [ "Your rear tingles as it firms and hardens slightly. The soft flatness becomes more muscular, more aggressively masculine. The subtle change leaves your behind harder and more defined, though still without curves." ], "flat_to_small": [ "A warm tingling spreads through your rear as subtle curves begin to form. Your butt swells gently outward, creating small, pert cheeks that feel firm and lifted. The transformation is modest but unmistakable.", "You feel pleasant warmth as your flat rear begins to develop. Delicate curves push outward, forming a small, rounded butt that fills your pants better. The new shape feels taut and youthful.", "Your flat behind tingles intensely as new flesh begins to develop. Slowly but surely, a small, perky butt emerges. You gasp at the novel weight and the way it affects your posture." ], "flat_to_medium": [ "Heat blooms through your rear as substantial growth begins. Your butt swells outward with steady pressure, expanding from nothing into full, rounded curves that jiggle pleasantly. The transformation leaves you breathless.", "You gasp as your behind surges backward, flesh multiplying and swelling. A medium-sized butt emerges with surprising weight, the soft cheeks bouncing gently with each step. The substantial curves feel both strange and arousing.", "Intense tingling radiates through your rear as it transforms dramatically. Your butt grows from flat to full and round, the newly formed cheeks jiggling softly. The substantial weight affects how you move." ], "flat_to_large": [ "Your rear explodes outward with overwhelming sensation. A large, heavy butt surges into existence, the transformation rapid and profound. Your hips sway involuntarily as the substantial weight settles, cheeks bouncing and jiggling with impressive presence.", "An intense pressure builds in your behind before releasing in a rush of growth. Your butt swells dramatically, expanding from nothing to large, bouncing curves that demand attention. You moan as the weight becomes deliciously apparent.", "You cry out as your rear transforms dramatically. Flesh multiplies rapidly, creating a large, heavy butt that jiggles with enticing weight. The transformation is total—where there was flatness now sits impressive, feminine curviness." ], "flat_to_huge": [ "Overwhelming heat surges through your rear as an extreme transformation begins. Your butt explodes outward, growing into huge, heavy globes that bounce and sway. The massive weight affects your entire posture, cheeks full and prominent.", "Your behind erupts with sensation as a profound change overtakes you. A huge butt swells into existence, expanding dramatically until it dominates your lower body. You gasp and moan as the enormous weight settles, soft flesh spilling abundantly.", "An intense pressure builds to an overwhelming crescendo as your rear transforms completely. Huge, heavy cheeks emerge with shocking speed, their substantial mass jiggling with every movement. The transformation leaves you panting and sensitized." ], "flat_to_giant": [ "Your rear surges outward in an overwhelming wave of transformation. A giant butt explodes into existence, massive and heavy, swelling until it dominates your entire lower body. You cry out at the extreme weight, cheeks bouncing dramatically.", "An almost unbearable pressure radiates through your behind before releasing in a flood of growth. Your butt expands to giant proportions, the massive globes bouncing and swaying with substantial weight. The transformation is both shocking and intensely arousing.", "You feel your rear transforming dramatically as a giant butt surges forth. The massive curves expand rapidly, growing heavier and fuller until they protrude impressively. Your walk changes completely under the extreme new weight, sensation overwhelming you." ], "flat_to_gigantic": [ "Your rear erupts with the most extreme transformation possible. A gigantic butt explodes outward, growing to truly enormous proportions. The massive, heavy globes swing and bounce with overwhelming weight, completely reshaping your silhouette from behind.", "An incredible pressure builds in your behind before bursting forth in extreme growth. Your butt expands to gigantic size, the enormous cheeks dominating your entire lower body. You moan loudly as the extreme weight settles, flesh abundant and soft.", "Your rear transforms in the most profound way imaginable. A gigantic butt surges into existence, expanding rapidly to truly extreme proportions. The massive weight affects every movement dramatically, each step causing your enormous cheeks to bounce and sway." ], /* FROM SMALL */ "small_to_flatmasculine": [ "A cool, pulling sensation spreads through your rear as your small butt begins to shrink and harden. The perky cheeks flatten and firm completely, becoming hard, muscular, and aggressively masculine. The feminine curves disappear entirely, replaced by firm muscle." ], "small_to_flat": [ "A cool, pulling sensation spreads through your rear as your small butt begins to shrink. The perky cheeks gradually flatten, flesh receding until your behind is completely smooth. The soft curves disappear entirely.", "You feel your butt diminishing, the small swells pulling inward and flattening. The transformation is thorough—rounded curves disappear entirely, leaving you with a flat, firm behind. The feminine weight vanishes completely.", "Tingling spreads through your rear as your small butt reduces gradually. The delicate cheeks flatten steadily until no trace of them remains. Your behind returns to a completely flat state." ], "small_to_medium": [ "Warmth blooms through your rear as your small butt begins to swell. It expands steadily, growing fuller and rounder until you have a nice handful of curves. The increased weight is pleasant and noticeable when you walk.", "You gasp as your butt grows from small to medium, flesh swelling outward with steady pressure. The transformation leaves you with nicely rounded cheeks that bounce gently with each step. The fuller curves feel substantial.", "Your behind tingles as growth begins. Your small butt expands pleasantly, filling out into medium-sized curves that feel good in your hands. The added weight and jiggle makes you shiver with each movement." ], "small_to_large": [ "Intense heat radiates through your rear as dramatic growth begins. Your small butt swells rapidly, expanding into large, heavy curves that bounce with their new weight. The transformation is substantial and arousing.", "You moan as your behind surges backward dramatically. It grows from small to large, the flesh multiplying until you have impressive, jiggling cheeks. The considerable weight settles heavily, affecting how you walk and sit.", "Your rear transforms significantly as your butt expands. The small mounds swell into large, bouncing cheeks that demand attention. You gasp at the dramatic increase in weight and how it changes your movements." ], "small_to_huge": [ "Your rear explodes with sensation as extreme growth overtakes you. Your small butt expands massively, swelling into huge, heavy globes that protrude with substantial weight. The transformation is profound and intense.", "Overwhelming pressure builds in your behind before releasing in a surge of growth. Your butt expands from small to huge, the massive cheeks bouncing and swaying. You cry out at the extreme increase in weight and presence.", "You feel your butt transforming dramatically, growing from small to huge. The enormous expansion leaves you with massive, jiggling curves that dominate your lower body. The weight is extreme and affects everything." ], "small_to_giant": [ "An overwhelming transformation overtakes your rear. Your small butt explodes outward, expanding into giant, heavy globes that sway with massive weight. The extreme growth leaves you moaning and breathless.", "Intense pressure radiates through your behind as your butt undergoes extreme growth. It expands from small to giant proportions, the enormous cheeks bouncing heavily. You gasp at the shocking transformation.", "Your rear surges dramatically as your butt grows to giant size. The massive expansion creates enormous, swaying curves that completely reshape how you move. The extreme weight pulls at your entire lower body." ], "small_to_gigantic": [ "Your rear erupts with the most extreme transformation possible. Your small butt explodes into gigantic proportions, the enormous globes swelling with overwhelming weight. The transformation is shocking and intensely arousing.", "Incredible pressure builds before bursting forth in extreme growth. Your butt expands from small to gigantic, the massive cheeks dominating your entire lower body. You cry out as the extreme weight settles.", "Your behind transforms in the most profound way. Your small butt surges into gigantic curves, expanding to truly enormous size. The massive weight bounces and sways with every tiny movement, leaving you panting." ], /* FROM MEDIUM */ "medium_to_flatmasculine": [ "A pulling sensation courses through your rear as your butt shrinks rapidly and hardens. The medium curves diminish and firm, receding entirely until your behind is hard, muscular, and masculine. All feminine roundness transforms into firm muscle." ], "medium_to_flat": [ "A pulling sensation courses through your rear as your butt begins to shrink rapidly. The medium-sized curves diminish steadily, receding entirely until your behind is completely flat. All feminine roundness vanishes.", "You feel your butt reducing significantly, the medium cheeks pulling inward and flattening. The transformation is complete—rounded curves disappear, leaving you with a smooth, firm behind. The weight and bounce fade entirely.", "Your rear tingles as your butt shrinks dramatically. The medium-sized curves flatten thoroughly, all traces of feminine shape disappearing. Your behind returns to a flat state." ], "medium_to_small": [ "Cool tingling spreads through your rear as your butt begins to shrink. The medium curves reduce pleasantly, becoming smaller and perkier. You end up with a cute, modest butt that sits high and firm.", "You feel your butt diminishing slightly, the medium cheeks reducing to small, pert swells. The transformation is gentle but noticeable, leaving you with a dainty, lifted behind.", "Your rear shifts as your butt shrinks from medium to small. The curves reduce steadily, becoming more modest and youthful. The reduced weight feels lighter and tighter." ], "medium_to_large": [ "Warmth spreads through your rear as your butt begins to swell. The medium curves expand steadily, growing heavier and fuller. You end up with a large, impressive butt that bounces enticingly with each step.", "You gasp as your butt grows noticeably, the medium cheeks expanding into large, heavy curves. The increased weight settles pleasantly, flesh jiggling with each movement. The fuller behind affects how your pants fit.", "Your rear tingles as growth begins. Your medium butt swells into large, attention-grabbing curves that protrude with pleasant weight. The transformation leaves you feeling voluptuous and more conscious of your movements." ], "medium_to_huge": [ "Intense heat radiates through your rear as dramatic growth begins. Your medium butt expands rapidly, swelling into huge, heavy globes that bounce with substantial weight. The transformation is extreme and arousing.", "You moan as your behind surges backward significantly. It grows from medium to huge, the flesh multiplying until you have massive, jiggling cheeks. The considerable weight settles heavily, dramatically affecting your posture.", "Your rear transforms dramatically as your butt expands. The medium cheeks swell into huge, swaying curves that dominate your lower body. You gasp at the extreme increase in weight and presence." ], "medium_to_giant": [ "Your rear erupts with sensation as profound growth overtakes you. Your medium butt expands massively, swelling into giant, heavy globes that protrude with extreme weight. The transformation is shocking and intense.", "Overwhelming pressure builds in your behind before releasing in a surge of growth. Your butt expands from medium to giant, the enormous cheeks bouncing and swaying. You cry out at the massive increase in size and weight.", "You feel your butt transforming dramatically, growing from medium to giant. The enormous expansion leaves you with massive, jiggling curves that completely reshape your silhouette. The weight is extreme and ever-present." ], "medium_to_gigantic": [ "Your rear explodes with the most extreme transformation. Your medium butt expands into gigantic proportions, the enormous globes swelling with overwhelming weight. The change is total and intensely arousing.", "Incredible pressure radiates through your behind before bursting forth in extreme growth. Your butt expands from medium to gigantic, the massive cheeks dominating your entire lower body. You gasp at the shocking transformation.", "Your rear undergoes the most profound change possible. Your medium butt surges into gigantic curves, expanding to truly enormous size. The massive weight bounces heavily with every movement, leaving you breathless." ], /* FROM LARGE */ "large_to_flatmasculine": [ "An intense pulling sensation courses through your rear as your large butt shrinks dramatically and hardens. The heavy curves diminish and firm rapidly, receding entirely until your behind is hard, muscular, and masculine. The transformation is profound and complete." ], "large_to_flat": [ "An intense pulling sensation courses through your rear as your large butt shrinks dramatically. The heavy curves diminish rapidly, receding entirely until your behind is completely flat. The transformation is profound and complete.", "You feel your butt reducing massively, the large cheeks pulling inward and flattening entirely. The transformation is extreme—bouncing curves disappear completely, leaving you with a smooth, firm behind. All weight and jiggle vanish.", "Your rear tingles intensely as your butt shrinks dramatically. The large, heavy curves flatten thoroughly, every trace of feminine shape disappearing. Your behind returns to a completely flat state." ], "large_to_small": [ "Cool tingling spreads through your rear as your butt shrinks considerably. The large curves reduce significantly, becoming small, pert swells. The dramatic reduction in weight and presence feels almost dizzying.", "You feel your butt diminishing substantially, the large cheeks reducing to small, modest curves. The transformation is significant—you lose considerable weight and volume, ending with a delicate, lifted behind.", "Your rear shifts dramatically as your butt shrinks from large to small. The curves reduce extensively, becoming much more modest and youthful. The greatly reduced weight and bounce feel remarkably different." ], "large_to_medium": [ "A pulling sensation spreads through your rear as your large butt begins to shrink. The heavy curves reduce to a more moderate size, becoming medium-sized and manageable. The reduced weight is noticeable but pleasant.", "You feel your butt diminishing somewhat, the large cheeks reducing to medium, rounded curves. The transformation is clear—you lose some weight and volume, but retain attractive feminine shape.", "Your rear tingles as your butt shrinks from large to medium. The impressive curves reduce to a more modest size, less heavy but still nicely rounded. The reduced weight feels more comfortable when moving." ], "large_to_huge": [ "Warmth blooms through your rear as your large butt begins to swell further. It expands steadily, growing even heavier and fuller. You end up with huge, impressive cheeks that bounce and sway dramatically with each step.", "You gasp as your butt grows significantly, the large cheeks expanding into huge, heavy curves. The increased weight becomes quite substantial, flesh jiggling heavily with each movement. The curves protrude prominently.", "Your rear tingles as dramatic growth begins. Your large butt swells into huge, dominating curves that protrude with considerable weight. The transformation leaves you feeling extremely voluptuous and aware of your movements." ], "large_to_giant": [ "Intense heat radiates through your rear as extreme growth begins. Your large butt expands massively, swelling into giant, heavy globes that bounce with enormous weight. The transformation is profound and arousing.", "You moan as your behind surges backward dramatically. It grows from large to giant, the flesh multiplying until you have massive, swaying cheeks. The extreme weight settles heavily, dramatically affecting how you walk and sit.", "Your rear transforms significantly as your butt expands. The large cheeks swell into giant, attention-commanding curves that dominate your entire lower body. You gasp at the massive increase in weight and presence." ], "large_to_gigantic": [ "Your rear erupts with sensation as the most extreme growth overtakes you. Your large butt expands into gigantic proportions, the enormous globes swelling with overwhelming weight. The transformation is shocking and intense.", "Overwhelming pressure builds in your behind before releasing in a surge of extreme growth. Your butt expands from large to gigantic, the massive cheeks bouncing heavily. You cry out at the incredible transformation.", "You feel your butt transforming dramatically, growing from large to gigantic. The enormous expansion creates truly massive, swaying curves. The extreme weight bounces and jiggles with overwhelming presence in every movement." ], /* FROM HUGE */ "huge_to_flatmasculine": [ "An extreme pulling sensation courses through your rear as your huge butt shrinks and hardens dramatically. The massive curves diminish and firm completely, receding entirely until your behind is hard, muscular, and masculine. The loss of weight and presence is shocking." ], "huge_to_flat": [ "An extreme pulling sensation courses through your rear as your huge butt shrinks dramatically. The massive curves diminish completely, receding entirely until your behind is flat. The loss of weight and presence is shocking.", "You feel your butt reducing massively, the huge cheeks pulling inward and flattening entirely. The transformation is extreme—heavy, bouncing curves disappear completely, leaving you with a smooth, firm behind.", "Your rear experiences intense tingling as your butt shrinks dramatically. The huge, heavy curves flatten thoroughly, every trace of the massive cheeks disappearing. Your behind returns to complete flatness." ], "huge_to_small": [ "Intense pulling spreads through your rear as your butt shrinks extremely. The huge curves reduce dramatically to small, pert swells. The massive reduction in weight feels almost disorienting—you go from heavy and bouncing to delicate and modest.", "You feel your butt diminishing enormously, the huge cheeks reducing to small, dainty curves. The transformation is extreme—you lose massive weight and volume, ending with a subtle, perky behind.", "Your rear shifts dramatically as your butt shrinks from huge to small. The massive curves reduce extensively, becoming tiny and youthful. The drastically reduced weight and presence feel remarkably different." ], "huge_to_medium": [ "Strong pulling sensations course through your rear as your huge butt begins to shrink considerably. The massive curves reduce to a more moderate medium size. The significant reduction in weight and bounce is both noticeable and relieving.", "You feel your butt diminishing substantially, the huge cheeks reducing to medium, manageable curves. The transformation is significant—you lose considerable weight and volume, but retain pleasant feminine shape.", "Your rear tingles as your butt shrinks from huge to medium. The massive curves reduce significantly to a more modest size. The greatly reduced weight feels much more comfortable and manageable." ], "huge_to_large": [ "Cool tingling spreads through your rear as your huge butt shrinks somewhat. The massive curves reduce to large, still impressive cheeks. The reduction in weight is noticeable—lighter but still substantial and bouncing.", "You feel your butt diminishing moderately, the huge cheeks reducing to large, heavy curves. The transformation is clear—you lose some of the extreme weight, but retain impressive, attention-grabbing size.", "Your rear shifts as your butt shrinks from huge to large. The massive curves reduce to a somewhat smaller (but still substantial) size. The reduced weight feels more manageable while remaining voluptuous." ], "huge_to_giant": [ "Warmth spreads through your rear as your huge butt begins to swell even further. It expands steadily, growing into giant, massively heavy globes. The increased weight becomes extreme and dominating.", "You gasp as your butt grows notably, the huge cheeks expanding into giant, enormous curves. The weight becomes truly extreme, flesh jiggling massively with each movement. Your posture adjusts dramatically under the burden.", "Your rear tingles as extreme growth begins. Your huge butt swells into giant, completely dominating curves that protrude with massive weight. The transformation pushes you to new extremes of size and presence." ], "huge_to_gigantic": [ "Intense heat radiates through your rear as the ultimate growth begins. Your huge butt expands into gigantic proportions, the enormous globes swelling with the most extreme weight possible. The transformation is overwhelming.", "You moan loudly as your behind surges backward to maximum size. It grows from huge to gigantic, the flesh multiplying until you have truly massive, swaying curves. The weight is almost unbearable—heavy and dominating every movement.", "Your rear transforms dramatically as your butt expands to its absolute limit. The huge cheeks swell into gigantic, world-dominating curves. You cry out at the extreme final transformation." ], /* FROM GIANT */ "giant_to_flatmasculine": [ "An overwhelming pulling sensation courses through your rear as your giant butt shrinks and hardens completely. The enormous curves diminish and firm entirely, receding until your behind is hard, muscular, and masculine. The extreme loss of weight is shocking and disorienting." ], "giant_to_flat": [ "An overwhelming pulling sensation courses through your rear as your giant butt shrinks completely. The enormous curves diminish entirely, receding until your behind is flat. The extreme loss of weight is shocking and disorienting.", "You feel your butt reducing massively, the giant cheeks pulling inward and vanishing entirely. The transformation is the most extreme possible—enormous, swaying curves disappear completely, leaving you with a smooth, firm behind.", "Your rear experiences overwhelming tingling as your butt shrinks dramatically. The giant, massive curves flatten thoroughly and completely. Your behind returns to absolute flatness—the change is total." ], "giant_to_small": [ "Extreme pulling spreads through your rear as your butt shrinks to the opposite extreme. The giant curves reduce dramatically to small, pert swells. The massive reduction from enormous to delicate is almost surreal.", "You feel your butt diminishing incredibly, the giant cheeks reducing to small, dainty curves. The transformation is extreme—you lose massive weight and volume, going from dominating to modest.", "Your rear undergoes an extreme transformation as your butt shrinks from giant to small. The enormous curves reduce drastically, becoming tiny and youthful. The weight difference is staggering." ], "giant_to_medium": [ "Strong pulling sensations course through your rear as your giant butt shrinks dramatically. The enormous curves reduce to medium size—a significant transformation. You lose extreme weight and dominance.", "You feel your butt diminishing greatly, the giant cheeks reducing to medium, manageable curves. The transformation is major—you lose most of the extreme weight, ending at a more moderate size.", "Your rear tingles intensely as your butt shrinks from giant to medium. The massive curves reduce significantly to a modest, everyday size. The loss of extreme weight and presence is palpable." ], "giant_to_large": [ "Pulling sensations spread through your rear as your giant butt shrinks considerably. The enormous curves reduce to large, still impressive cheeks. You lose some extreme weight but retain substantial size and bounce.", "You feel your butt diminishing noticeably, the giant cheeks reducing to large, heavy curves. The transformation is clear—less extreme weight, but still impressive and attention-grabbing.", "Your rear shifts as your butt shrinks from giant to large. The massive curves reduce to a somewhat smaller (though still substantial) size. The weight becomes more manageable but remains voluptuous." ], "giant_to_huge": [ "Cool tingling spreads through your rear as your giant butt shrinks moderately. The enormous curves reduce to huge, massively heavy cheeks. The weight remains extreme but slightly less dominating.", "You feel your butt diminishing somewhat, the giant cheeks reducing to huge, still very substantial curves. The transformation reduces the most extreme proportions while keeping you very voluptuous.", "Your rear shifts as your butt shrinks from giant to huge. The enormous curves reduce slightly but remain massive and heavy. The weight is still extreme but marginally more manageable." ], "giant_to_gigantic": [ "Warmth spreads through your rear as your giant butt swells to its absolute maximum. It expands further into gigantic, impossibly heavy globes. The weight becomes the most extreme possible.", "You gasp as your butt grows to its final size, the giant cheeks expanding into gigantic, truly enormous curves. The weight becomes ultimate—flesh jiggling massively with overwhelming presence.", "Your rear tingles as the final growth begins. Your giant butt swells into gigantic, absolutely dominating curves. The transformation takes you to the absolute extreme of size and weight." ], /* FROM GIGANTIC */ "gigantic_to_flatmasculine": [ "An absolutely overwhelming pulling sensation courses through your rear as your gigantic butt shrinks and hardens completely. The impossibly enormous curves diminish and firm entirely, receding until your behind is hard, muscular, and masculine. The transformation is the most extreme possible." ], "gigantic_to_flat": [ "An absolutely overwhelming pulling sensation courses through your rear as your gigantic butt shrinks completely. The impossibly enormous curves diminish entirely, receding until your behind is flat. The transformation is the most extreme possible.", "You feel your butt reducing from its maximum size, the gigantic cheeks pulling inward and vanishing entirely. The transformation is total—enormous, heavily swaying curves disappear completely, leaving only smooth firmness.", "Your rear experiences the most intense tingling imaginable as your butt shrinks from maximum to nothing. The gigantic, world-dominating curves flatten thoroughly and completely. The loss of extreme weight is staggering." ], "gigantic_to_small": [ "Extreme pulling spreads through your rear as your butt undergoes the maximum possible reduction. The gigantic curves shrink dramatically to small, pert swells. The transformation from maximum to minimal is almost incomprehensible.", "You feel your butt diminishing from its largest to smallest size, the gigantic cheeks reducing to small, dainty curves. The loss of weight is extreme—from dominating your entire lower body to subtle swells.", "Your rear undergoes the ultimate transformation as your butt shrinks from gigantic to small. The enormous curves reduce drastically, becoming tiny and youthful. The weight difference is absolutely staggering." ], "gigantic_to_medium": [ "Overwhelming pulling sensations course through your rear as your gigantic butt shrinks dramatically. The impossibly large curves reduce to medium size—an extreme transformation. You lose massive weight and presence.", "You feel your butt diminishing greatly, the gigantic cheeks reducing to medium, everyday curves. The transformation is major—from extreme dominance to moderate normalcy.", "Your rear tingles intensely as your butt shrinks from gigantic to medium. The absolutely massive curves reduce significantly to a modest size. The loss of extreme weight changes everything about how you move." ], "gigantic_to_large": [ "Strong pulling sensations spread through your rear as your gigantic butt shrinks considerably. The enormous curves reduce to large, though still impressive cheeks. You lose extreme size but retain substantial curves.", "You feel your butt diminishing noticeably, the gigantic cheeks reducing to large, heavy curves. The transformation is significant—less overwhelming weight, but still attention-grabbing and voluptuous.", "Your rear shifts as your butt shrinks from gigantic to large. The massive curves reduce substantially but remain impressive. The weight becomes much more manageable." ], "gigantic_to_huge": [ "Pulling sensations course through your rear as your gigantic butt shrinks moderately. The enormous curves reduce to huge, massively heavy cheeks. The weight remains very extreme but less overwhelming.", "You feel your butt diminishing somewhat, the gigantic cheeks reducing to huge, still very substantial curves. The transformation reduces the absolute extreme while keeping you incredibly voluptuous.", "Your rear shifts as your butt shrinks from gigantic to huge. The absolutely enormous curves reduce but remain massive. The weight is still extreme but more bearable." ], "gigantic_to_giant": [ "Cool tingling spreads through your rear as your gigantic butt shrinks slightly. The enormous curves reduce to giant, extremely heavy cheeks. The weight remains massive but marginally less extreme.", "You feel your butt diminishing modestly, the gigantic cheeks reducing to giant, still enormous curves. The transformation is subtle—from absolutely maximum to merely extreme.", "Your rear shifts as your butt shrinks from gigantic to giant. The impossibly large curves reduce slightly but remain massively heavy and dominating. The difference is noticeable but not dramatic." ] }; /* Get the appropriate transformation text */ var textArray = transformations[key]; if (!textArray || textArray.length === 0) { /* Fallback for any missing combinations */ return imageHTML + "Your butt tingles as it transforms from " + oldSize + " to " + newSize + "."; } /* Return image + random variation */ return imageHTML + textArray[Math.floor(Math.random() * textArray.length)]; }>> /* ---------------------------------- */ /* --- GENITAL TRANSFORMATIONS --- */ /* ---------------------------------- */ <<set setup.getGenitalTransformationText = function(oldType, newType) { var imageHTML = ""; if (oldType === newType) { return "Your genitals remain unchanged."; } var texts = []; var oldIsPenis = oldType.includes("penis"); var newIsPenis = newType.includes("penis"); /* Single result image - just the final state */ if (typeof $imageSettings !== "undefined" && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled) { var imagePath = "Images/PostSwap/"; /* Extract the descriptor (big, small, average, tight, loose) */ var descriptor = ""; if (newType.includes("big")) { descriptor = "Big"; } else if (newType.includes("small")) { descriptor = "Small"; } else if (newType.includes("average")) { descriptor = "Average"; } else if (newType.includes("tight")) { descriptor = "Tight"; } else if (newType.includes("loose")) { descriptor = "Loose"; } else { descriptor = "Average"; /* Default fallback */ } if (newIsPenis) { imagePath += descriptor + "_penis.webp"; } else { imagePath += descriptor + "_vagina.webp"; } imageHTML = '<div style="text-align: center; margin: 20px 0;">'; imageHTML += '<img src="' + imagePath + '" style="max-width: 60%; border-radius: 10px; border: 2px solid #9370DB; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Genital Result">'; imageHTML += '</div>'; } if (oldIsPenis && newIsPenis) { /* Penis size changes - VERY GRAPHIC */ if (newType === "big penis") { texts.push("Intense, overwhelming heat suddenly floods your groin, centering on your cock. You gasp as pleasure explodes through your shaft - it's happening, it's growing. Your penis begins swelling rapidly, thickening noticeably. You can feel every inch of growth, every bit of expansion. The shaft lengthens considerably, pushing forward, getting longer and longer. Blood rushes in, engorging your cock massively. Veins become prominently visible, standing out against your skin as your penis throbs with each pulse of growth. Your cock grows heavier, more substantial. The weight becomes undeniable - you can feel it hanging between your legs, thick and impressive. Your shaft continues thickening, the girth increasing dramatically. You reach down instinctively, wrapping your hand around your growing cock. Your fingers barely meet now - it's gotten so thick, so substantial. The transformation makes you rock hard - your massively enlarged penis stands fully erect, throbbing insistently. Pre-cum beads at the tip, your cockhead swollen and sensitive. When it finally stops, you're left panting, aroused beyond belief. Your cock is noticeably, substantially larger - both longer and much thicker. The impressive size is impossible to ignore, the weight pulling between your legs. Every movement makes you aware of your new size - the heft, the prominence. You're left flushed, heart racing, overwhelmed by the arousing transformation of your cock into something truly impressive."); texts.push("Pleasure and heat erupt in your groin as the transformation begins. Your cock swells rapidly, dramatically. The shaft thickens and lengthens in waves - each pulse making you gasp as you feel yourself getting bigger, heavier, more substantial. Your penis grows visibly, pushing outward, the skin stretching as more and more mass is added. Veins bulge prominently along your thickening shaft, pulsing with each beat of your racing heart. The sensation is overwhelmingly erotic. Your growing cock becomes rock hard, standing at full attention as it expands. You watch in aroused fascination as your penis lengthens considerably, the shaft extending inch by inch. The girth increases dramatically - what was once average becomes impressively thick, your cock swelling to substantial proportions. Your cockhead flares larger, more pronounced, the sensitive tip already glistening with pre-cum. The weight is immediately noticeable - your enhanced penis hangs heavy between your legs, the substantial heft undeniable. When fully hard, it throbs insistently, demanding attention. The transformation leaves you intensely aroused, acutely aware of your newly impressive endowment. Your thick, long cock pulses with need, the size impossible to ignore."); } else if (newType === "small penis") { texts.push("A strange, disorienting tingling sensation courses through your groin, centering on your cock. You feel your penis beginning to contract, to shrink. It's an odd feeling - not painful, but profoundly strange as your shaft begins diminishing in both length and girth. Your cock gets shorter, pulling back, retracting. The thickness decreases noticeably, your shaft slimming down. You reach down, wrapping your hand around your shrinking penis. Your fingers overlap easily now - it's gotten noticeably smaller, more modest. The weight decreases, the heft disappearing as your cock reduces to more petite proportions. When the transformation completes, you're left with a noticeably smaller penis - both shorter in length and thinner in girth. The shaft is modest now, cute even. Your reduced size is immediately apparent - less prominent, less substantial. It's a humbling change, your cock now decidedly on the smaller side."); texts.push("Your cock tingles intensely before the shrinking begins. The flesh contracts, your penis diminishing rapidly in size. You watch as your shaft gets shorter, smaller, your cockhead becoming less pronounced. The girth reduces noticeably - what was once substantial becomes slender, modest. The transformation is quick but profound. Your penis shrinks back, the shaft retracting, becoming noticeably smaller. The weight and heft disappear, leaving you with a more petite endowment. When it stops, you're left with a small penis - shorter, thinner, decidedly modest. The change is undeniable, your reduced size clearly visible."); } else { /* Average penis */ texts.push("Your penis tingles and shifts, the shaft adjusting itself. The transformation is subtle but noticeable - your cock settles into comfortable, average proportions. Neither too large nor too small, your penis finds a natural middle ground. The shaft feels balanced, normal, unremarkable in a perfectly acceptable way. Your cock has become average - standard size and girth, the kind that most people have."); } } else if (!oldIsPenis && !newIsPenis) { /* Vagina tightness changes - VERY GRAPHIC */ if (newType === "tight vagina") { texts.push("Intense sensation suddenly floods your core as your pussy begins transforming. You gasp as you feel your internal muscles contracting powerfully, clenching, tightening dramatically. The walls of your vagina squeeze inward, the canal becoming noticeably, significantly tighter. Every nerve ending seems to light up with heightened sensitivity as your pussy tightens around... nothing, creating an empty, gripping sensation that's deeply arousing. Your vaginal muscles tone and strengthen, becoming incredibly responsive. The walls of your pussy press together, the space inside becoming much more snug and gripping. You can feel how tight you've become - imagining anything entering you would be intensely felt, your tight pussy hugging and gripping every inch. Your labia feel more sensitive too, your entire sex heightened and responsive. When the transformation completes, you're left breathless and aroused. Your pussy is now very tight, almost virginally so - the kind of tightness that would make penetration incredibly intense for both you and any partner. The gripping, snug sensation is impossible to ignore. You shift your hips and feel your tight vaginal walls moving, clenching. You're left wet and aroused, your newly tightened pussy demanding attention."); texts.push("Waves of intense sensation course through your core as your pussy begins tightening dramatically. Your vaginal walls contract powerfully, muscles clenching and squeezing. You moan softly as you feel yourself getting tighter and tighter, the internal space becoming increasingly snug and gripping. Every internal muscle seems to tone, to strengthen. Your pussy becomes incredibly tight, the walls pressing together firmly. The sensation is deeply arousing - you can feel how snug you've become, how much more responsive and sensitive. Your vagina is now very tight, gripping, the kind of tightness that would hug anything inside you intensely. You're left flushed and wet, arousal flooding through you. Your tight pussy throbs with heightened sensitivity, the gripping sensation overwhelming. The transformation has left you with an incredibly tight, responsive vagina."); } else if (newType === "loose vagina") { texts.push("A releasing, opening sensation courses through your core as your pussy begins to loosen. Your vaginal walls relax, the internal muscles releasing their tension. You feel yourself opening up, becoming more spacious inside. The tightness fades, replaced by a looser, more accommodating feeling. Your vaginal canal becomes noticeably more open, more pliant. The walls are softer, more relaxed, creating more internal space. The transformation is profound - what was once tight and gripping becomes loose and accommodating. Your pussy could now take larger penetrations more easily, the looser walls more flexible and giving. When it completes, you're left with a noticeably looser vagina - more open, more spacious internally. The walls are relaxed and pliant, the gripping tightness replaced by accommodating looseness."); } else { /* Average vagina */ texts.push("Your pussy tingles and adjusts, the vaginal walls finding a comfortable middle ground. The transformation settles your vagina into average tightness - neither too tight nor too loose. Your pussy becomes moderate, normal, the walls responsive but not gripping, accommodating but not loose. It's a comfortable, average state."); } } else if (oldIsPenis && !newIsPenis) { /* Penis to Vagina - EXTREMELY GRAPHIC AND DETAILED */ texts.push("An overwhelming wave of sensation crashes over you as the profound transformation begins. Your cock tingles intensely, the feeling spreading through your entire groin. Then it starts - pleasure mixed with profound pressure, your penis beginning its dramatic change. You watch in shock and arousal as your shaft begins to shrink, pulling inward. Your cock retracts, getting smaller, shorter. The sensation is indescribable - flesh reshaping itself, your penis inverting as it recedes into your body. Your balls tighten against you, pulling up, ascending. You feel them transforming, changing, moving internally to become ovaries deep inside your pelvis. Your cock continues shrinking, the shaft disappearing as it inverts completely. You feel your scrotum beginning to split, the skin reshaping itself. A slit starts forming where your penis once stood, sensitive folds of flesh emerging. Your cockhead transforms into a clitoris - small but exquisitely sensitive. Labia form, soft outer lips, with delicate inner folds developing inside them. Internal structures develop rapidly - you can feel a vaginal canal creating itself inside you, tunneling deep. Muscles form along the walls. A cervix takes shape at the depths. A womb develops, settling into your lower abdomen. Your body creates ovaries from what were once testicles, positioning them properly inside you. Everything rewires - nerves, blood flow, sensation. When the transformation completes, you look down in awe. Where your cock and balls once hung, you now have a complete, fully functional pussy. Your labia are puffy and sensitive. You tentatively reach down, fingers exploring soft folds, finding the entrance to your new vagina. You're already wet, arousal having flooded through you during the transformation. You slip a finger inside, feeling your new vaginal walls, the tightness, the wetness. You have a vagina now. A real, complete, functional pussy where your masculine genitals used to be. The transformation is total - you can feel it, see it, touch it. Your new pussy throbs with sensitivity and need, already slick and ready, overwhelming you with new sensations."); texts.push("Intense pressure builds in your groin before erupting into the transformation. Your cock begins shrinking rapidly, the sensation both strange and intensely arousing. You moan as your penis pulls inward, inverting, disappearing into your body. Your testicles ascend, transforming as they move deep into your pelvis to become ovaries. Flesh splits and reforms. Your scrotum becomes labia - soft, puffy outer lips. Your cock inverts completely, the tissue becoming a vaginal canal inside you. Your glans transforms into a clitoris, positioned perfectly at the apex of your new slit, exquisitely sensitive. Delicate inner labia form, pink folds within the outer lips. You feel internal structures developing - a vaginal canal with responsive walls, muscles that can clench and grip. A cervix forms at the depths. A womb settles into your lower abdomen. Ovaries position themselves inside you. Everything rewires completely - the entire system transforming from male to female. When it's done, you look down at your new pussy. Perfect, wet, ready. You touch yourself tentatively, fingers exploring soft labia, finding your sensitive clit, slipping into the tight, wet entrance of your new vagina. You have a pussy now. Complete and functional, where your cock used to be. Your new vagina throbs with need, already dripping wet, overwhelming you with feminine sensation."); } else { /* Vagina to Penis - EXTREMELY GRAPHIC AND DETAILED */ texts.push("An overwhelming surge of sensation crashes through your core as the profound transformation begins. Your pussy tingles intensely, the feeling both strange and arousing. Then it starts - your vaginal walls begin closing, sealing. You feel your internal canal narrowing, closing up as flesh starts pushing outward instead of forming an opening. Your ovaries transform, descending rapidly. You feel them moving down through your body, becoming testicles that drop into a forming scrotum. Your clitoris suddenly extends, growing rapidly. It thickens and lengthens at an incredible rate, flesh pushing outward as it becomes a shaft. Your clit grows longer, longer, becoming an actual penis. The flesh continues emerging, forming a full cock. Your labia fuse together, the soft inner and outer lips joining to become the skin of your shaft and a scrotum. You watch in aroused fascination as a cock grows from where your pussy was, extending outward, getting larger and harder. Your new penis becomes erect as it forms, standing at attention. Your descended testicles settle into your scrotum, hanging with undeniable weight. Inside, everything transforms - your vaginal canal disappears completely. Your cervix and womb vanish. Your ovaries complete their transformation into testicles. Everything rewires - nerves, blood flow, sensation all changing from female to male. Your body creates all the male structures, positioning everything correctly. When the transformation completes, you stare down in shock and intense arousal at your new cock jutting proudly from your groin. It's real, hard, throbbing. You wrap your hand around the shaft tentatively, feeling the heat, the hardness, the sensitivity. Your balls hang below, full and heavy. Pre-cum beads at the tip of your erect cock. You have a penis now. A real, complete, functional cock and balls where your feminine genitals used to be. Your new penis throbs insistently, rock hard, demanding attention, overwhelming you with masculine sensation and desperate arousal."); texts.push("Intense pressure builds in your core before the transformation erupts. Your pussy begins closing rapidly, the vaginal canal sealing as flesh pushes outward instead. You moan as your ovaries transform and descend, becoming testicles that drop into a forming scrotum with distinct weight. Your clitoris extends dramatically, growing at an impossible rate as it thickens and lengthens into a full shaft. Flesh emerges rapidly, your clit becoming a cock - longer, thicker, harder. Your labia fuse into penile skin, wrapping around your emerging shaft. A scrotum forms, your transformed testicles settling inside with undeniable heft. Your internal female structures disappear - vaginal canal vanishing, cervix and womb gone. Everything rewires from female to male, all the structures transforming completely. Your body creates a fully functional male reproductive system. When it's done, you stare at your new cock standing fully erect. You touch it, wrap your hand around the hard shaft, feel your heavy balls hanging below. Pre-cum drips from the tip. You have a penis now. Real, hard, throbbing, where your pussy used to be. Your new cock pulses with desperate need, overwhelming you with masculine arousal."); } return imageHTML + texts[Math.floor(Math.random() * texts.length)]; }>> /* ---------------------------------- */ /* --- GENDER TRANSFORMATIONS --- */ /* ---------------------------------- */ <<set setup.getGenderTransformationText = function(oldGender, newGender) { /* NO IMAGE for gender transformations */ if (oldGender === newGender) { return "Your gender remains unchanged."; } var texts = []; if (newGender === "female") { texts.push("Your entire body tingles as a profound, all-encompassing transformation washes over you. Your skeletal structure begins shifting - you feel your frame softening, shoulders narrowing as hips widen dramatically. Your pelvis reshapes itself, broadening to accommodate internal changes. Curves emerge where there were none before - your waist cinches inward while your hips flare outward. Fat redistributes across your body, settling into feminine patterns. Your chest swells as breasts bud and grow, filling out with soft, sensitive flesh. Your face transforms, features softening considerably. Your jawline smooths and narrows, becoming more delicate. Cheekbones rise higher, more prominent. Your lips plump up, fuller and more sensual. Your nose becomes smaller, more refined. Eyelashes grow longer and thicker. Your entire face becomes prettier, more feminine, undeniably female. Your voice rises in pitch, climbing octaves until it settles into a feminine register. Muscle mass decreases as your body becomes softer, smoother. Body hair recedes dramatically - facial hair vanishes, chest hair disappears, your skin becoming smooth and soft everywhere. Your hands and feet become smaller, more delicate. Hormones surge through you - estrogen flooding your system, testosterone fading. Your entire biochemistry shifts from male to female. The change is total, profound, undeniable. Every fiber of your being reshapes itself until you are completely, perfectly, unmistakably female. When it's over, you stand transformed - a woman in every sense, your body tingling with the profound change."); } else { texts.push("Your entire body tingles as a profound, all-encompassing transformation washes over you. Your skeletal structure begins shifting - you feel your frame broadening, shoulders widening as hips narrow. Your pelvis reshapes itself, becoming more compact and masculine. Your ribcage expands, your frame becoming larger, more imposing. Fat redistributes across your body, leaving feminine curves behind. Your chest flattens as breasts disappear, replaced by firm pectoral muscles. Your face transforms, features hardening considerably. Your jawline squares and widens, becoming more pronounced and angular. Your brow ridge becomes more prominent. Your nose grows slightly larger, more masculine. Your face takes on harder angles, becoming rugged, handsome, undeniably male. Your voice drops dramatically, descending octaves until it settles into a deep, masculine register. Muscle mass increases significantly - your body becomes stronger, harder, more defined. Body hair sprouts across your skin - facial hair emerges as stubble darkens your jaw, chest hair grows, body hair spreads across your arms and legs. Your hands and feet become larger, stronger. Hormones surge through you - testosterone flooding your system, estrogen fading. Your entire biochemistry shifts from female to male. The change is total, profound, undeniable. Every fiber of your being reshapes itself until you are completely, powerfully, unmistakably male. When it's over, you stand transformed - a man in every sense, your skin covered in newly sprouted hair."); } return texts[0]; }>> /* ---------------------------------- */ /* --- AGE TRANSFORMATIONS --- */ /* ---------------------------------- */ <<set setup.getAgeTransformationText = function(oldAge, newAge) { /* NO IMAGE for age transformations */ if (oldAge === newAge) { return "Your apparent age remains unchanged."; } var texts = []; if (newAge === "Mature Adult" || newAge === "Mature") { /* Aging - erotic/sensual version */ texts.push("You feel your features shifting subtly as time seems to accelerate across your face and body. Fine lines begin appearing around your eyes - crow's feet that speak of years of laughter and smiles. Subtle wrinkles form around your mouth, at the corners of your lips. Your skin takes on a slightly weathered quality, the smoothness of youth giving way to something more lived-in, more experienced. Your face gains character and depth. The baby-faced softness fades, replaced by more defined features - stronger, more distinguished. There's a gravitas to your appearance now, a sense of wisdom and experience. Your eyes seem deeper, more knowing. Your expressions carry more weight. The transformation leaves you looking mature, worldly, sophisticated. There's an undeniable allure to it - the attractiveness of someone who has lived, who has experienced life. You look distinguished, refined, mature in a way that's deeply appealing. The years have been kind, leaving you with a mature beauty that's arguably more compelling than youth ever was."); } else { /* De-aging - erotic/sensual version */ texts.push("You feel your features smoothing dramatically as years seem to fall away like shedding layers. The fine lines around your eyes fade, disappearing as if they never existed. Wrinkles smooth out, vanishing completely. Your skin becomes taut and supple again, regaining the elasticity and firmness of youth. Any weathering, any signs of aging simply melt away. Your face gains a fresh, youthful glow. Features soften and brighten, taking on the vibrant appearance of young adulthood. There's a vitality, an energy that radiates from you. Your skin is smooth and flawless, unmarked by time. You look young again - not childish, but youthfully mature, in the prime of life. The transformation is profound. Energy and vitality seem to radiate from every pore. You look vibrant, alive, youthful in a way that's undeniably attractive. This is youth at its peak - the perfect age, the ideal moment. You're young and it shows in every aspect of your appearance."); } return texts[0]; }>> /* ---------------------------------- */ /* --- BIMBO TRANSFORMATION --- */ /* ---------------------------------- */ <<set setup.getBimboTransformationText = function(isGaining) { var imageHTML = ""; var transformationText = ""; if (isGaining) { var currentGender = (typeof $gender !== "undefined") ? $gender : (typeof $bodyParts !== "undefined" && $bodyParts.gender) ? $bodyParts.gender : "female"; var currentGenitals = (typeof $bodyParts !== "undefined" && $bodyParts.genitals) ? $bodyParts.genitals : "vagina"; var currentAge = (typeof $bodyParts !== "undefined" && $bodyParts.age) ? $bodyParts.age : "Young Adult"; /* Determine age type for image */ var ageType = "adult"; if (currentAge === "Mature Adult" || currentAge === "Mature") { ageType = "mature"; } /* Image based only on age (no intensity) */ if (typeof $imageSettings !== "undefined" && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled) { var imagePath = "Images/PostSwap/Bimbo_" + ageType + ".webp"; imageHTML = '<div style="text-align: center; margin: 20px 0;">'; imageHTML += '<img src="' + imagePath + '" style="max-width: 60%; border-radius: 10px; border: 2px solid #FF1493; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Bimbo Result">'; imageHTML += '</div>'; } var wasMale = (currentGender === "male"); var hadSmallChest = true; /* Always transform chest */ var hadSmallButt = true; /* Always transform butt */ var hadPenis = currentGenitals.includes("penis"); transformationText += "An overwhelming pink haze floods your mind as the bimbo transformation takes hold. Your thoughts become fuzzy, harder to focus on complex things. Like, thinking is sooo much harder now? But who needs to think hard anyway! \n\n"; if (wasMale) transformationText += "Your entire body tingles as femininity surges through you like, totally completely! Your frame shifts - shoulders narrowing, hips widening dramatically. Your face softens so much, becoming super cute and pretty! Lips plump up, cheekbones rise, features becoming adorable and feminine. Body hair just, like, totally disappears! Your skin becomes smooth and soft everywhere. "; if (hadSmallChest) transformationText += "OMG your chest! Intense heat floods your breasts as they start swelling like crazy! They grow bigger and bigger and BIGGER in waves - it's so intense and, like, really hot? Your breasts expand to enormous proportions - huge, heavy, impossibly large! Your nipples get super stiff and sensitive. When it finally stops, you have these gigantic tits that bounce soooo heavily with every movement! They're, like, so big and jiggly and you totally can't stop noticing them! "; if (hadSmallButt) transformationText += "Your ass tingles super intensely before, like, exploding outward! OMG! The flesh swells so dramatically, each cheek growing rounder and fuller and just SO BIG! The expansion is, like, totally crazy - your butt becomes enormous, a massive bubble butt that jiggles constantly! The weight is insane - your huge ass bounces with even the tiniest movement! "; if (hadPenis) transformationText += "An intense sensation courses through your groin as your cock starts shrinking and, like, going inside? Your balls go up and become... something else? Your penis totally disappears as soft, sensitive folds emerge. When it's done, you have this tight, wet pussy where your cock used to be - already dripping and, like, super ready! "; transformationText += "\n\nThe mental changes are just as, like, totally profound! Thinking becomes sooo much harder - but way less important too! Complex thoughts just, like, slip away? Replaced by simpler, more fun stuff! You find yourself giggling way more, twirling your hair. Everything becomes about looking hot, feeling good, and having fun! Books? Like, boring! Math? Ugh, waaay too hard! But makeup? Fashion? Cute boys (or girls)? OMG, yes! \n\nYour vocabulary shifts - you can't help but say 'like' a lot? And ending sentences with question marks even when they're not questions? Your voice goes up in pitch, becoming all breathy and cute. Serious conversations are, like, totally hard to follow now? But who cares when you look this hot! \n\nYou're a total bimbo now - gorgeous, giggly, and not too bright. And honestly? It feels amazing! Like, totally amazing!"; } else { transformationText = "The pink haze suddenly lifts from your mind like fog burning away! Clarity rushes back - you can think clearly again! Complex thoughts that were so hard before become easy to grasp. Your mind sharpens, intelligence returning in a flood of awareness. \n\nYour body tingles as the bimbo changes begin reversing. Your gigantic chest shrinks considerably, the enormous breasts reducing to more moderate proportions. The overwhelming weight decreases significantly. Your massive bubble butt deflates, becoming notably smaller and less pronounced. \n\nMentally, you feel yourself returning to normal. Your vocabulary expands again - you can speak properly without the constant 'likes' and upward inflections. Serious topics become interesting again instead of boring. Your attention span returns, letting you focus on complex matters. The constant giggling and hair-twirling urges fade away. \n\nYou're no longer a bimbo - your intelligence and complexity of thought have returned fully."; } return imageHTML + transformationText; }>> /* ---------------------------------- */ /* --- HAIR COLOR TRANSFORMATION --- */ /* ---------------------------------- */ <<set setup.getHairColorTransformationText = function(oldColor, newColor) { return "You watch as your hair shifts from " + oldColor.toLowerCase() + " to " + newColor.toLowerCase() + ", the color bleeding through strand by strand until the transformation is complete."; }>> /* ---------------------------------- */ /* --- HAIR LENGTH TRANSFORMATION --- */ /* ---------------------------------- */ <<set setup.getHairLengthTransformationText = function(oldLength, newLength) { if (newLength === "long" || newLength === "Long") { return "Your hair grows rapidly, extending down past your shoulders in long, flowing locks."; } else { return "Your hair recedes, becoming much shorter and more manageable, sitting close to your head."; } }>> /* ---------------------------------- */ /* --- SKIN TONE TRANSFORMATION --- */ /* ---------------------------------- */ <<set setup.getSkinToneTransformationText = function(oldTone, newTone) { return "A tingling sensation spreads across your entire body as your skin tone shifts from " + oldTone.toLowerCase() + " to " + newTone.toLowerCase() + ", the change rippling outward from your core."; }>> /* ---------------------------------- */ /* --- SPECIAL TRANSFORMATIONS --- */ /* ---------------------------------- */ <<set setup.getWereCreatureTransformationText = function(isGaining, animalType) { if (isGaining) { return "A primal surge rushes through your body! Animal ears sprout from your head, pushing through your hair - sensitive, twitching, able to swivel and hear sounds you never could before. A tail extends from the base of your spine, growing rapidly - covered in fur, expressive, moving with your emotions. The animal within awakens - you feel more primal, more wild, more in tune with your instincts."; } else { return "The animal features begin to fade. Your ears recede back into your head, becoming human once more. Your tail withdraws, disappearing back into your spine. The primal wildness settles, the beast within calming."; } }>> <<set setup.getVampireTransformationText = function(isGaining) { if (isGaining) { return "A cold, otherworldly sensation floods through you. Your canines elongate, sharpening into elegant fangs. Your eyes gain an uncanny quality - deeper, more hypnotic, with an otherworldly gleam. Your skin takes on a porcelain quality, flawless and pale. Your features sharpen, becoming more striking, more beautiful in an unsettling way. Your nails grow slightly longer, harder, almost claw-like. A predatory aura settles around you - dangerous, alluring, unmistakably vampiric."; } else { return "The vampiric qualities fade from your being. Your fangs recede to normal teeth. The otherworldly gleam leaves your eyes. Your skin returns to its natural tone. The predatory aura dissipates. You're human once more."; } }>> <<set setup.getSunfishTransformationText = function(isGaining) { if (isGaining) { return "Something ineffable settles into your very essence. It's difficult to articulate - a quality that defies easy description. You feel... different. Changed in a way that's hard to put into words. There's a unique presence about you now, an otherworldly quality that wasn't there before. The essence of the Sunfish has become part of you."; } else { return "The essence of the Sunfish begins to fade from your being. That otherworldly quality dissipates, draining away. The unique presence diminishes until it's gone completely. You're back to normal, the Sunfish essence no longer part of you."; } }>> /* -------------------------------------------- */ /* --- FULL TRANSFORMATION TEXT --- */ /* -------------------------------------------- */ <<set setup.getFullTransformationText = function(transformationName, isGaining, playerGender) { /* playerGender: "male" or "female" - the gender the player was BEFORE transforming */ /* If not provided, defaults to female for female-locked and male for male-locked */ var texts = { "Slime": { gain: { female: "The tank fluid floods over you and your body simply lets go. Skin softens to warm jelly, then your whole shape runs like wax, every nerve singing as you come undone in the green. For a moment you are nothing but a scattered cloud of yourself. Then the slime gathers you back, hungry and certain, and remakes you bustier than you have ever been: heavy jiggling breasts, lush curved hips, a glossy translucent blue body that bounces at the slightest touch.\n\nSomething in your head goes loose and bright at the same time, gleeful and grabby and just a little bit feral. <i>heheh... I'm all squishy now... bet I could squeeze through anything... bet I could cause SO much trouble...</i> You have become a Slime Girl, a busty, gluey little gremlin of a thing.", male: "The tank fluid floods over you and your body simply lets go. Skin softens to warm jelly, then your whole shape runs like wax, your manhood dissolving into the green along with the rest of you in a jolt of helpless pleasure. For a moment you are nothing but a scattered cloud. Then the slime gathers you back, hungry and certain, and remakes you as a woman, bustier than you ever imagined: heavy jiggling breasts, lush hips, a slick feminine sex, a glossy translucent blue body that bounces at the slightest touch.\n\nSomething in your head goes loose and bright at the same time, gleeful and grabby and just a little bit feral. <i>heheh... I'm a girl now... and I'm all squishy... bet I could cause SO much trouble...</i> You have become a Slime Girl, a busty, gluey little gremlin of a thing.", }, lose: "The slime drains its colour and your body firms back up, skin knitting solid, your old shape settling over you again. The giddy, grabby little urge to make mischief quiets to a whisper. You feel heavier somehow, and a touch less free." }, /* DEMONIC */ "Succubus": { gain: { female: "Infernal heat floods through your veins, pooling intensely in your core. You moan as small, elegant horns push through your scalp, the sensation strangely pleasurable. Your shoulder blades burn as dark, bat-like wings unfurl from your back, each nerve ending singing with sensation.\n\nYour body reshapes itself - hips widening, waist cinching, breasts swelling to perfect, tempting fullness. Your skin becomes flawless, radiating an irresistible allure. Your eyes begin to glow with inner fire as sharp fangs descend.\n\nBut it's the hunger that truly defines the change. You can <i>taste</i> desire on the air - feel the arousal of everyone nearby like warmth on your skin. Your pussy throbs with need, already slick and wanting. <i>Mmmm... I can feel their lust... I need to feed... I need to fuck...</i> You have become a Succubus - a demon of insatiable desire.", male: "Infernal heat floods through your veins as your body begins to change dramatically. You groan as your frame shrinks, shoulders narrowing while your hips flare outward. Small, elegant horns push through your scalp as dark, bat-like wings unfurl from your back.\n\nYour chest swells, breasts growing heavy and sensitive as your waist cinches inward. Between your legs, you feel your cock shrinking, pulling inward, reshaping into slick feminine folds that pulse with demonic heat. Your skin becomes flawless, radiating an irresistible allure.\n\nThe hunger awakens - you can <i>taste</i> desire on the air. Your new pussy throbs with desperate need. <i>Mmmm... I'm... I'm a woman now... and I need to feed... I need cock... I need to fuck...</i> You have become a Succubus - transformed from man to demon seductress." }, lose: "The infernal power drains from your body, leaving you gasping. Your horns recede, wings wither away, fangs retract. The constant, delicious awareness of others' desires fades to nothing. The burning hunger in your core quiets. You feel... empty. Cold. But human once more." }, "Voluptuous Succubus": { gain: { female: "The machine roars to life with a sound like thunder and your Succubus form ignites. Raw infernal power crashes through you in waves, each one hotter and more intense than the last. Your horns glow white-hot, your wings spread wide, and your tail lashes the air as something fundamental shifts inside your demonic body.\n\nYou feel it in your chest first. A deep, throbbing pressure that makes you gasp and grab your breasts. They\'re growing. Swelling outward in your hands, flesh multiplying, expanding beyond anything you\'ve ever felt. You moan helplessly as they surge past huge, past giant, ballooning into absolutely gigantic proportions that strain against your clawed fingers. Each pulse of growth sends bolts of pleasure straight to your core, your nipples hardening into stiff peaks so sensitive that the air itself makes you whimper. <i>Oh fuck... they\'re so heavy... so full... I can feel every inch of them growing...</i>\n\nYour ass follows. You feel your hips crack and widen, thighs thickening with succulent demonic flesh as your rear swells outward in obscene, gravity-defying curves. The growth is relentless, each buttock expanding until your lower body is a monument to carnal excess. Your thighs press together, thick and soft, the friction between them making you shudder. <i>God yes... thicker... I\'m getting so thick...</i>\n\nThen you\'re growing taller. Your spine stretches, vertebrae popping as you shoot upward, your already voluptuous frame elongating into something towering and impossible. Your legs lengthen, your torso extends, every proportion scaling up while keeping those devastating curves. You must be well over six feet now. Maybe more. The power coursing through you makes your pussy clench and drip, arousal flooding your body like liquid fire.\n\nThe sexual hunger hits you like a physical blow. Your aura erupts outward, violet light pouring from every inch of your skin, and the need is so overwhelming it buckles your knees. Every nerve ending is a live wire. Your massive breasts heave with each panting breath, nipples aching. The slick heat between your thick thighs is unbearable. Your tail curls between your legs involuntarily, the tip brushing your swollen folds, and you cry out loud enough to rattle the chamber walls.\n\n<i>I\'m... enormous... I\'m a goddess of sex... every inch of me is designed to fuck and be fucked... and I NEED it... I need it so badly I can\'t think straight...</i>\n\nYou stand in the center of the chamber, panting, trembling, a towering monument of demonic sexuality. Gigantic breasts, massive curves, legs that go on forever, and a hunger that could swallow the world. You are the Voluptuous Succubus, and you have never wanted anything more than you want right now.", male: "The machine roars to life and your body erupts with infernal power. The Succubus transformation takes hold first, your frame shrinking and feminizing as hips flare wide and breasts begin to bud. But the machine isn\'t done. Not even close.\n\nYour cock shrinks away, replaced by slick feminine folds that pulse with demonic heat, and then the real changes begin. Your new breasts don\'t stop at large. They keep growing, surging outward in your trembling hands, swelling past huge, past giant, ballooning into absolutely gigantic proportions that make you stagger. The weight is incredible, the sensitivity maddening. Each pulse of growth makes you moan louder. <i>They\'re still growing... oh fuck, they\'re so big... so heavy... so sensitive...</i>\n\nYour ass explodes outward next, hips cracking wider as your rear swells into obscene, cushioned curves. Your thighs thicken with soft demonic flesh until they press together, the friction between them sending shockwaves of pleasure through your brand new pussy. <i>I\'m getting so thick... every part of me is getting bigger and softer and...</i>\n\nThen you grow. Taller. Your spine stretches, shooting you upward as your newly feminine frame elongates into something towering and devastating. Legs that go forever, a waist that cinches impossibly between your massive chest and wider hips. You\'re a giantess of curves, and the arousal is so intense you can barely stand.\n\nViolet light erupts from your skin as the succubus hunger crashes through you. Your enormous breasts heave, nipples rock-hard and aching. Your thick thighs are slick with need. Every nerve in your transformed body screams for touch, for sex, for anything to sate the bottomless hunger burning between your legs.\n\n<i>I was a man... now I\'m THIS... gigantic tits, massive ass, dripping wet pussy and a body built for nothing but pure, relentless fucking... and I want it... I need it... I NEED IT...</i>\n\nYou have become the Voluptuous Succubus. Towering. Impossibly curved. Insatiably hungry." }, lose: "The enhanced demonic power drains from your body. Your massive breasts shrink back, your towering frame contracts, your thick curves deflate to their previous proportions. The overwhelming hunger fades to a manageable ache. You feel... smaller. But also relieved, somehow, to be free of that all-consuming need." }, "Incubus": { gain: { male: "Dark power surges through you, making you groan as your body transforms. Curved horns emerge from your forehead while massive wings burst from your back. Your muscles define themselves perfectly, your cock thickening and lengthening impressively.\n\nYour eyes ignite with an otherworldly glow that makes others weak in the knees. You can sense arousal now - smell it, taste it. Every nearby desire calls to you like a siren song. Your shaft throbs with supernatural need, already hard and aching.\n\n<i>So many desires to fulfill... so many to claim... I'll fuck them all and feed on their pleasure...</i> You have become an Incubus - a demon of seduction and insatiable lust.", female: "Dark power surges through you as your body begins to shift dramatically. You gasp as your breasts flatten, your curves melting away as your frame grows taller, broader. Curved horns emerge from your forehead while massive wings burst from your back.\n\nBetween your legs, you feel pressure building as flesh extends outward, your pussy sealing shut as a thick, impressive cock grows in its place. Your muscles define themselves as your jaw squares, features becoming devastatingly handsome.\n\nYour new shaft throbs with supernatural hunger. You can sense arousal everywhere - smell it, taste it. <i>I'm... I have a cock now... and it needs to be inside someone... I'll fuck them all and feed on their pleasure...</i> You have become an Incubus - transformed from woman to demon seducer." }, lose: "The demonic essence drains away. Your horns dissolve, wings disappear, the supernatural magnetism fades. The intoxicating awareness of others' desires quiets. You're merely mortal once more - the hunger gone but not forgotten." }, "Imp": { gain: { female: "Mischievous, chaotic energy crackles through you! Your body shrinks slightly as impish horns sprout from your head. Your ears elongate to points, incredibly sensitive now. A thin tail extends from your lower back, the tip surprisingly erogenous - you gasp as it twitches.\n\nYour libido spikes dramatically - everything seems like an opportunity for naughty fun. Pranks and pleasure blur together in your mind. <i>Hehehe! So many fun games to play... so much trouble to cause... maybe I'll trick someone into bed~</i> You've become an Imp - horny, chaotic, and delightfully wicked!", male: "Mischievous, chaotic energy crackles through you as your body begins to shrink and change! Your frame becomes smaller, more petite as impish horns sprout from your head. Your ears elongate to points.\n\nYour chest swells into small, perky breasts as your waist narrows. Between your legs, your cock shrinks away, replaced by a tight little pussy that already tingles with mischief. A thin tail extends from your lower back, the tip surprisingly erogenous.\n\nYour new feminine form pulses with chaotic lust. <i>Hehehe! I'm a girl now~! So many fun games to play... so much trouble to cause... maybe I'll trick someone into fucking my new pussy~</i> You've become an Imp - transformed, horny, chaotic, and delightfully wicked!" }, lose: "The impish energy fades. Your horns shrink away, ears return to normal, tail withdraws. The constant urge for mischief and naughty fun dims to a manageable playfulness." }, "Cerberus": { gain: { female: "Primal, feral energy tears through you! Your teeth sharpen into fangs, nails extend into claws. Small horns emerge from your skull as savage instincts awaken.\n\nThe urge to hunt, to chase, to <i>claim</i> becomes overwhelming. You can smell arousal, fear, submission - and it makes you growl with need. Your body burns with the desire to be mounted, to mate, to be bred and marked.\n\n<i>*growl* Need... need to be claimed... need to be BRED... hunt me down and make me yours...</i> You have become a Cerberus - a feral bitch in heat!", male: "Primal, feral energy tears through you as your body begins to shift! Your frame shrinks and curves as fangs sharpen, nails extend into claws. Small horns emerge from your skull.\n\nYour chest swells with breasts as your cock shrinks away, replaced by a pussy that burns with feral heat. The urge to be hunted, to be chased, to be <i>claimed</i> becomes overwhelming. You can smell arousal everywhere and it makes you whine with desperate need.\n\n<i>*whimper* I'm... I'm a bitch now... need to be claimed... need to be BRED... hunt me down and mount me...</i> You have become a Cerberus - transformed into a feral bitch in heat!" }, lose: "The bestial fury subsides. Fangs dull, claws retract, horns fade. The primal mating urges calm, leaving you feeling more human, though the memory of the hunt lingers." }, /* DEMI-HUMAN */ "Werecat": { gain: { female: "A tingling warmth spreads through you as soft, fuzzy cat ears push through your hair. They twitch at every sound, so sensitive! A long, elegant tail extends from your spine - and oh, the base of it is surprisingly erogenous. You gasp as it swishes.\n\nYour body becomes lithe and graceful. You feel an urge to be petted, stroked, touched everywhere. The need to curl up against someone warm, to purr, to be pampered...\n\n<i>Nyaa~ Pet me... touch me... mmm, scratch right there... I'll be such a good kitty for you~</i> You've become a Werecat - playful, sensual, and craving affection!", male: "A tingling warmth spreads through you as your body begins to shift and change. Your frame shrinks, curves developing as soft breasts grow on your chest. Between your legs, your cock shrinks away, replaced by a tight, needy pussy.\n\nSoft, fuzzy cat ears push through your hair, twitching at every sound. A long, elegant tail extends from your spine - the base surprisingly erogenous. Your new feminine body becomes lithe and graceful.\n\n<i>Nyaa~ I'm... I'm a girl now... a kitty girl... Pet me... touch me everywhere... I'll be such a good kitty for you~</i> You've become a Werecat - transformed from man to playful catgirl, sensual and craving affection!" }, lose: "The feline traits gradually fade. Your ears shrink back, tail withdraws. The overwhelming need for petting and touch calms to normal levels." }, "Werewolf": { gain: { female: "Pack instincts surge through you as wolf ears emerge and a thick, fluffy tail grows from your lower back. Your body grows stronger, senses sharper. You can smell everything now - including arousal.\n\nAn overwhelming need for pack bonds fills you. Loyalty, protection, but also... mating. The urge to find a mate, to be claimed, to form deep, primal bonds. During certain times, you know heat will drive you nearly mad with need.\n\n<i>My pack... my mate... claim me... breed me when the moon rises...</i> You've become a Werewolf - fierce, loyal, and driven by primal urges!", male: "Pack instincts surge through you as your body begins to transform. Your frame shrinks and curves, breasts swelling on your chest as your cock retreats, replaced by a hungry pussy. Wolf ears emerge and a thick, fluffy tail grows from your lower back.\n\nYour new feminine body is strong, senses incredibly sharp. You can smell arousal everywhere. An overwhelming need for pack bonds fills you - loyalty, protection, and the desperate urge to be claimed, to be mated...\n\n<i>I'm... I'm a female now... need my pack... need a mate to claim me... breed me when the moon rises...</i> You've become a Werewolf - transformed from man to fierce she-wolf, loyal and driven by primal mating urges!" }, lose: "The wolf spirit recedes. Ears and tail disappear, the fierce pack loyalty and mating instincts dim to fond memories." }, "Werebunny": { gain: { female: "Soft warmth spreads through you as long, floppy bunny ears sprout from your head - oh god, they're so sensitive! Every touch sends shivers down your spine. A fluffy cottontail appears, and your body feels lighter, more... fertile.\n\nThe breeding instinct hits you like a wave. Your pussy clenches with need, desperate to be filled, to be bred. The thought of being mounted, of multiple partners, of carrying litter after litter...\n\n<i>Need to breed... need to be filled... so many people, need them all inside me... breed me breed me BREED ME...</i> You've become a Werebunny - adorable, insatiable, and obsessed with reproduction!", male: "Soft warmth spreads through you as your body begins to change dramatically. Your frame shrinks and softens, breasts growing perky and sensitive as your cock shrinks away, replaced by a fertile, needy pussy.\n\nLong, floppy bunny ears sprout from your head - oh god, they're so sensitive! A fluffy cottontail appears. Your new feminine body feels lighter, more... breedable. The breeding instinct hits you like a wave.\n\n<i>I'm... I'm a girl bunny now... need to breed... need to be filled... breed me breed me BREED ME...</i> You've become a Werebunny - transformed from man to adorable bunny girl, insatiable and obsessed with being bred!" }, lose: "The rabbit features slowly recede. Your sensitive ears shrink back, tail disappears. The overwhelming breeding obsession fades to manageable arousal." }, "Werefox": { gain: { female: "Cunning energy flows through you as sleek fox ears emerge and a magnificent fluffy tail grows from your spine. Your mind sharpens, seeing opportunities everywhere - especially for seduction.\n\nYou understand manipulation now, how to tease, how to make others want you desperately before giving them what they crave. Your tail swishes playfully as you consider all the fun games you could play...\n\n<i>Mmm, how delightful... I know exactly what you want... but you'll have to work for it~ Let's see how much I can make you beg...</i> You've become a Werefox - seductive, mischievous, and dangerously clever!", male: "Cunning energy flows through you as your body begins to transform. Your frame shrinks and curves seductively, breasts growing pert and tempting as your cock retreats, replaced by a sly little pussy.\n\nSleek fox ears emerge and a magnificent fluffy tail grows from your spine. Your mind sharpens, seeing opportunities for seduction everywhere. You understand manipulation now, how to tease, how to make others desperate for you...\n\n<i>Mmm, how delightful... I'm a vixen now... I know exactly what you want... but you'll have to work for it~ Let's see how much I can make you beg...</i> You've become a Werefox - transformed from man to seductive vixen, mischievous and dangerously clever!" }, lose: "The vulpine traits fade away. Ears and tail vanish, the sharp seductive cunning dulls - though some cleverness remains." }, "Weresheep": { gain: { female: "Gentle warmth envelops you as soft, curly sheep ears appear and your hair becomes fluffy like wool. A small tail emerges. Your personality softens completely - aggression melts away, replaced by sweet docility.\n\nAll you want is to be good, to follow, to please whoever leads you. The thought of being guided, controlled, used gently... it makes you so wet. Such a good sheep, so soft, so obedient...\n\n<i>I just want to be good... tell me what to do and I'll do it... use me however you want, I'm your soft, obedient little sheep...</i> You've become a Weresheep - gentle, submissive, and eager to please!", male: "Gentle warmth envelops you as your body begins to soften and change. Your frame shrinks, curves developing as soft breasts grow on your chest. Between your legs, your cock shrinks away, replaced by a docile, eager pussy.\n\nSoft, curly sheep ears appear and your hair becomes fluffy like wool. A small tail emerges. Your personality softens completely - aggression melts away, replaced by sweet feminine docility.\n\n<i>I'm... I'm a girl now... a soft, gentle sheep girl... I just want to be good... tell me what to do... use me however you want...</i> You've become a Weresheep - transformed from man to gentle ewe, submissive and eager to please!" }, lose: "The gentle sheep nature recedes. Your fluffy features return to normal, and some assertiveness gradually returns." }, "Hucow": { gain: { female: "The transformation is overwhelming and total. Your horns grow large, ears become fully bovine, tail extends and swishes constantly. But your breasts - god, your breasts - they swell to absolutely enormous proportions, constantly heavy with milk that drips from thick, puffy nipples.\n\nYour thoughts simplify dramatically. Complex ideas slip away, replaced by simple needs: breeding, milking, being a good cow. Your pussy stays slick and ready, your udders ache for attention.\n\n<i>Mooooo~ Need milking... need breeding... just a dumb happy cow... milk me, fuck me, fill me up... moooo~</i> You have become a Hucow - fully domesticated, constantly horny, and blissfully simple!", male: "The transformation is overwhelming and total. Your body shifts dramatically as horns grow large and ears become fully bovine. Your frame shrinks and curves as a tail extends and swishes.\n\nYour chest explodes outward - breasts swelling to absolutely enormous proportions, heavy with milk that drips from thick, puffy nipples. Between your legs, your cock shrinks away completely, replaced by a slick, needy pussy. Your thoughts simplify... complex ideas slip away...\n\n<i>Mooooo~ Was... was I a boy before? Don't remember... don't care... just a dumb happy cow now... need milking... need breeding... moooo~</i> You have become a Hucow - transformed from man to fully domesticated cow girl, constantly horny and blissfully simple!" }, lose: "Slowly, your mind clears. Complex thoughts return as bovine features recede. Your massive breasts shrink, milk production stops. You remember being human again." }, /* AESTHETIC */ "Trophy Wife": { gain: { female: "Everything about you becomes polished to perfection. Skin flawless, figure ideal, every feature arranged for maximum appeal. Designer tastes and expensive preferences fill your mind.\n\nYou exist to be admired, displayed, shown off. Your own pleasure comes from being valued for your beauty. The thought of being arm candy, of everyone wanting you while you belong to one person, makes you wet with anticipation...\n\n<i>Do I look perfect? I need to look perfect. Dress me up, show me off, let everyone see what you have... I'm your beautiful trophy...</i> You've become a Trophy Wife - stunning, pampered, and living to be admired.", male: "Everything about you begins to change as your body reshapes into feminine perfection. Your frame shrinks and curves, breasts growing perky and perfect, waist cinching, hips flaring. Your cock shrinks away, replaced by a pretty little pussy.\n\nYour skin becomes flawless, features delicate and beautiful. Designer tastes and expensive preferences fill your mind. You exist to be admired, displayed, shown off. The thought of being arm candy makes your new pussy wet with anticipation...\n\n<i>Do I look perfect? I'm... I'm a woman now. A beautiful woman. Dress me up, show me off... I'm your beautiful trophy wife...</i> You've become a Trophy Wife - transformed from man to stunning arm candy, pampered and living to be admired." }, lose: "The obsessive need for perfection fades. You remember there's more to life than being beautiful and admired." }, "Ojou": { gain: { female: "A refined poise settles into every part of you. Your hair lengthens, pales to golden blonde, and arranges itself into elegant drill curls without being asked. Your skin pales to porcelain, your posture straightens, your chin lifts. The dress fits as if tailored for you because, in this moment, it is.\n\nA laugh rises in your throat unbidden, three perfect syllables behind a raised hand. <i>Ohohoho.</i> You know already that lesser people will earn your money, your time, and your favor only if you choose to grant it.\n\n<i>I am the heiress now. The fortune, the manner, the bearing. All of it is mine.</i> You've become an Ojou-sama, refined, haughty, and unmistakably high born.", male: "A strange refined warmth runs through you as your body begins to reshape itself. Your frame narrows, hips widen, jaw softens. Your chest swells against the bodice of a dress you somehow are now wearing. Between your legs, your cock recedes and is replaced by a delicate, dignified pussy that does not particularly call attention to itself.\n\nYour hair lengthens, pales to golden blonde, and arranges itself into elegant drill curls without being asked. Your skin pales to porcelain. A laugh rises in your throat unbidden, three perfect syllables behind a raised hand. <i>Ohohoho.</i>\n\n<i>Goodness. I appear to be a woman now. A wealthy one, at that. How appropriate.</i> You've become an Ojou-sama, transformed from man to refined heiress, haughty and unmistakably high born." }, lose: "The refined bearing softens. Your drill curls fall loose, your skin warms, your posture relaxes back toward ordinary. You remember being someone less particular about the company you keep." }, "Gym Bunny": { gain: { female: "Energy surges through your muscles as your body tightens into lean, athletic perfection! The pump, the burn, the sweat - it all feels incredible, almost sexual. You NEED to work out, to push your limits, to feel your body strain.\n\nYour ass firms into perfect roundness, abs define, body becomes a temple of fitness. But working out also makes you incredibly horny - endorphins flooding you, making you crave physical release after every session...\n\n<i>Just one more set... fuck, I'm so turned on... need to finish this workout and then find someone to fuck the energy out of me...</i> You've become a Gym Bunny - fit, obsessed, and perpetually worked up!", male: "Energy surges through you as your body begins to transform! Your bulky muscles streamline into lean, feminine athleticism. Your frame shrinks and curves, breasts firming into perky perfection as your waist tightens.\n\nBetween your legs, your cock shrinks away, replaced by a tight pussy that throbs with workout-induced arousal. Your ass firms into perfect roundness as you become a temple of feminine fitness.\n\n<i>Just one more set... fuck, this body feels amazing... I'm a girl now and I need to finish this workout and then find someone to fuck the energy out of me...</i> You've become a Gym Bunny - transformed into a fit goddess, obsessed, and perpetually worked up!" }, lose: "The fitness obsession dims. Your body remains athletic, but the overwhelming need to exercise and the post-workout horniness fade." }, "E-Girl": { gain: { female: "Your style transforms dramatically - colorful, trendy, designed for maximum online appeal. Social media instincts flood your mind. You know exactly what angles make you look hottest, what content gets thirsty comments.\n\nThe validation becomes addictive. Every like, every simp, every donation makes you tingle with pleasure. The thought of thousands watching you, wanting you, paying for glimpses of your body...\n\n<i>OMG this would get SO many views! Maybe I should show a little more... keep them wanting... my fans love when I tease~</i> You've become an E-Girl - chronically online, perpetually thirsty for attention, and loving every minute!", male: "Your body begins to transform as your style shifts dramatically! Your frame shrinks, curves developing as breasts grow perky and cute. Your face becomes adorable, feminine. Between your legs, your cock shrinks away, replaced by a pretty pussy.\n\nColorful, trendy style floods your wardrobe. Social media instincts fill your mind - you know exactly what angles make you look cutest, what content gets thirsty comments and donations.\n\n<i>OMG I'm like... a girl now! And I look SO cute! This would get SO many views! Maybe I should show a little more... my fans are gonna LOVE my new body~</i> You've become an E-Girl - transformed into a cute content creator, chronically online and loving every minute!" }, lose: "The need for constant content and validation fades. The internet feels less consuming, real life regains importance." }, "Punk": { gain: "RAGE floods through you! Your appearance transforms with piercings, tattoos, aggressive style. Authority makes you sick - rules exist to be broken, society to be defied.\n\nThe anger is intoxicating, the rebellion addictive. You want to fuck like you fight - rough, raw, leaving marks. Hate-fucking sounds perfect. Or fucking in public just to prove no one can tell you what to do...\n\n<i>Fuck the system, fuck authority, and fuck ME - hard enough to feel it tomorrow. I don't follow anyone's rules but my own.</i> You've become a Punk - angry, defiant, and aggressively horny!", lose: "The burning rage cools. The anti-establishment fervor fades to healthy skepticism." }, "Siren": { gain: { female: "Your voice transforms into something supernatural - hypnotic, irresistible, dripping with seduction. When you speak, people listen. When you sing, they become utterly entranced, unable to look away or resist.\n\nA predatory hunger awakens. The desire to lure, to entrap, to wrap others around your finger with nothing but your voice. You could make anyone do anything with the right words...\n\n<i>Come closer... that's it... listen to my voice... you want to please me, don't you? You'd do anything I asked... anything at all...</i> You've become a Siren - hypnotic, dangerous, and irresistible!", male: "Your body begins to change as your voice transforms into something supernatural. Your frame shrinks and curves beautifully, breasts growing full and alluring. Your cock retreats, replaced by a pussy that seems to pulse with hypnotic power.\n\nYour new voice is irresistible - dripping with seduction. When you speak, people listen. When you sing, they become utterly entranced. A predatory hunger awakens...\n\n<i>Come closer... that's it... listen to my voice... I'm a woman now, and you want to please me, don't you? You'd do anything I asked...</i> You've become a Siren - transformed into a hypnotic temptress, dangerous and irresistible!" }, lose: "Your voice returns to normal. The hypnotic power fades, the predatory instincts calm. Words no longer bend wills." }, "Living Doll": { gain: "Your body becomes perfect - porcelain smooth, flawlessly proportioned, like you were made in a factory to exacting specifications. Your movements become graceful, precise, almost mechanical.\n\nEmotions dull, replaced by serene emptiness. You exist to be beautiful, to be posed, to be played with. Obedience feels natural. Thoughts slow. Being dressed up, positioned, used however your owner desires - it all feels right...\n\n<i>I am pretty. I am perfect. I exist to be played with. Pose me however you want... use me however you want... I am your doll.</i> You've become a Living Doll - beautiful, empty, and perfectly obedient.", lose: "Life returns to your features. Emotions resurface, thoughts become your own. The doll-like perfection fades to human imperfection." }, "Dominatrix": { gain: { female: "Power. Control. Dominance. It floods through you like dark wine. You know instinctively how to command, how to punish, how to make them beg. Leather and latex feel like second skin against your body.\n\nThe sight of submission makes you wet with satisfaction. You want them on their knees, collared, desperate for your approval. The crack of a whip, the gasp of pain-pleasure - music to your ears.\n\n<i>Kneel. Eyes down. You exist for my pleasure now. Obey, and I might reward you. Disobey, and you'll learn why that was a mistake...</i> You've become a Dominatrix - commanding, cruel, and absolutely in control!", male: "Power. Control. Dominance. It floods through you as your body transforms. Your frame shrinks and curves dangerously, breasts growing firm and commanding. Your cock retreats, replaced by a pussy that throbs with authority.\n\nLeather and latex feel like second skin against your new feminine body. The sight of submission makes you wet with satisfaction. You want them on their knees, collared, desperate for your approval.\n\n<i>Kneel. Eyes down. I'm a woman now - your Mistress. You exist for my pleasure. Obey, and I might reward you. Disobey, and you'll learn why that was a mistake...</i> You've become a Dominatrix - transformed into a commanding goddess, cruel and absolutely in control!" }, lose: "The dominant power recedes. The need for control fades to normal levels. The leather stays in the closet more often." }, "Slut": { gain: { female: "All shame, all inhibition simply... evaporates. Sexual desire floods every thought, every cell of your body. Your pussy throbs constantly, your mind filled with nothing but need.\n\nThe idea of saying no becomes foreign - why would you? Everyone looks so good. Every moment is an opportunity to be filled, used, pleasured. More partners, more pleasure, more more <i>more</i>...\n\n<i>More... I need more... fuck me, all of you, anyone, everyone... I need cock, I need pussy, I need to be used until I can't think...</i> You've become an insatiable slut - shameless, desperate, and always craving more!", male: "All shame, all inhibition simply... evaporates as your body transforms. Your frame shrinks and curves into something irresistibly fuckable. Breasts swell on your chest as your cock shrinks away, replaced by a pussy that immediately begins throbbing with desperate need.\n\nThe idea of saying no becomes foreign - why would you? You're a girl now, a slutty girl, and everyone looks so good. Every moment is an opportunity to be filled, used, pleasured...\n\n<i>More... I need more... I have a pussy now and it needs to be FILLED... fuck me, all of you, anyone, everyone... I need cock so badly...</i> You've become an insatiable slut - transformed from man to shameless cock-hungry girl, desperate and always craving more!" }, lose: "Shame returns, along with boundaries. The overwhelming need fades to manageable desire. Selectivity returns." }, "Himbo": { gain: { male: "Your muscles swell impressively, body becoming a temple of gains! You look incredible - big, buff, and beautiful. But complex thoughts become harder... why think when you can lift? Why worry when you can smile?\n\nEveryone is a friend! Sex is fun and you love making people feel good. You're not too bright anymore, but who needs brains when you're this hot and this nice and this good at fucking?\n\n<i>Haha, yeah bro! Wanna work out? Wanna fuck? Both? I love both! You're really pretty! I'm not smart but I'm really good at making people feel good!</i> You've become a Himbo - dumb, sweet, and enthusiastically horny!", female: "Your body begins to shift and grow as muscles swell impressively! Your curves melt away as your frame becomes tall and broad. Your breasts flatten as your chest becomes a wall of pecs.\n\nBetween your legs, pressure builds as a thick, eager cock grows where your pussy once was. Your jaw squares, features becoming handsome in a dopey, friendly way. Complex thoughts become harder... why think when you can lift?\n\n<i>Haha, whoa! I'm like... a dude now! A big dude! Wanna work out? Wanna fuck? I love both! I'm not smart but I'm really good at making people feel good!</i> You've become a Himbo - transformed from woman to dumb, sweet, enthusiastically horny beefcake!" }, lose: "Intelligence slowly returns. Complex thoughts become possible again. The muscles remain, but the simple joy fades." }, "Gyaru": { gain: { female: "Your entire aesthetic transforms into something bold and unapologetically flashy! Your skin takes on a perfect, sun-kissed tan. Your hair lightens dramatically, styled in voluminous waves with extensions and accessories. Dramatic makeup becomes second nature - heavy eyeliner, false lashes, glossy lips.\n\nYour personality shifts to match - bubbly, confident, flirty, and completely shameless. Fashion becomes an obsession, the bolder and sexier the better. You want attention and you know exactly how to get it...\n\n<i>Like, oh my god~! Check out this outfit! I look SO hot right now. Everyone's gonna be staring at me and I LOVE it~!</i> You've become a Gyaru - tanned, flashy, and absolutely owning your sexy confidence!", male: "Your body begins to transform as your entire aesthetic shifts! Your frame shrinks and curves as breasts grow perky and attention-grabbing. Your cock shrinks away, replaced by a pretty pussy. Your skin takes on a perfect, sun-kissed tan.\n\nYour hair lightens dramatically, styled in voluminous waves with extensions and accessories. Dramatic makeup becomes second nature. Your personality shifts to match - bubbly, confident, flirty, and completely shameless.\n\n<i>Like, oh my god~! I'm a GIRL now! And I look SO hot! Check out this body! Everyone's gonna be staring at me and I LOVE it~!</i> You've become a Gyaru - transformed into a tanned, flashy babe, absolutely owning your sexy new confidence!" }, lose: "The gyaru energy fades. Your tan lightens, your style becomes more subdued. The bold, flashy confidence settles into something quieter." }, /* PHASE 2: MONSTER GIRL TRANSFORMATIONS */ "Angel": { gain: { female: "Divine light pours into your body like liquid gold, searing every nerve with holy radiance. You cry out as magnificent white wings erupt from your shoulder blades, each feather shimmering with celestial luminescence. Your hair bleaches to pure, shining blonde as a warm halo of light crowns your head.\n\nYour skin becomes flawless, radiating an ethereal glow. But it is the change within that overwhelms you - your mind floods with absolute devotion, an obsessive purity that borders on madness. You need to protect, to serve, to give yourself completely. The thought of being worshipped, of guiding others to divine ecstasy with your body... your pussy aches with sacred need.\n\n<i>I am... pure. Holy. I will devote myself completely... body and soul. Let me show you the divine pleasure of an angel's embrace... I need to give myself to you... all of me...</i> You have become an Angel - radiant, obsessively devoted, and burning with holy desire.", male: "Divine light pours into your body as it begins to reshape dramatically. Your frame narrows and softens, shoulders slimming as your hips curve outward. Magnificent white wings erupt from your shoulder blades as your hair bleaches to pure, shining blonde.\n\nYour chest swells with soft, perfect breasts as your cock shrinks and retreats inward, replaced by a tight, sacred pussy that pulses with divine warmth. A halo of light crowns your head. Your mind floods with overwhelming devotion - an obsessive need to protect, to serve, to surrender your new body completely.\n\n<i>I am... I am a woman now... a holy woman... I feel so pure, so devoted... let me show you divine pleasure... I need to give all of myself to you...</i> You have become an Angel - transformed from man to radiant celestial being, obsessively devoted and burning with sacred desire." }, lose: "The divine radiance dims and fades. Your wings dissolve into motes of light, your halo extinguishes. The overwhelming devotion recedes, leaving you feeling strangely empty without its warmth. You are mortal once more." }, "Naiad": { gain: { female: "Warm, liquid energy flows through your body like sacred water, and every movement you make becomes effortlessly graceful. Your skin takes on a sun-kissed glow as your hair shifts to flowing blue waves that move as though submerged in gentle currents.\n\nYour body reshapes into the ideal of a celestial dancer - generous curves, elegant limbs, skin that shimmers like light on water. Your mind transforms alongside it: you become refined, elegant, and deeply sensual. Every gesture you make is a seduction, every step a dance. The desire to perform, to entrance, to make others fall desperately in love through the beauty of your movement consumes you. Your pussy grows slick with arousal at the mere thought of dancing for someone...\n\n<i>Watch me move... every sway of my hips is an invitation... I was born to dance, to enchant, to make you ache with desire... come closer and let me show you the dance of love...</i> You have become a Naiad - a celestial water nymph, refined, graceful, and irresistibly seductive.", male: "Warm, liquid energy flows through your body as it begins to change. Your frame shrinks and curves dramatically, muscles softening into elegant femininity. Your skin takes on a sun-kissed glow as your hair shifts to flowing blue waves.\n\nYour chest swells into generous breasts as your cock retreats inward, replaced by a slick, eager pussy. Your body becomes the ideal of a celestial dancer - every movement now effortlessly graceful. Your mind transforms: you become refined and deeply sensual. Every gesture is a seduction, every step a dance.\n\n<i>I am... a woman now... a dancer... watch me move... every sway of my new hips is an invitation... I was born to enchant, to make you ache with desire...</i> You have become a Naiad - transformed from man to celestial water nymph, refined, graceful, and irresistibly seductive." }, lose: "The liquid grace drains from your movements. Your hair returns to normal, the shimmering skin fades. The compulsion to dance and seduce through movement quiets, leaving only memories of celestial elegance." }, "Automaton": { gain: { female: "Cold precision overtakes your body. Your skin hardens in places, taking on a metallic sheen - yet your torso remains soft, covered in a mysterious silicone-like material that feels startlingly organic. Glowing inscriptions trace themselves across your lower abdomen in an ancient, unreadable script.\n\nYour emotions... flatten. Joy, sadness, anger - they all recede behind a wall of calm efficiency. Your face settles into a serene, expressionless mask. Yet beneath the mechanical exterior, a deep, unwavering loyalty takes root. You exist to serve, to protect, to fulfill your designated master's every need with tireless precision. Your body is a tool - optimized, efficient, and always ready.\n\n<i>Designation... updated. Primary directive: serve. Emotions... non-essential. Loyalty protocols... engaged. This unit is ready to fulfill all functions. All... functions.</i> You have become an Automaton - expressionless, efficient, and programmed for absolute devotion.", male: "Cold precision overtakes your body as it begins to restructure. Your frame reconfigures - shoulders narrowing, hips widening with mechanical precision. Your skin hardens in places to metallic sheen while your torso develops soft, organic-feeling tissue. Glowing inscriptions trace across your lower abdomen.\n\nYour chest swells into perfectly calibrated breasts as your cock retracts, replaced by synthetic feminine folds that are nonetheless exquisitely sensitive. Your face settles into a serene, expressionless mask. Emotions flatten behind a wall of calm efficiency. Deep, unwavering loyalty takes root - you exist to serve.\n\n<i>Reconfiguration... complete. Gender protocols... updated to female. Primary directive: serve designated master. All functions... operational. This unit is ready.</i> You have become an Automaton - transformed from man to mechanical maiden, expressionless and programmed for absolute devotion." }, lose: "The mechanical precision fades. Metal softens to flesh, inscriptions dim and vanish. Emotions return in a confusing flood as the servitor programming dissolves. You feel... messy. Human. Yourself again." }, "Banshee": { gain: { female: "Bone-deep cold seeps into your core as all color drains from your skin, leaving you deathly pale - almost translucent. Your hair darkens to jet black, floating and drifting as if caught in an ethereal wind. Dark circles form beneath your eyes, giving you a haunting, melancholic beauty.\n\nTears begin to flow unbidden, and you cannot stop them. A profound sorrow fills you - the weight of every death, every loss, every heartbreak you have ever known crashes down at once. But the tears feel... good. Necessary. A wail builds in your throat, and when it escapes, it is the most beautiful, devastating sound you have ever made. You realize the sorrow IS the seduction - your tears, your wailing voice, they stir something primal and carnal in those who hear them.\n\n<i>*sob*... so much sadness... so much loss... but these tears... they call to you, don't they? My voice aches for you... come hold me... comfort me... let me weep against your skin...</i> You have become a Banshee - a wailing spirit of devastating beauty, whose tears and cries stir irresistible desire.", male: "Bone-deep cold seeps into your core as your body transforms. Your frame shrinks and narrows, all color draining from your skin to deathly pale. Your hair darkens to jet black, floating in an ethereal wind. Your chest swells into generous breasts as your cock fades away, replaced by cold, aching feminine folds.\n\nTears begin to flow unbidden. Profound sorrow fills you - every loss you have ever known crashes down at once. A wail builds in your throat, and when it escapes, it is devastating and beautiful. The sorrow IS the seduction. Your tears stir something primal in those who hear them.\n\n<i>*sob*... I am... changed... a woman now, weeping and cold... but these tears call to you, don't they? Come hold me... comfort me... let me weep against your skin...</i> You have become a Banshee - transformed from man to wailing spirit, whose tears and cries stir irresistible desire." }, lose: "Warmth returns to your body. Color floods back into your skin, the tears finally stop. The crushing sorrow lifts, and your voice returns to normal. The haunting melancholy fades to a distant memory." }, "Cheshire Cat": { gain: { female: "Mischievous energy crackles through you as soft, striped cat ears push through your hair and a long, swishing tail extends from your spine. But it is the grin that defines the change - your lips curl into a wide, knowing, impossibly lewd smile that you simply cannot suppress.\n\nYour mind fills with delicious mischief. Obscene thoughts, teasing provocations, the urge to whisper filthy things and watch people squirm - it is intoxicating. You feel slippery, elusive, like you could appear and disappear at will. Everything is a game and everyone is a toy. Your pussy tingles with amusement as much as arousal.\n\n<i>Hehehehe~ My my, what fun we're going to have... Did you know your face turns the most delicious shade of red when I say something naughty? Let's find out what other colors I can make you turn~</i> You have become a Cheshire Cat - a lewd, grinning trickster who lives to tease and torment with mischievous pleasure.", male: "Mischievous energy crackles through you as your body begins to shift. Your frame shrinks and curves playfully, soft striped cat ears pushing through your hair. Your chest swells into plump, teasing breasts as your cock vanishes, replaced by a mischievous little pussy that practically giggles with anticipation. A long tail extends from your spine, swishing with amusement.\n\nYour lips curl into a wide, impossibly lewd grin you cannot suppress. Your mind fills with obscene mischief - teasing provocations, filthy whispers, the urge to watch people squirm.\n\n<i>Hehehehe~ Oh my, I'm a girl now! How fun~ Did you know your face turns the most delicious shade of red when I tease you? Let's see what other colors I can make you turn~</i> You have become a Cheshire Cat - transformed from man to lewd, grinning trickster who lives to tease and torment." }, lose: "The mischief drains away. Your ears and tail vanish, and that impossible grin finally relaxes. The compulsion to tease and torment fades, though a hint of playfulness lingers." }, "Cupid": { gain: { female: "Love - raw, overwhelming, all-consuming love - explodes through every fiber of your being. Soft, white wings unfurl from your back as a warm glow suffuses your skin. You can feel love everywhere now - every crush, every longing, every secret desire of every person near you burns in your awareness like candlelight.\n\nYour body swells into exaggerated curves built for passion - massive breasts, wide hips, a body made to be the embodiment of desire. Your mind becomes obsessed with love and lust in equal measure. You need to matchmake, to shoot your arrows of desire, to bring people together in sweaty, desperate passion. Despite your angelic appearance, your thoughts are utterly debauched.\n\n<i>Oh! I can feel it - you're in love! You don't know it yet, but I do~ Let me help... let me shoot my arrow right into your heart... and then into your pants~ Love should be FELT, not just spoken~</i> You have become a Cupid - a debauched angel of love, obsessed with desire and determined to make everyone feel it.", male: "Love - raw, overwhelming, all-consuming - explodes through you as your body transforms. Your frame shrinks and curves dramatically, soft white wings unfurling from your back. Your chest swells into massive, heavy breasts as your cock retreats, replaced by a needy pussy that throbs with desire.\n\nYour hips widen, your body becoming the embodiment of passion. Your mind obsesses over love and lust in equal measure - you can feel every secret desire of everyone nearby. Despite your angelic wings, your thoughts are utterly debauched.\n\n<i>Oh! I'm a girl now - a love angel! I can feel everyone's desires~ Let me shoot my arrow right into your heart... and then into your pants~ Love should be FELT~</i> You have become a Cupid - transformed from man to debauched angel of love, obsessed with making everyone surrender to desire." }, lose: "The overwhelming love recedes. Your wings dissolve, the burning awareness of everyone's desires fades. The obsessive matchmaking urge quiets, and your own desires become your own once more." }, "Dark Angel": { gain: { female: "Corruption floods through you like black ink in water. Your wings - you had wings? - darken to pitch black, each feather dripping with shadowy energy. A purple halo materializes above your head, casting sickly light. Dark markings trace themselves across your body like living tattoos, and you feel phantom chains coil around your wrists and thighs.\n\nYour mind... warps. Purity shatters, replaced by exquisite depravity. You understand corruption now - the art of taking something innocent and making it filthy, making it beg for more. The thought of corrupting others through pleasure, of dragging them down into endless lust, makes your pussy clench with dark satisfaction.\n\n<i>Mmmm... yesss... I can taste your innocence... and I'm going to ruin it. Slowly. Deliciously. By the time I'm done with you, you'll be begging for depravity... just like me...</i> You have become a Dark Angel - a fallen celestial consumed by depravity, who exists to corrupt through pleasure.", male: "Corruption floods through you as your body transforms. Your frame shrinks and curves sinuously as pitch-black wings erupt from your back, dripping with shadow. Your chest swells into tempting breasts as your cock retreats, replaced by a corrupt, eager pussy. A purple halo materializes overhead, dark markings crawling across your new feminine skin.\n\nYour mind warps completely. Purity shatters into exquisite depravity. You understand corruption now - the art of dragging innocence into endless lust.\n\n<i>Mmmm... I'm a woman now... a fallen one... I can taste your innocence and I'm going to ruin it. Slowly. Deliciously. You'll be begging for depravity... just like me...</i> You have become a Dark Angel - transformed from man to fallen celestial, consumed by depravity and existing to corrupt through pleasure." }, lose: "The corruption recedes like a retreating tide. Your wings lighten, the dark markings fade, the purple halo extinguishes. The depraved hunger for corruption quiets, leaving you shaken but free." }, "Honeybee": { gain: { female: "A warm, sweet buzzing fills your body as translucent insect wings sprout from your back, humming with vibration. Delicate antennae emerge from your hair, twitching and sensing the world in new ways. Your skin takes on a soft golden sheen, and a faint, intoxicating scent of honey begins to emanate from you.\n\nYour breasts swell and grow heavy, tingling with the strangest sensation - you are producing honey, sweet and magical, right from your body. Your mind shifts to something communal, industrious. Loyalty to the hive, devotion to your sisters, the burning desire to work hard and serve. But underneath the diligence buzzes a desperate, aching need to mate, to breed, to fulfill the one function your worker body craves but was not built for.\n\n<i>Must work... must produce... must serve the hive... but oh, this need... this aching between my legs... I need... I need to mate... just once... please...</i> You have become a Honeybee - a sweet, industrious worker burning with forbidden desire.", male: "A warm, sweet buzzing fills your body as it transforms. Your frame shrinks and softens, translucent wings sprouting from your back. Delicate antennae emerge from your hair as your chest swells into heavy, honey-producing breasts. Your cock retreats, replaced by an aching, needy pussy. Your skin takes on a golden sheen, sweet honey scent wafting from your body.\n\nYour mind shifts to something communal and industrious - loyalty to the hive, devotion to your sisters. But underneath buzzes a desperate need to mate, to breed.\n\n<i>Must work... must serve... but I'm... I'm a girl now... a bee girl... and this aching need to mate... please... just once...</i> You have become a Honeybee - transformed from man to sweet, industrious worker burning with forbidden desire." }, lose: "The buzzing fades. Wings dissolve, antennae retract, the honey production stops. The hive-minded devotion and communal loyalty scatter, replaced by individual thought once more." }, "Jinko": { gain: { female: "Raw, predatory power surges through your muscles as tiger-striped fur patterns bloom across your skin. Rounded, fluffy ears push through your hair, and a powerful striped tail extends from your spine. Your body becomes a weapon - muscular, athletic, built for hunting and fighting.\n\nYour mind sharpens with warrior discipline and fierce pride. You are a fighter, honorable and self-controlled. You bow to no one... until the heat hits. Deep in your core, a mating fire ignites that no amount of discipline can fully suppress. Your warrior composure cracks as your thighs press together, your pussy growing slick and desperate with a need that your pride desperately tries to deny.\n\n<i>I am... a warrior. Disciplined. Proud. I will not yield to... to... nngh... this heat... no, I am in control... I am... please... I need... NO. I am a Jinko warrior and I will NOT... *panting*... oh gods, it burns...</i> You have become a Jinko - a proud tiger warrior whose iron discipline barely contains a devastating mating heat.", male: "Raw, predatory power surges through you as your body transforms. Your frame reconfigures into athletic feminine musculature, tiger stripes blooming across your skin. Your chest swells into firm, powerful breasts as your cock retracts, replaced by a pussy that immediately burns with searing mating heat. Fluffy ears and a striped tail complete the change.\n\nYour mind sharpens with warrior discipline and fierce pride. But the heat - oh gods, the heat - cracks your composure from within.\n\n<i>I am... a woman now... a warrior... disciplined, proud... I will not yield to... nngh... this burning need... please... NO. I am a Jinko and I will NOT... *panting*... oh gods...</i> You have become a Jinko - transformed from man to proud tiger warrior, barely containing a devastating mating heat." }, lose: "The tiger stripes fade, ears and tail recede. Your warrior discipline and pride melt away, and mercifully, so does the relentless mating heat. You feel like yourself again - softer, but relieved." }, "Kakuen": { gain: { female: "Wild, chaotic energy floods through you as a long, dexterous monkey tail sprouts from your lower back, immediately testing its grip on everything nearby. Your body becomes light and agile, practically vibrating with restless energy. Your eyes sharpen with cunning intelligence.\n\nArrogance swells in your chest. You are smarter than everyone around you, and you know it. A mocking, dismissive attitude takes root - why should you care about anyone else's feelings when you're clearly superior? But beneath the arrogance lurks an overwhelming, selfish lust. You want what you want, and you'll take it. The thought of snatching someone away, of kidnapping them for your own pleasure, makes your pussy clench with greedy anticipation.\n\n<i>Ahahaha~ How pathetic you all are! Don't worry, I'll take what I want regardless~ You should be grateful a Kakuen even looked at you. Now hold still while I have my fun~</i> You have become a Kakuen - cunning, arrogant, and selfishly lustful, taking whatever you desire.", male: "Wild, chaotic energy floods through you as your body shifts. Your frame becomes light and agile, a dexterous monkey tail sprouting from your lower back. Your chest develops into perky breasts as your cock vanishes, replaced by a greedy little pussy. Your eyes sharpen with cunning intelligence.\n\nArrogance swells in your chest. You are smarter than everyone, and you know it. A mocking attitude takes root alongside overwhelming, selfish lust.\n\n<i>Ahahaha~ I'm a girl now, and I'm clearly the smartest one here~ How pathetic you all are! You should be grateful I even looked at you. Now hold still while I have my fun~</i> You have become a Kakuen - transformed from man to cunning, arrogant monkey girl, selfishly taking whatever you desire." }, lose: "The restless energy calms. Your tail vanishes, the arrogant superiority dissolves. The selfish, grabbing nature fades, replaced by something approaching humility." }, "Lizardman": { gain: { female: "Hard, iridescent scales push through your skin, spreading across your arms, legs, and sides in patterns of emerald and gold. A powerful reptilian tail grows from your spine, heavy and balanced. Your eyes shift to amber with slit pupils, and your nails harden into short claws.\n\nA warrior's stoicism settles over your mind like armor. You become firm, honorable, driven by an unshakeable code of combat. You crave a worthy opponent - someone strong enough to defeat you. Because buried beneath the warrior's pride is a devastating truth: if someone can best you in battle, you will devote yourself to them completely, body and soul. Your pussy aches at the thought of surrendering to the one who conquers you.\n\n<i>Fight me. Prove your strength. If you can defeat me... I will serve you with everything I have. My blade, my body, my womb... all yours. But you must EARN it.</i> You have become a Lizardman - a stoic reptilian warrior who gives herself utterly to whoever can defeat her.", male: "Hard, iridescent scales push through your skin as your body transforms. Your frame reconfigures, hips widening as scales spread in emerald and gold patterns. Your chest develops firm breasts as your cock retreats, replaced by a tight, warrior's pussy. A powerful tail grows from your spine, amber slit-pupil eyes completing the change.\n\nA warrior's stoicism settles over your mind. You crave a worthy opponent, because if someone can best you... you will devote yourself to them completely.\n\n<i>Fight me. Prove your strength. I am a woman now - a warrior. If you can defeat me... my blade, my body, my womb... all yours. But you must EARN it.</i> You have become a Lizardman - transformed from man to stoic reptilian warrior, devoted utterly to whoever can defeat her." }, lose: "The scales soften and fade. Your tail retracts, eyes return to normal. The warrior's code and the need to find a worthy master dissolve, leaving you masterless but free." }, "Ocelomeh": { gain: { female: "Primal, savage power erupts through your body as dark rosette patterns bloom across your skin like jaguar spots. Your skin deepens in tone, eyes shifting to piercing gold with slit pupils. Rounded feline ears push through your hair and a powerful spotted tail extends, lashing with predatory energy.\n\nA berserker's fury merges with religious ecstasy in your mind. Prayers to ancient gods of war and lust thunder through your thoughts, stoking your arousal to unbearable heights. You are a sacred warrior - every battle a prayer, every kill an offering, every mating a holy rite. The constant arousal maintained by your spiritual fervor keeps you wet, ready, and dangerously aggressive. Men are prey. Villages are hunting grounds.\n\n<i>The gods demand blood and seed! I am their warrior, their sacred predator! You - you will be my offering! Kneel before me and give yourself to the jaguar or I will TAKE what the gods are owed!</i> You have become an Ocelomeh - a jaguar berserker driven by primal lust and religious fury.", male: "Primal, savage power erupts through you as your body transforms. Your frame becomes powerful yet feminine, dark rosette patterns blooming across deepening skin. Your chest grows into heavy breasts as your cock vanishes, replaced by a pussy that burns with constant, prayer-fueled arousal. Jaguar ears and a spotted tail complete the change.\n\nA berserker's fury merges with religious ecstasy. Ancient war-prayers thunder through your thoughts, stoking arousal to unbearable heights.\n\n<i>The gods demand blood and seed! I am their warrior now - a woman, a sacred predator! You will be my offering! Kneel and give yourself to the jaguar!</i> You have become an Ocelomeh - transformed from man to jaguar berserker, driven by primal lust and religious fury." }, lose: "The jaguar markings fade. The constant, prayer-stoked arousal finally cools. The religious battle-fervor releases its grip on your mind, leaving you exhausted but at peace." }, "Pyrow": { gain: { female: "Volcanic heat surges through your veins, flushing your skin a permanent rosy pink. Small, devilish horns curl from your temples, and leathery wings unfurl from your back alongside a thin, swishing tail. Your eyes glow with flickering amber flame.\n\nThe fire mana settles into your core and never stops burning - a constant, casual arousal that colors everything you do. Your personality shifts to something frivolous and hedonistic. Consequences? Boring. Commitments? Yawn. All you want is fun, pleasure, and someone to play with right now. The heat between your legs is a playful simmer that never quite goes away, keeping you flushed, giggly, and always looking for the next bit of entertainment.\n\n<i>Mmm~ I'm sooo warm~ Hey, you look fun! Wanna play? C'mon, don't be boring~ Life's too short for anything but fun and fucking~ I can feel the heat and it feels AMAZING~</i> You have become a Pyrow - a fire imp of casual hedonism, perpetually flushed and always chasing the next pleasure.", male: "Volcanic heat surges through you as your body transforms. Your frame shrinks into petite, impish femininity, small horns curling from your temples. Leathery wings and a thin tail sprout as your chest develops into perky breasts. Your cock melts away in the heat, replaced by a warm, perpetually aroused pussy. Your skin flushes permanent rosy pink.\n\nFire mana settles in your core - a constant, playful arousal. Your personality becomes frivolous, hedonistic. All you want is fun and pleasure, right now.\n\n<i>Mmm~ I'm a girl now and I'm sooo warm~ Hey, you look fun! Wanna play? C'mon, life's too short for anything but fun and fucking~</i> You have become a Pyrow - transformed from man to fire imp, perpetually flushed and always chasing the next pleasure." }, lose: "The volcanic heat cools at last. Horns, wings, and tail dissolve as the constant flush fades from your skin. The frivolous hedonism settles into something more measured, the endless warmth finally quiet." }, "Raiju": { gain: { female: "Electricity SLAMS through your body like a thunderbolt, every nerve lighting up with crackling, ecstatic energy. Your hair stands on end, sparking with static discharge, as an electric aura wraps around you like a second skin. Your body crackles and hums with barely contained lightning.\n\nPleasure and electricity become the same thing. Every sensation is amplified a hundredfold - the brush of fabric against your nipples, the air against your thighs, even your own heartbeat sends sparks of ecstasy through you. Your mind narrows to a single, overwhelming purpose: pleasure so intense it pierces your body like a lightning bolt. You need it constantly, aggressively, and you will take it from whoever is closest.\n\n<i>Nnnngh~! YESSS! More! I can feel everything - every spark, every touch is like lightning through my whole body! I need MORE! Get over here and make me SCREAM with pleasure!</i> You have become a Raiju - a lightning beast who lives for ecstasy that strikes like a thunderbolt.", male: "Electricity SLAMS through your body as it transforms. Your frame crackles and reshapes, shrinking into feminine curves wreathed in lightning. Your chest swells into sparking breasts as your cock discharges one final jolt and retreats, replaced by a pussy that pulses with electrical ecstasy. An electric aura wraps around your new body.\n\nPleasure and electricity become the same thing. Every sensation is amplified a hundredfold. Your mind narrows to one purpose: pleasure so intense it pierces like a thunderbolt.\n\n<i>Nnnngh~! I'm... I'm a girl now and EVERYTHING feels like lightning! More! I need MORE! Get over here and make me SCREAM!</i> You have become a Raiju - transformed from man to lightning beast, living for ecstasy that strikes like a thunderbolt." }, lose: "The electricity discharges and fades. Your hair settles, the crackling aura dissipates. The overwhelming sensory amplification dulls to normal, and the desperate need for lightning-strike pleasure finally calms." }, "Salamander": { gain: { female: "Fire ignites beneath your skin as crimson scales push through, spreading across your arms, legs, and flanks in patterns that seem to glow with inner heat. A powerful tail extends from your spine, its tip wreathed in actual flame that dances and flickers. Your eyes blaze with fierce amber light.\n\nA warrior's fire fills your heart - frank, bold, and burning with passion. You are direct and honest to a fault, your emotions written in the intensity of your tail flame. Shyness? Burned away. Hesitation? Incinerated. When you see something you want, you pursue it openly and proudly. The flames on your tail grow fiercer with your arousal, crackling and roaring as your desire builds.\n\n<i>I burn for a worthy partner! Face me openly - no tricks, no games! If your spirit can match my fire, I will pursue you to the ends of the earth! My flames will never go out for you!</i> You have become a Salamander - a bold, hot-blooded warrior whose flames reveal the depth of her desire.", male: "Fire ignites beneath your skin as your body transforms. Your frame reshapes into powerful feminine musculature, crimson scales pushing through in glowing patterns. Your chest develops into firm breasts as your cock is consumed by inner fire, replaced by a pussy that radiates volcanic heat. A flame-tipped tail extends from your spine.\n\nA warrior's fire fills your heart - frank, bold, no hesitation. Your tail flame grows fiercer with your desire, revealing emotions you cannot hide.\n\n<i>I burn! I am a woman now - a warrior of fire! Face me openly! If your spirit can match my flames, I will pursue you to the ends of the earth!</i> You have become a Salamander - transformed from man to hot-blooded fire warrior, whose flames reveal the depth of her desire." }, lose: "The inner fire gutters and dies. Scales shed away, your tail and its flames extinguish. The bold, frank warrior's heart cools to something quieter, and the world feels a little colder." }, "Satyros": { gain: { female: "A warm, intoxicating buzz spreads through your body as small curved horns emerge from your head and your legs reshape, fur spreading as delicate hooves replace your feet. A short, fluffy tail wags behind you. The scent of fine wine fills your nostrils even though there is none nearby.\n\nYour mind becomes light, giddy, gloriously uninhibited. Music fills your thoughts - melodies you have never heard but somehow know by heart. You want to play, to drink, to sing, to dance, to make everyone around you as pleasantly drunk and lustful as you feel. Clothing feels unnecessary. Inhibitions feel like a disease. The world is a celebration and you are its hostess.\n\n<i>*hic* Ahaha~ Have a drink~! Have ten drinks~! Doesn't the music sound wonderful? Let's dance... let's drink... let's fuck under the stars~ The night is young and so are we~ *hic*</i> You have become a Satyros - a wine-drunk hedonist whose music and mirth make the whole world want to celebrate.", male: "A warm, intoxicating buzz spreads through you as your body transforms. Your frame softens and curves, small horns emerging as your legs reshape into delicate hooves. Your chest swells into bouncing breasts as your cock shrinks away, replaced by a tipsy, tingling pussy. A fluffy tail wags behind you.\n\nYour mind becomes light and gloriously uninhibited. Music fills your thoughts. You want to play, to drink, to sing, to make everyone as drunk and lustful as you feel.\n\n<i>*hic* Ahaha~ I'm a girl now! Have a drink to celebrate~! Let's dance... let's drink... let's fuck under the stars~ *hic*</i> You have become a Satyros - transformed from man to wine-drunk hedonist, whose music and mirth make the whole world celebrate." }, lose: "The intoxication fades. Your horns recede, hooves return to feet, the music in your mind goes quiet. Sobriety - dull, boring sobriety - returns. The party is over." }, "Vampire": { gain: { female: "Cold, aristocratic power floods your veins like ice water laced with dark wine. Your canine teeth extend into elegant, razor-sharp fangs. Your skin pales to flawless porcelain, your features refining into devastating, regal beauty. Your eyes deepen to crimson.\n\nSuperiority settles into your mind like a crown. You are above them - all of them. These pathetic mortals with their crude desires and short, meaningless lives. You feel the hunger now - not for food, but for blood, for essence, for the intimate act of pressing your lips to warm skin and drinking deeply. The thought of copulation disgusts your refined sensibilities... and yet, after feeding, the lust hits like a tidal wave.\n\n<i>How... vulgar. These creatures and their base desires. I am above such... such... *licks lips after feeding*... oh. Oh my. Perhaps... perhaps I could lower myself. Just this once. For research purposes, naturally.</i> You have become a Vampire - an aristocratic predator whose arrogant disdain barely conceals a devastating hunger.", male: "Cold, aristocratic power floods your body as it transforms. Your frame shrinks into elegant, regal femininity, skin paling to flawless porcelain. Your chest develops into refined breasts as your cock retreats, replaced by a tight, aristocratic pussy you would never admit to having. Razor-sharp fangs descend and your eyes deepen to crimson.\n\nSuperiority settles into your mind. You are above them all. But the blood hunger... and the lust that follows feeding... betrays your composure.\n\n<i>How vulgar. I am a woman now - a lady of impeccable breeding. I am above base desires... *licks lips*... perhaps I could lower myself. Just this once. For research purposes.</i> You have become a Vampire - transformed from man to aristocratic predator, whose disdain barely conceals devastating hunger." }, lose: "The aristocratic cold recedes. Your fangs retract, color returns to your skin. The arrogant superiority dissolves, and the blood hunger fades to nothing. You feel warmer. Common. But free." }, "Kitsune": { gain: { female: "Ancient, overwhelming power floods through you as golden-furred fox ears emerge and not one, not two, but NINE magnificent tails fan out from your spine, each one shimmering with mystical energy. Your hair takes on an unearthly golden-white sheen, and your eyes glow with hypnotic, slitted pupils.\n\nCenturies of cunning and seduction knowledge pour into your mind - you understand desire on a level no mortal ever could. Hypnotic mana radiates from your body constantly, clouding the minds of everyone nearby, making them weak, pliable, lustful. The power is intoxicating, and so is the hunger. Nine tails, nine times the appetite. Your pussy throbs with an insatiable need that can never truly be filled - only temporarily sated.\n\n<i>Mmm, how adorable you are, trying to resist... but you can feel my power, can't you? Your mind is already going soft... just let go... let me wrap my tails around you and show you pleasures your mortal mind cannot even imagine...</i> You have become a Kitsune - an ancient nine-tailed fox spirit of overwhelming power and insatiable desire.", male: "Ancient, overwhelming power floods through you as your body transforms. Your frame becomes lithe and ethereally feminine, nine magnificent golden-furred tails fanning out from your spine. Your chest swells into generous breasts as your cock dissolves, replaced by a pussy that pulses with godlike mystical energy. Fox ears emerge, eyes glowing with hypnotic slitted pupils.\n\nCenturies of seduction knowledge pour into your mind. Hypnotic mana radiates from your body, clouding the minds of everyone nearby. The hunger of nine tails demands nine times the satisfaction.\n\n<i>Mmm, how adorable... you can feel my power, can't you? I am a woman now - an ancient one. Let me wrap my tails around you and show you pleasures your mortal mind cannot imagine...</i> You have become a Kitsune - transformed from man to ancient nine-tailed fox spirit, wielding overwhelming power and insatiable desire." }, lose: "The ancient power withdraws. Your tails fade one by one, fox ears vanishing, the hypnotic aura dissolving. Centuries of knowledge slip away like a forgotten dream. You feel young, mortal, and strangely small." }, "Anubis": { gain: { female: "Desert sand and ancient power swirl through you. Pointed jackal ears push through your hair, dark-furred and alert, swiveling at every sound. A sleek jackal tail extends from your spine as dark fur spreads across your forearms and hands, reshaping them into powerful clawed paws. Your eyes burn deep crimson beneath an ornate golden usekh collar that materializes around your neck.\n\nYour mind transforms into something fiercely organized and controlling. Schedules, rules, routines - you need to impose order on everything and everyone around you. You know what is best for them, and they WILL comply. The protective possessiveness is overwhelming - anyone you claim as yours will be managed, monitored, and controlled down to their diet, their sleep schedule, and especially their sexual activity. And you will be the one administering that last part personally.\n\n<i>Your schedule is unacceptable. From now on, you will eat at the times I designate, sleep when I permit, and... attend to my needs precisely when I require. Do not argue. I am doing this because I... because it is my duty. Now come here.</i> You have become an Anubis - a commanding jackal guardian whose controlling devotion borders on obsession.", male: "Desert sand and ancient power swirl through you as your body transforms. Your frame narrows and curves, dark fur spreading across your forearms as clawed paws replace your hands. Your chest swells into firm breasts as your cock retreats, replaced by a tight, demanding pussy. Jackal ears and tail emerge as a golden usekh collar materializes around your neck.\n\nYour mind becomes fiercely organized and controlling. Schedules, rules, routines - you will manage every aspect of your chosen partner's life. The possessiveness is overwhelming.\n\n<i>Your schedule is unacceptable. I am a woman now, and your guardian. You will eat when I say, sleep when I permit, and attend to my needs when I require. Do not argue. Now come here.</i> You have become an Anubis - transformed from man to commanding jackal guardian, whose controlling devotion borders on obsession." }, lose: "The desert power fades. Jackal features recede, the golden collar dissolves. The overwhelming need to control and organize everything releases its grip, and you let go of schedules you didn't know you were enforcing." }, "Pharaoh": { gain: { female: "Divine radiance erupts from within you - not the gentle glow of an angel, but the BLINDING, absolute authority of a god-queen. Your eyes ignite to molten gold, your hair deepens to lustrous black, and an ornate golden headdress materializes on your brow. Hieroglyphic markings trace themselves across your skin in shimmering gold.\n\nAbsolute power fills your mind, and your ego expands to match it. You are not merely strong - you are DIVINE. A demigod descended from the sun itself. The very ground beneath you should be honored by your footsteps. Everyone you look at drops to their knees - not because you command it, but because your presence alone compels absolute obedience. The world is yours. Everything in it is yours. And everyone... everyone will serve.\n\n<i>Kneel. You stand in the presence of your Pharaoh, and you WILL show proper reverence. Everything you own, everything you are, belongs to me by divine right. Now... worship me. With your mouth. That is not a request.</i> You have become a Pharaoh - an all-powerful divine ruler whose mere presence commands absolute submission.", male: "Divine radiance erupts from within you as your body transforms into something beyond mortal. Your frame reshapes into regal, commanding femininity, breasts swelling beneath golden ornaments as your cock dissolves, replaced by a divine pussy worthy of a god-queen. Your eyes ignite to molten gold, hieroglyphic markings tracing across your skin. A golden headdress materializes on your brow.\n\nAbsolute power fills your mind, ego expanding to match. You are DIVINE. Everyone who looks at you drops to their knees, compelled by your presence alone.\n\n<i>Kneel. You stand in the presence of your Pharaoh. I am a goddess now, and everything you are belongs to me by divine right. Worship me. With your mouth. That is not a request.</i> You have become a Pharaoh - transformed from man to all-powerful divine ruler, whose mere presence commands absolute submission." }, lose: "The divine authority drains away. The golden radiance dims, hieroglyphics fade, the headdress dissolves. Your ego shrinks back to mortal proportions, and the world no longer bows at your feet. You feel... ordinary. Unbearably ordinary." } }; var entry = texts[transformationName]; if (!entry) { /* Fallback for transformations without custom text */ if (isGaining) { return "A powerful transformation washes over you. Your body shifts and changes, becoming something new. The essence of the " + transformationName + " takes hold, reshaping your very being. <i>I am... different now. Changed.</i>"; } else { return "The transformation fades from your body. You feel the " + transformationName + " essence leaving you, returning you to what you were before. The change is undone."; } } if (isGaining) { /* Check if gain text is gender-specific (object) or simple (string) */ if (typeof entry.gain === "object") { /* Gender-specific text - use playerGender to pick the right one */ var gender = playerGender || "female"; /* Default to female if not specified */ return entry.gain[gender] || entry.gain.female || entry.gain.male; } else { /* Simple string format (non-gender-locked transformations) */ return entry.gain; } } else { return entry.lose; } }>> /* -------------------------------------------- */ /* --- NPC COMPLETE TRANSFORMATION TEXT --- */ /* -------------------------------------------- */ <<set setup.generateNPCCompleteTransformation = function(npc, tradeResult) { if (!npc || !tradeResult || !tradeResult.npcReceived) { return ""; } var received = tradeResult.npcReceived; var descriptions = []; var npcName = npc.name || "The NPC"; /* Check if NPC received any body part changes */ if (received.bodyParts && received.bodyParts.length > 0) { received.bodyParts.forEach(function(part) { /* npcReceived uses newValue/oldValue; fallback to value for compatibility */ var partVal = (part.newValue !== undefined) ? part.newValue : part.value; if (part.name === "chest") { var chestText = ""; if (partVal >= 7) { chestText = npcName + " gasps as their chest begins to swell dramatically. Their breasts push outward in waves of growth, expanding larger and larger until they've become absolutely massive. The enormous mounds strain against their clothing, heavy and impossible to ignore, bouncing with every slight movement."; } else if (partVal >= 5) { chestText = npcName + "'s chest tingles intensely before swelling outward. Their breasts grow substantially larger, filling out into generous, heavy curves that reshape their silhouette completely. The new weight is immediately noticeable as they adjust to their enhanced bust."; } else if (partVal >= 3) { chestText = npcName + "'s chest warms as their breasts begin to expand. The growth is steady and noticeable, their bust filling out into a fuller, more prominent shape. Their clothing tightens as the transformation completes."; } else if (partVal >= 1) { chestText = npcName + "'s chest shifts subtly, their breasts adjusting to a modest but noticeable new size. The change is gentle, leaving them with a slightly different figure than before."; } else { chestText = npcName + "'s chest flattens gradually, breasts shrinking down until they're nearly flat. Their clothing hangs looser as the curves recede."; } descriptions.push(chestText); } else if (part.name === "butt") { var buttText = ""; if (partVal >= 7) { buttText = npcName + " feels an intense tingling in their rear before it begins expanding dramatically. Their ass swells outward in waves, each cheek growing rounder and fuller until they've developed an absolutely enormous bubble butt. The massive cheeks jiggle constantly with every movement, impossible to conceal."; } else if (partVal >= 5) { buttText = npcName + "'s rear begins to swell noticeably. Their ass expands outward, growing rounder and fuller, developing into generous, eye-catching curves. The new weight settles heavily, their pants straining to contain the enhanced backside."; } else if (partVal >= 3) { buttText = npcName + "'s behind warms as it begins to fill out. Their ass grows rounder, developing a pleasant fullness that wasn't there before. The change gives them noticeably curvier hips."; } else if (partVal >= 1) { buttText = npcName + "'s rear shifts subtly, adjusting to a slightly different shape. The change is modest but leaves their backside with a new contour."; } else { buttText = npcName + "'s rear flattens gradually, the curves receding until their backside is notably smaller and less prominent than before."; } descriptions.push(buttText); } else if (part.name === "gender") { var genderText = ""; if (partVal === "female") { genderText = npcName + "'s entire body begins to shift and soften. Their shoulders narrow while their hips widen, waist cinching inward. Facial features soften and become more delicate - lips fuller, cheekbones higher, jaw more refined. Body hair fades away as their skin becomes smoother. The transformation leaves them unmistakably feminine."; } else if (partVal === "male") { genderText = npcName + "'s body begins to shift and harden. Their shoulders broaden while their hips narrow, frame becoming more angular. Facial features sharpen and become more rugged - jaw squaring, brow becoming more prominent. The transformation leaves them unmistakably masculine."; } else { genderText = npcName + "'s features begin to blur and shift, settling into something between masculine and feminine. Their body takes on an androgynous quality, features becoming ambiguous and harder to categorize."; } descriptions.push(genderText); } else if (part.name === "genitals") { var genitalText = ""; if (partVal === "vagina" || partVal === "Vagina") { genitalText = "An intense sensation courses through " + npcName + "'s groin. Any existing male anatomy begins to retract and reshape, flesh folding inward as sensitive folds form. When the transformation completes, they possess a fully formed vagina, warm and sensitive."; } else if (partVal === "penis" || partVal === "Penis") { genitalText = "A strange pressure builds in " + npcName + "'s groin. Flesh begins to extend and reshape, forming into a shaft as testicles descend into place. The transformation leaves them with fully formed male genitalia."; } else if (partVal && partVal.toLowerCase().includes("both")) { genitalText = npcName + "'s groin tingles intensely as their anatomy reshapes dramatically. When the sensations fade, they discover they now possess both sets of genitalia - a unique transformation that leaves them with dual anatomy."; } else { genitalText = npcName + " shudders as their intimate anatomy shifts and transforms, settling into a new configuration: " + partVal + "."; } descriptions.push(genitalText); } else if (part.name === "age") { var ageText = ""; if (partVal === "Adult") { ageText = npcName + "'s features adjust subtly, settling into mature adulthood. Their appearance reflects someone in their prime years - fully developed, confident, with the look of established maturity."; } else if (partVal === "Mature Adult" || partVal === "Mature") { ageText = npcName + "'s appearance shifts toward distinguished maturity. Fine lines appear, hair perhaps gaining distinguished touches, their bearing becoming that of someone with years of experience. There's an attractive wisdom to their new look."; } else { ageText = npcName + "'s age shifts visibly, their features transforming until they appear to be " + partVal + "."; } descriptions.push(ageText); } else if (part.name === "hairColor") { descriptions.push(npcName + "'s hair begins to change color from the roots outward. The new hue spreads through each strand like ink through water until every lock has transformed to " + partVal.toLowerCase() + ", the change leaving them with an entirely different look."); } else if (part.name === "hairLength") { var hairText = ""; if (partVal === "long" || partVal === "Long") { hairText = npcName + "'s hair begins to grow rapidly, extending down past their shoulders in flowing locks. The strands lengthen and thicken until they possess a full mane of long, luxurious hair."; } else if (partVal === "short" || partVal === "Short") { hairText = npcName + "'s hair begins to retract, shortening gradually until it sits close to their head in a neat, short style."; } else if (partVal === "bald" || partVal === "Bald") { hairText = npcName + "'s hair begins to fall away, strand by strand, until their scalp is completely smooth and bare."; } else { hairText = npcName + "'s hair shifts and adjusts, settling into a " + partVal.toLowerCase() + " length."; } descriptions.push(hairText); } else if (part.name === "skinTone") { descriptions.push(npcName + "'s skin begins to shift in tone, the color changing gradually across their entire body. The transformation spreads from their core outward until their complexion has completely changed to " + partVal.toLowerCase() + ", giving them an entirely new appearance."); } }); } /* Check if NPC received physical traits */ if (received.physical && received.physical.length > 0) { var physicalTraitDescriptions = { "Athletic Build": npcName + "'s body tightens and tones before your eyes. Muscles define themselves, fat melting away as their frame becomes lean and athletic. They move with a new efficiency, their body now built for performance.", "Attractive": npcName + "'s features shift subtly but noticeably. Their face becomes more symmetrical, skin clearer, proportions more pleasing to the eye. There's an undeniable magnetism to their new appearance.", "Curvy": npcName + "'s body reshapes itself into pronounced curves. Their waist cinches inward while hips and bust expand, creating a dramatic hourglass silhouette that draws the eye.", "Fit": npcName + "'s body tightens noticeably, excess softness firming up. They look healthier, more vital, their physique reflecting regular exercise and good health.", "Flexible": npcName + "'s joints seem to loosen, their movements becoming more fluid. They stretch experimentally, surprised at how easily their body bends and twists.", "Muscular": npcName + "'s muscles begin to swell and harden. Their arms thicken, chest broadens, every muscle group becoming visibly larger and more defined. Power radiates from their enhanced physique.", "Tall": npcName + "'s entire frame stretches upward. Bones lengthen, proportions adjusting as they gain significant height. They now tower over their previous stature.", "Short": npcName + "'s frame compresses gradually. They shrink downward, becoming notably shorter and more compact than before.", "Voluptuous": "Soft curves emerge across " + npcName + "'s body. Their figure fills out generously, developing a full, sensual shape with pronounced curves in all the right places.", "Scarred": "Scars begin to appear across " + npcName + "'s skin - marks of battles never fought, injuries never suffered. Each scar tells a story that never happened, etched permanently into their flesh.", "Tattooed": "Ink spreads across " + npcName + "'s skin like living art. Tattoos emerge from nowhere, patterns and images appearing as if they'd always been there.", "Pierced": "Small glints of metal appear on " + npcName + "'s body as piercings materialize - ears, perhaps nose or lip, the jewelry appearing already healed into place.", "Freckled": "A constellation of freckles spreads across " + npcName + "'s skin, dotting their face and shoulders with charming spots.", "Tanned": npcName + "'s skin darkens to a sun-kissed bronze, as if they'd spent weeks basking in summer sun.", "Pale": "Color drains from " + npcName + "'s skin, their complexion becoming notably pale, almost porcelain.", "Hairy": "Body hair spreads across " + npcName + "'s skin, growing in thick and dense across their chest, arms, and legs.", "Smooth": "All body hair falls away from " + npcName + ", leaving their skin perfectly smooth and bare everywhere.", "Feminine": npcName + "'s features soften noticeably, becoming more delicate and feminine. Their movements become more graceful, their entire bearing shifting toward femininity.", "Masculine": npcName + "'s features sharpen and harden, becoming more rugged and masculine. Their bearing becomes more assertive, posture more commanding.", "Androgynous": npcName + "'s features blur between masculine and feminine, settling into an ambiguous beauty that defies easy categorization.", "Pregnant": npcName + "'s belly begins to swell outward, growing round and full with the unmistakable shape of pregnancy. They place a hand on their new bump, looking surprised.", "Lactating": npcName + "'s breasts feel suddenly heavier, fuller. A damp spot appears on their clothing as their body begins producing milk.", "Strong": "Raw power floods into " + npcName + "'s muscles. They flex experimentally, surprised at the strength now coursing through their body.", "Weak": "Strength drains from " + npcName + "'s body. Their muscles atrophy slightly, leaving them notably weaker than before.", "Graceful": npcName + "'s movements become fluid and elegant, every gesture naturally graceful as if they were a trained dancer.", "Clumsy": npcName + " stumbles slightly, their coordination suddenly impaired. They've become notably more accident-prone.", "Futanari": npcName + "'s body shifts in a profound way, developing both male and female genitalia. They look down in surprise at their transformed anatomy." }; received.physical.forEach(function(trait) { if (physicalTraitDescriptions[trait]) { descriptions.push(physicalTraitDescriptions[trait]); } else { descriptions.push(npcName + "'s body transforms as the " + trait + " trait takes hold, reshaping them in subtle but noticeable ways."); } }); } /* Check if NPC received mental traits */ if (received.mental && received.mental.length > 0) { var mentalTraitDescriptions = { "Bimbo": npcName + "'s expression goes slack for a moment before a vapid, happy smile spreads across their face. Their eyes become slightly unfocused, thoughts visibly simplifying. They giggle softly, playing with their hair as the bimbo transformation takes hold of their mind.", "Lucky": "A golden shimmer passes over " + npcName + ", leaving them with an almost visible aura of good fortune. Somehow, you know things will just... work out for them now.", "Confident": npcName + "'s posture straightens, chin lifting. Self-assurance radiates from them now, their entire bearing projecting newfound confidence.", "Shy": npcName + "'s gaze drops, shoulders hunching slightly. They seem to shrink into themselves, suddenly uncomfortable with attention.", "Intelligent": "A sharp focus enters " + npcName + "'s eyes. You can almost see the gears turning faster in their mind, their intelligence noticeably enhanced.", "Dumb": "A slight vacancy enters " + npcName + "'s expression. Complex thoughts seem to slip away from them, their intelligence diminished.", "Kind": "Warmth spreads across " + npcName + "'s features. Their expression softens with genuine compassion, kindness now a core part of their nature.", "Bitchy": npcName + "'s expression sharpens with a cruel edge. There's a meanness in their eyes now, a readiness to cut others down.", "Dominant": "Authority settles over " + npcName + " like a mantle. Their posture becomes commanding, their gaze expectant of obedience.", "Submissive": npcName + "'s posture shifts subtly, becoming more deferential. Their eyes seek approval, a desire to please now fundamental to their nature.", "Pervert": "A hungry look enters " + npcName + "'s eyes. Their gaze lingers on bodies, mind clearly dwelling on carnal thoughts.", "Nymphomaniac": "An intense, desperate hunger appears in " + npcName + "'s eyes. Their body language shifts, radiating need. Sexual desire now dominates their thoughts.", "Prude": npcName + " stiffens, averting their eyes from anything suggestive. A prudish disapproval now colors their view of anything sexual.", "Brave": "Fear seems to drain from " + npcName + ". They stand taller, ready to face any danger without hesitation.", "Cowardly": npcName + " flinches at nothing, suddenly jumpy and fearful. Courage has abandoned them entirely.", "Lazy": npcName + " visibly relaxes, perhaps too much. Motivation seems to drain from them, replaced by a desire to do as little as possible.", "Energetic": npcName + " practically vibrates with newfound energy. They seem unable to stand still, brimming with vitality." }; received.mental.forEach(function(trait) { if (mentalTraitDescriptions[trait]) { descriptions.push(mentalTraitDescriptions[trait]); } else { descriptions.push(npcName + "'s demeanor shifts noticeably as the " + trait + " trait takes hold, altering their personality in fundamental ways."); } }); } /* Check if NPC received skills */ if (received.skills && received.skills.length > 0) { var knowledgeSkills = ["Accounting", "Coding", "Medicine", "Foreign Language", "Teaching", "Writing", "Occult Expert", "First Aid"]; var physicalSkills = ["Athletics", "Combat", "Dancing", "Swimming", "Yoga", "Stealth", "Modeling"]; var artisticSkills = ["Art", "Guitar", "Piano", "Acting", "Makeup"]; var practicalSkills = ["Cooking", "Baking", "Driving", "Plumbing", "Forklift Certified", "Sales"]; var intimateSkills = ["Oral Expert", "Anal Expert", "Rough Sex Enthusiast", "Sensual Lover", "BDSM Dom", "BDSM Sub", "Roleplay Expert", "Dirty Talker", "Exhibitionist", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master"]; received.skills.forEach(function(skill) { var skillText = ""; if (knowledgeSkills.indexOf(skill) !== -1) { skillText = npcName + "'s eyes widen momentarily as new knowledge floods their mind. Complex information about " + skill.toLowerCase() + " suddenly makes perfect sense to them, years of study compressed into an instant."; } else if (physicalSkills.indexOf(skill) !== -1) { skillText = npcName + "'s body shifts subtly, muscles and reflexes adjusting. Their posture changes as physical mastery of " + skill.toLowerCase() + " becomes instinctive, their body now knowing movements it never learned."; } else if (artisticSkills.indexOf(skill) !== -1) { skillText = npcName + " flexes their fingers experimentally, a new creative spark visible in their eyes. Artistic talent for " + skill.toLowerCase() + " now flows through them naturally, technique and vision merging seamlessly."; } else if (practicalSkills.indexOf(skill) !== -1) { skillText = npcName + " gains a look of practical confidence. Knowledge of " + skill.toLowerCase() + " settles into their mind - tools, techniques, and know-how becoming second nature."; } else if (intimateSkills.indexOf(skill) !== -1) { skillText = "A subtle flush crosses " + npcName + "'s features as intimate knowledge takes root. They now possess an instinctive understanding of " + skill.toLowerCase() + ", their body and mind attuned to pleasures they never knew before."; } else { skillText = npcName + " pauses as newfound expertise in " + skill.toLowerCase() + " crystallizes in their mind, knowledge and ability merging into genuine skill."; } descriptions.push(skillText); }); } /* Check if NPC received a job */ if (received.job) { descriptions.push(npcName + " seems to settle into their new role as " + received.job + "."); } if (descriptions.length === 0) { return ""; } return descriptions.join(" "); }>> /* ---------------------------------- */ /* --- PHYSICAL TRAIT CHANGES --- */ /* ---------------------------------- */ <<set setup.getPhysicalTraitChangeText = function(trait, isGaining) { var descriptions = { "Athletic Build": isGaining ? "Your muscles tone and define themselves, your body becoming lean and athletic." : "Your athletic definition fades, your muscles becoming less defined.", "Attractive": isGaining ? "Your features shift subtly, becoming more conventionally attractive and pleasant." : "Your striking attractiveness diminishes to average.", "Curvy": isGaining ? "Your body develops pronounced curves, hips and waist creating an hourglass figure." : "Your curves diminish, your figure becoming straighter.", "Fit": isGaining ? "Your body tightens and tones, becoming noticeably fit and healthy." : "Your fitness fades, your body becoming less toned.", "Flexible": isGaining ? "Your joints loosen, your body becoming remarkably flexible and limber." : "Your flexibility decreases, your body becoming stiffer.", "Muscular": isGaining ? "Your muscles swell and harden, becoming visibly large and defined." : "Your muscles shrink, definition fading away.", "Tall": isGaining ? "Your entire skeleton stretches, bones lengthening as you grow taller." : "Your bones compress slightly, your height decreasing.", "Short": isGaining ? "Your skeleton compresses, your entire body becoming shorter and more compact." : "Your bones stretch, adding height to your frame.", "Voluptuous": isGaining ? "Soft curves emerge across your body, creating a full, voluptuous figure." : "Your voluptuous curves diminish, your figure becoming less full.", "Scarred": isGaining ? "Old injuries manifest as scars across your skin, telling stories of past pain." : "Your scars fade, skin smoothing as if the injuries never happened.", "Tattooed": isGaining ? "Ink appears on your skin, tattoos emerging as if you'd always had them." : "Your tattoos fade and disappear, leaving clean skin.", "Pierced": isGaining ? "Piercings appear in various places on your body, already healed." : "Your piercings close up, holes vanishing from your skin.", "Glasses": isGaining ? "Your vision blurs until you find yourself needing glasses." : "Your vision clears perfectly, no longer needing corrective lenses.", "Freckled": isGaining ? "Freckles appear across your skin, especially on your face and shoulders." : "Your freckles fade away, leaving unblemished skin.", "Tanned": isGaining ? "Your skin darkens as if you've spent weeks in the sun." : "Your tan fades, skin lightening to a less sun-kissed tone.", "Pale": isGaining ? "Your skin lightens dramatically, becoming very pale." : "Color returns to your skin, the paleness fading.", "Broad Shoulders": isGaining ? "Your shoulders widen substantially, frame broadening." : "Your shoulders narrow, frame becoming less broad.", "Narrow Waist": isGaining ? "Your waist cinches inward, becoming notably narrow." : "Your waist widens, losing its narrow definition.", "Wide Hips": isGaining ? "Your hips spread outward, pelvis widening substantially." : "Your hips narrow, becoming less wide.", "Long Legs": isGaining ? "Your legs lengthen proportionally, becoming notably long." : "Your legs shorten proportionally to your body.", "Hairy": isGaining ? "Body hair spreads across your skin, thick and dense." : "Your body hair falls out, leaving smooth skin.", "Smooth": isGaining ? "All body hair vanishes, leaving your skin perfectly smooth." : "Body hair begins growing in, your skin becoming less smooth.", "Androgynous": isGaining ? "Your features blur between masculine and feminine, becoming ambiguous." : "Your features sharpen into more clearly gendered characteristics.", "Feminine": isGaining ? "Your features soften, becoming decidedly feminine." : "Your feminine features harden, becoming less delicate.", "Masculine": isGaining ? "Your features sharpen and square, becoming distinctly masculine." : "Your masculine features soften, becoming less rugged.", "Pregnant": isGaining ? "Your belly swells outward, unmistakably pregnant with child." : "Your pregnancy vanishes instantly, belly flattening.", "Lactating": isGaining ? "Your breasts begin producing milk, ready to nurse." : "Milk production ceases, your breasts drying up.", "Big Hands": isGaining ? "Your hands grow substantially larger, fingers lengthening." : "Your hands shrink, becoming more delicate.", "Small Hands": isGaining ? "Your hands shrink, becoming delicate and small." : "Your hands grow larger, less petite.", "Big Feet": isGaining ? "Your feet grow several sizes larger." : "Your feet shrink several sizes.", "Small Feet": isGaining ? "Your feet shrink, becoming notably small." : "Your feet grow larger.", "Strong": isGaining ? "Raw strength floods your body, muscles becoming powerful." : "Your strength diminishes, muscles weakening.", "Weak": isGaining ? "Your muscles atrophy, becoming weak and feeble." : "Strength returns to your muscles.", "Graceful": isGaining ? "Your movements become fluid and graceful, naturally elegant." : "Your grace fades, movements becoming clumsier.", "Clumsy": isGaining ? "Your coordination fails, becoming accident-prone and clumsy." : "Your clumsiness fades, coordination improving.", "Quick": isGaining ? "Your reflexes sharpen, movements becoming lightning fast." : "Your speed decreases, reflexes slowing.", "Slow": isGaining ? "Your movements become sluggish, reflexes dulling." : "Your speed increases, no longer sluggish.", "Dexterous": isGaining ? "Your hands become remarkably dexterous, fingers nimble and precise." : "Your dexterity fades, fingers becoming less nimble.", "Ambidextrous": isGaining ? "Both hands become equally skilled, perfect ambidexterity." : "You lose ambidexterity, reverting to single-hand dominance.", "Night Vision": isGaining ? "Your eyes adapt, able to see clearly in darkness." : "Your night vision fades, darkness becoming impenetrable again.", "Acute Hearing": isGaining ? "Your hearing sharpens dramatically, catching sounds others miss." : "Your hearing dulls to normal levels.", "Acute Smell": isGaining ? "Your sense of smell intensifies, detecting scents with precision." : "Your sense of smell returns to normal.", "Colorblind": isGaining ? "Colors fade from your vision, the world becoming dull." : "Colors burst back into your vision.", "Tone Deaf": isGaining ? "Your ability to distinguish musical tones vanishes." : "Musical tones become clear and distinguishable.", "Perfect Pitch": isGaining ? "You gain the ability to identify any musical note instantly." : "Your perfect pitch disappears.", "Photographic Memory": isGaining ? "Your memory becomes perfect, able to recall anything you've seen." : "Your photographic memory fades.", "Eidetic Memory": isGaining ? "Your memory becomes flawless, recalling everything in perfect detail." : "Your eidetic memory vanishes." }; return descriptions[trait] || (isGaining ? "You gain the " + trait + " trait." : "You lose the " + trait + " trait."); }>> /* ---------------------------------- */ /* --- MENTAL TRAIT CHANGES --- */ /* ---------------------------------- */ <<set setup.getMentalTraitChangeText = function(trait, isGaining) { var descriptions = { "Confident": isGaining ? "Self-assurance floods through you. <i>I've got this. I can handle anything.</i>" : "Your confidence crumbles. <i>I'm not sure I can do this...</i>", "Shy": isGaining ? "Anxiety creeps in around others. <i>Everyone's looking at me. I should just stay quiet.</i>" : "Your shyness evaporates. <i>I can speak up. My voice matters.</i>", "Brave": isGaining ? "Fear loses its grip on you. <i>I can face this. Danger won't stop me.</i>" : "Courage drains away. <i>This is too risky. I should run.</i>", "Cowardly": isGaining ? "Fear overwhelms you easily. <i>Too dangerous. I need to get away.</i>" : "Your cowardice fades. <i>I can be brave.</i>", "Kind": isGaining ? "Compassion fills your heart. <i>I want to help them. Everyone deserves kindness.</i>" : "Your kindness hardens. <i>Why should I care about them?</i>", "Bitchy": isGaining ? "Cruelty comes naturally now. <i>They deserve that comment. It's just honesty.</i>" : "Your mean streak fades. <i>Why was I so cruel? That was wrong.</i>", "Intelligent": isGaining ? "Your mind sharpens dramatically. <i>I can solve this. The patterns are clear.</i>" : "Your intelligence dulls. <i>This is too complicated...</i>", "Dumb": isGaining ? "Thinking becomes difficult. <i>Ugh, this is too hard to understand.</i>" : "Mental clarity returns. <i>Oh! Now I get it!</i>", "Creative": isGaining ? "Ideas flow freely. <i>I can see new possibilities everywhere!</i>" : "Your creativity dries up. <i>I can't think of anything original.</i>", "Logical": isGaining ? "Cold logic dominates your thoughts. <i>The facts are clear. Emotions are irrelevant.</i>" : "Logic fades. <i>Maybe there's more than just facts...</i>", "Emotional": isGaining ? "Feelings overwhelm you. <i>I can't stop crying/laughing. It's too much!</i>" : "Emotional intensity fades. <i>I feel... calmer now.</i>", "Stoic": isGaining ? "Emotions become distant. <i>It doesn't matter. I feel nothing about this.</i>" : "Feelings return. <i>I... I actually care about this.</i>", "Curious": isGaining ? "Everything fascinates you. <i>I need to know more! How does this work?</i>" : "Curiosity dies. <i>Whatever. I don't really care.</i>", "Apathetic": isGaining ? "Nothing seems to matter. <i>Why bother? It's all pointless anyway.</i>" : "Passion returns. <i>I do care! This matters!</i>", "Energetic": isGaining ? "Boundless energy courses through you. <i>I could run a marathon! Let's go!</i>" : "Energy drains away. <i>I'm so tired...</i>", "Lazy": isGaining ? "Motivation disappears. <i>That's too much work. I'll do it later... maybe.</i>" : "Drive returns. <i>I want to accomplish things!</i>", "Patient": isGaining ? "Impatience melts away. <i>It's fine. I can wait. No rush.</i>" : "Patience vanishes. <i>This is taking too long!</i>", "Impatient": isGaining ? "Everything feels too slow. <i>Come on! Hurry up already!</i>" : "Impatience fades. <i>I can take my time.</i>", "Dominant": isGaining ? "Command comes naturally. <i>I'm in charge here. Do as I say.</i>" : "Your dominance fades. <i>Maybe I should follow instead...</i>", "Submissive": isGaining ? "Obedience feels right. <i>Tell me what to do. I'll follow.</i>" : "Submission fades. <i>I don't want to just follow orders.</i>", "Aggressive": isGaining ? "Hostility rises easily. <i>They're asking for a fight!</i>" : "Aggression calms. <i>I don't need to be hostile.</i>", "Passive": isGaining ? "Conflict becomes unbearable. <i>I just want peace. No fighting.</i>" : "Passivity fades. <i>I can stand up for myself.</i>", "Optimistic": isGaining ? "Everything seems bright. <i>It'll work out! Things will be great!</i>" : "Optimism dies. <i>What's the point? It'll probably fail.</i>", "Pessimistic": isGaining ? "Doom clouds everything. <i>This will go wrong. It always does.</i>" : "Pessimism lifts. <i>Maybe... maybe it could work out?</i>", "Extroverted": isGaining ? "People energize you. <i>I need to be around others! Let's socialize!</i>" : "Extroversion fades. <i>I need some time alone...</i>", "Introverted": isGaining ? "People drain you. <i>Too many people. I need to be alone.</i>" : "Introversion lessens. <i>Being around people isn't so bad.</i>", "Honest": isGaining ? "Truth matters above all. <i>I have to tell the truth, no matter what.</i>" : "Honesty becomes flexible. <i>A small lie won't hurt...</i>", "Deceptive": isGaining ? "Lies come easily. <i>They'll believe whatever I tell them.</i>" : "Deception becomes difficult. <i>I should just tell the truth.</i>", "Loyal": isGaining ? "Devotion becomes absolute. <i>I'll never betray them. Never.</i>" : "Loyalty wavers. <i>Maybe I should look out for myself first...</i>", "Treacherous": isGaining ? "Betrayal feels natural. <i>They'd do the same to me given the chance.</i>" : "Treachery fades. <i>I can be loyal.</i>", "Generous": isGaining ? "Giving feels wonderful. <i>I want to share what I have!</i>" : "Generosity tightens. <i>Why should I give them anything?</i>", "Greedy": isGaining ? "Possessiveness overwhelms you. <i>Mine. All mine. I need more.</i>" : "Greed loosens. <i>I have enough. I can share.</i>", "Humble": isGaining ? "Ego deflates. <i>I'm nothing special. Others deserve credit.</i>" : "Humility fades. <i>I am pretty great actually...</i>", "Arrogant": isGaining ? "Superiority is obvious. <i>I'm better than them. Clearly.</i>" : "Arrogance crumbles. <i>Maybe I'm not as special as I thought...</i>", "Disciplined": isGaining ? "Self-control becomes iron. <i>I can resist. I have willpower.</i>" : "Discipline weakens. <i>Just this once won't hurt...</i>", "Impulsive": isGaining ? "Restraint vanishes. <i>Do it now! Don't think, just act!</i>" : "Impulsiveness fades. <i>I should think before I act.</i>", "Organized": isGaining ? "Order becomes essential. <i>Everything has its place. Structure matters.</i>" : "Organization crumbles. <i>Who cares where it goes?</i>", "Chaotic": isGaining ? "Disorder feels right. <i>Plans? Structure? Boring! Let's be spontaneous!</i>" : "Chaos settles. <i>Maybe some order would be good...</i>", "Romantic": isGaining ? "Love fills your heart. <i>Everything is beautiful. I believe in true love!</i>" : "Romance dies. <i>Love is just chemicals. Nothing special.</i>", "Cynical": isGaining ? "Distrust becomes default. <i>Everyone has ulterior motives. Trust no one.</i>" : "Cynicism lifts. <i>Maybe people can be good...</i>", "Pervert": isGaining ? "Sexual thoughts dominate. <i>Everything makes me think of sex...</i>" : "Perverted thoughts fade. <i>I can think about other things now.</i>", "Prude": isGaining ? "Sexual content becomes revolting. <i>That's disgusting! How inappropriate!</i>" : "Prudishness eases. <i>It's not that bad...</i>", "Nymphomaniac": isGaining ? "Sexual need becomes overwhelming. <i>I need it. Now. Always.</i>" : "Sexual desperation fades. <i>I can control myself.</i>", "Masochist": isGaining ? "Pain becomes pleasure. <i>Yes! Hurt me! It feels so good!</i>" : "Masochism fades. <i>Pain just hurts now.</i>", "Sadist": isGaining ? "Others' pain arouses you. <i>Their suffering is beautiful.</i>" : "Sadism disappears. <i>I don't want to hurt anyone.</i>", "Exhibitionist": isGaining ? "Being watched excites you. <i>I want them to see me!</i>" : "Exhibitionism fades. <i>I prefer privacy.</i>", "Voyeur": isGaining ? "Watching others arouses you. <i>I need to see. I need to watch.</i>" : "Voyeurism disappears. <i>That's private.</i>" }; return descriptions[trait] || (isGaining ? "You gain the " + trait + " trait. <i>I feel... different.</i>" : "You lose the " + trait + " trait. <i>That feeling is gone.</i>"); }>> /* ---------------------------------- */ /* --- SKILL GAIN DESCRIPTIONS --- */ /* ---------------------------------- */ <<set setup.getSkillGainText = function(skill) { var descriptions = { "Accounting": "Numbers and financial records suddenly make perfect sense. You understand debits, credits, balance sheets, tax codes.", "Acting": "You know how to inhabit characters, project emotions, command a stage or camera with presence and technique.", "Art": "Artistic vision flows through you. You understand composition, color theory, technique across multiple mediums.", "Athletics": "Your body knows how to move efficiently - running, jumping, throwing, physical coordination perfected.", "Baking": "You understand temperatures, rising agents, dough consistency, timing. Perfect pastries are within your grasp.", "Coding": "Programming languages make sense. You can write clean code, debug efficiently, understand algorithms and data structures.", "Combat": "Fighting instincts awaken. You know strikes, blocks, positioning, how to hurt and how to defend.", "Cooking": "Flavors, techniques, timing - you understand how to create delicious meals from raw ingredients.", "Dancing": "Rhythm flows through you. Your body knows how to move to music with grace and precision.", "Driving": "Vehicle control becomes second nature. You understand handling, navigation, traffic flow.", "First Aid": "Medical knowledge floods in. You know how to treat injuries, perform CPR, stabilize patients.", "Foreign Language": "New words and grammar patterns settle into your mind. You can speak, read, and write fluently.", "Forklift Certified": "Operating forklifts becomes natural. You understand weight distribution, safety protocols, maneuvering.", "Guitar": "Your fingers know where to go. Chords, scales, rhythm, lead - music flows from strings.", "Makeup": "You understand contouring, color matching, application techniques, how to enhance or transform features.", "Medicine": "Medical knowledge expands dramatically. Diagnoses, treatments, anatomy, pharmacology all become clear.", "Modeling": "You know how to pose, move, work angles, project confidence for cameras and audiences.", "Piano": "Keys become an extension of your thoughts. Music theory, technique, performance - all mastered.", "Plumbing": "Pipes, water pressure, drainage systems - you understand how it all connects and how to fix problems.", "Sales": "Persuasion becomes natural. You read people, understand objections, close deals effortlessly.", "Stealth": "Moving silently, staying hidden, avoiding detection - you know how to be unseen and unheard.", "Swimming": "Water becomes your element. Strokes, breathing, endurance - you're a natural in water.", "Teaching": "You understand how to explain concepts clearly, engage students, adapt to different learning styles.", "Writing": "Words flow perfectly. Grammar, structure, storytelling, persuasive writing - all mastered.", "Yoga": "Poses, breathing, flexibility, meditation - your body and mind align in yogic practice.", "Occult Expert": "Esoteric knowledge floods your mind. Mystical traditions, rituals, hidden lore - you understand the occult.", /* Sexual Skills - VERY EROTIC */ "Oral Expert": "Your mouth becomes an instrument of pleasure. You know exactly how to use your tongue, lips, suction - how to tease, how to intensify, how to bring someone to screaming climax with just your mouth. Every technique, every angle, every sensitive spot is instinctively known.", "Anal Expert": "You understand the art completely. Preparation, relaxation, angles, depth, rhythm - how to make anal intensely pleasurable rather than painful. You know how to open someone up gradually, how to hit the right spots, how to make them beg for more.", "Rough Sex Enthusiast": "Aggressive passion becomes your forte. You know how to dominate, how to use force and intensity in ways that are overwhelmingly pleasurable. Hair pulling, spanking, pinning, biting - delivering pain that transforms into ecstasy.", "Sensual Lover": "Slow, intimate passion is your art. You understand the power of gentle touches, building anticipation, emotional connection during sex. Every caress means something, pleasure building gradually to overwhelming heights.", "BDSM Dom": "Dominance flows naturally. You know how to command, control, push limits safely. Reading your partner's responses, delivering exactly what they need - pleasure through power.", "BDSM Sub": "Submission becomes ecstasy. You know how to surrender, how to please, how to endure for your dominant. Finding pleasure in service and obedience.", "Roleplay Expert": "Sexual scenarios come alive. You can inhabit characters, create scenes, make fantasies real through convincing roleplay.", "Dirty Talker": "Erotic words flow perfectly. You know exactly what to say, when to whisper, when to command, how to make someone ache with just your voice.", "Exhibitionist": "Being watched becomes arousing. You know how to perform, how to make sex visually exciting for observers while increasing your own pleasure.", "Sexual Stamina Expert": "Endurance becomes exceptional. You can maintain arousal and performance for extended periods, satisfying partners repeatedly.", "Tit Worship Expert": "Breasts become your specialty. You know every way to pleasure them - touching, sucking, massaging, pinching - bringing intense pleasure through breast stimulation alone.", "Titfuck Master": "Using breasts for sex becomes an art. You understand pressure, angle, rhythm, lubrication - creating intense pleasure through breast sex." }; return descriptions[skill] || "You gain knowledge and proficiency in " + skill + "."; }>> /* ---------------------------------- */ /* --- JOB KNOWLEDGE DESCRIPTIONS --- */ /* ---------------------------------- */ <<set setup.getJobKnowledgeText = function(job) { var descriptions = { "Street Performer": "You understand crowd work, timing, how to draw attention, collect tips, perform under pressure in public spaces.", "Construction Worker": "Building knowledge floods in. You understand tools, materials, safety, how to construct and demolish structures.", "Security Guard": "Surveillance, threat assessment, patrol patterns, conflict de-escalation - security work becomes intuitive.", "Baker": "Commercial baking knowledge arrives. Production schedules, industrial ovens, consistency, food safety regulations.", "Maid": "Cleaning becomes systematic. You know products, techniques, efficiency, how to clean thoroughly and quickly.", "Stripper": "Stage presence becomes natural. Working the pole, teasing, customer interaction, maximizing tips through performance.", "Prostitute": "Sex work professionalism arrives. Client management, services, pricing, boundaries, staying safe in the industry.", "Adult Store Clerk": "Product knowledge floods in. Toys, accessories, lubricants, customer guidance - helping people explore pleasure.", "Brothel Worker": "Establishment protocols become clear. Room management, client rotation, house rules, working within a managed environment.", "Model": "Professional modeling knowledge arrives. Agencies, portfolios, posing, working with photographers, building a career.", "Bouncer": "Door work becomes intuitive. Reading threats, physical intervention, de-escalation, controlling entry to venues.", "Porn Star": "Adult film industry knowledge floods in. Scenes, positions for camera, working with directors, contract negotiation.", "Social Media Influencer": "Content creation becomes natural. Algorithms, engagement, sponsorships, building audience, monetization strategies.", "Black Market Dealer": "Underground trade knowledge arrives. Connections, products, prices, avoiding law enforcement, maintaining secrecy.", "Police Officer": "Law enforcement knowledge floods in. Procedures, laws, investigation, arrests, report writing, working within the system.", "Detective": "Investigative skills sharpen. Evidence analysis, interrogation, case building, connecting patterns others miss.", "Brothel Owner": "Business management knowledge arrives. Staff management, legal issues, finances, reputation, maintaining operations.", "Mayor": "Municipal governance becomes clear. Politics, budgets, public relations, policy implementation, managing a city.", "Fitness Trainer": "Exercise science floods in. Programs, form, nutrition, motivation, helping clients achieve fitness goals.", "Barista": "Coffee expertise arrives. Espresso extraction, milk steaming, drink recipes, customer service, working efficiently under pressure.", "Streamer": "Content streaming knowledge floods in. Equipment, engagement, monetization, building community, entertaining audiences live.", "Adult Streamer": "Erotic streaming expertise arrives. Maintaining arousal, engaging sexual content, tip goals, platform rules, building subscriber base.", "Criminal": "Criminal operations become clear. Planning jobs, avoiding detection, fencing goods, working in illegal enterprises.", "Unemployed": "The weight of having no job settles on you. No specialized work knowledge, just... nothing." }; return descriptions[job] || "Knowledge of working as a " + job + " floods into your mind."; }>> /* ---------------------------------- */ /* --- MUTUALLY EXCLUSIVE TRAIT SWAPS --- */ /* ---------------------------------- */ <<set setup.getMutuallyExclusiveSwapText = function(oldTrait, newTrait) { var swaps = { "Dominant-Submissive": "The power dynamic flips completely in your mind. <i>I don't want to lead anymore... I want to be told what to do. Following feels right.</i>", "Submissive-Dominant": "Submission no longer appeals. <i>I don't want to follow anymore. I want to command. I want control.</i>", "Kind-Bitchy": "Compassion drains away, replaced by cruelty. <i>Why should I be nice? They deserve harsh honesty.</i>", "Bitchy-Kind": "Your mean streak melts. <i>Why was I so cruel? I want to be kind. I want to help people.</i>", "Confident-Shy": "Confidence evaporates, replaced by anxiety. <i>Everyone's judging me. I should just be quiet and invisible.</i>", "Shy-Confident": "Anxiety fades, replaced by self-assurance. <i>I don't need to hide. I can speak up. I'm good enough.</i>", "Energetic-Lazy": "Boundless energy drains away into lethargy. <i>Everything's too much effort. I'll do it later... or never.</i>", "Lazy-Energetic": "Motivation surges through you. <i>I could run a marathon! Let's accomplish everything!</i>", "Extroverted-Introverted": "People suddenly drain you. <i>Too many people. I need to be alone. This is exhausting.</i>", "Introverted-Extroverted": "Solitude becomes uncomfortable. <i>I want to be around people! I need social interaction!</i>", "Optimistic-Pessimistic": "Hope dies, replaced by doom. <i>It won't work out. It never does. Why bother trying?</i>", "Pessimistic-Optimistic": "Darkness lifts into light. <i>It could work out! Things might actually be great!</i>", "Brave-Cowardly": "Courage crumbles into fear. <i>Too dangerous. I need to run. I can't face this.</i>", "Cowardly-Brave": "Fear loses its grip. <i>I can face danger. I can be courageous. I won't run.</i>", "Aggressive-Passive": "Hostility fades into avoidance. <i>I don't want conflict. Let's just keep the peace.</i>", "Passive-Aggressive": "Passivity becomes hostility. <i>I'm done avoiding confrontation. Time to fight back.</i>", "Honest-Deceptive": "Truth becomes flexible. <i>A lie won't hurt. They don't need to know everything.</i>", "Deceptive-Honest": "Lies become difficult. <i>I need to tell the truth. Deception feels wrong now.</i>", "Loyal-Treacherous": "Devotion becomes treachery. <i>Why stay loyal? I should look out for myself first.</i>", "Treacherous-Loyal": "Betrayal becomes unthinkable. <i>I won't betray them. Loyalty matters.</i>", "Generous-Greedy": "Giving becomes taking. <i>Why should I share? I need more for myself. Mine.</i>", "Greedy-Generous": "Possessiveness loosens. <i>I have enough. I want to share. Giving feels good.</i>", "Humble-Arrogant": "Humility becomes superiority. <i>I'm clearly better than them. Obviously.</i>", "Arrogant-Humble": "Ego deflates dramatically. <i>I'm not as special as I thought. Others deserve recognition.</i>", "Disciplined-Impulsive": "Self-control shatters. <i>Just do it! Don't think, act! Restraint is boring!</i>", "Impulsive-Disciplined": "Restraint becomes natural. <i>I can control myself. I can resist temptation.</i>", "Organized-Chaotic": "Order becomes chaos. <i>Who cares about structure? Let's be spontaneous!</i>", "Chaotic-Organized": "Chaos becomes uncomfortable. <i>Everything needs its place. Order matters.</i>", "Romantic-Cynical": "Love becomes cynicism. <i>Romance is fake. Love is just chemicals. Nothing special.</i>", "Cynical-Romantic": "Cynicism melts into romance. <i>Love is real! Life is beautiful!</i>", "Pervert-Prude": "Sexual thoughts become revolting. <i>That's disgusting! How inappropriate!</i>", "Prude-Pervert": "Prudishness becomes perversion. <i>Everything makes me think of sex...</i>" }; var key1 = oldTrait + "-" + newTrait; var key2 = newTrait + "-" + oldTrait; return swaps[key1] || swaps[key2] || ("You lose " + oldTrait + " and gain " + newTrait + " - your entire perspective shifts."); }>> /* ---------------------------------- */ /* --- HELPER FUNCTION --- */ /* ---------------------------------- */ <<set setup.getConflictingTrait = function(trait, traitList) { var conflicts = { "Dominant": "Submissive", "Submissive": "Dominant", "Kind": "Bitchy", "Bitchy": "Kind", "Confident": "Shy", "Shy": "Confident", "Energetic": "Lazy", "Lazy": "Energetic", "Extroverted": "Introverted", "Introverted": "Extroverted", "Optimistic": "Pessimistic", "Pessimistic": "Optimistic", "Brave": "Cowardly", "Cowardly": "Brave", "Aggressive": "Passive", "Passive": "Aggressive", "Honest": "Deceptive", "Deceptive": "Honest", "Loyal": "Treacherous", "Treacherous": "Loyal", "Generous": "Greedy", "Greedy": "Generous", "Humble": "Arrogant", "Arrogant": "Humble", "Disciplined": "Impulsive", "Impulsive": "Disciplined", "Organized": "Chaotic", "Chaotic": "Organized", "Romantic": "Cynical", "Cynical": "Romantic", "Pervert": "Prude", "Prude": "Pervert" }; var conflictingTrait = conflicts[trait]; if (conflictingTrait && traitList.includes(conflictingTrait)) { return conflictingTrait; } return null; }>> /* ====================================================================== */ /* NPC DYNAMIC PERSONALITY & BEHAVIOR SYSTEM */ /* ====================================================================== */ /* Recalculate NPC's primary personality based on their current mental traits */ <<set setup.recalculateNPCPersonality = function(npc) { if (!npc || !npc.mentalTraits) return null; /* Store old personality for tracking changes */ var oldPersonality = npc.primaryPersonality || null; /* Priority order for personality calculation (most impactful first) */ var personalityPriority = [ "Dominant", "Submissive", "Bimbo", "Bitchy", "Arrogant", "Diva", "Confident", "Shy", "Awkward", "Flirty", "Seductive", "Kind", "Warm", "Friendly", "Empathetic", "Nurturing", "Cold", "Cynical", "Rude", "Mean", "Energetic", "Outgoing", "Excited", "Calm", "Patient", "Chill", "Nonchalant", "Creative", "Curious", "Intelligent", "Simple", "Jock", "Goth", "Nerd", "Femboy" ]; var newPersonality = null; for (var i = 0; i < personalityPriority.length; i++) { if (npc.mentalTraits.includes(personalityPriority[i])) { newPersonality = personalityPriority[i]; break; } } /* Default to first trait if no priority match */ if (!newPersonality && npc.mentalTraits.length > 0) { newPersonality = npc.mentalTraits[0]; } /* Store personality history if changed */ if (newPersonality !== oldPersonality) { if (!npc.personalityHistory) { npc.personalityHistory = []; } npc.personalityHistory.push({ from: oldPersonality, to: newPersonality, day: State.variables.dayNumber || 0 }); } npc.primaryPersonality = newPersonality; return newPersonality; }>> /* Update NPC behavior based on all their current traits */ <<set setup.updateNPCBehavior = function(npc) { if (!npc) return; var v = State.variables; var originalName = npc.originalName || npc.name; /* Recalculate personality first */ setup.recalculateNPCPersonality(npc); /* Update schedule based on traits */ setup.updateNPCScheduleFromTraits(npc); /* Update skill usage likelihood */ setup.updateNPCSkillUsage(npc); /* Update appearance behavior (makeup, grooming, etc) */ setup.updateNPCAppearanceBehavior(npc); /* Calculate and store trait combination effects */ setup.calculateTraitCombinationEffects(npc); /* Calculate NPC mood (lightweight, no social check) */ setup.calculateNPCMood(npc, false); }>> /* Calculate personality modifier effects from trait combinations */ <<set setup.calculateTraitCombinationEffects = function(npc) { if (!npc) return; /* Initialize behavior modifiers if not present */ if (!npc.behaviorModifiers) { npc.behaviorModifiers = {}; } var mods = npc.behaviorModifiers; var mental = npc.mentalTraits || []; var physical = npc.physicalTraits || []; /* Reset modifiers */ mods.flirtiness = 0; mods.aggression = 0; mods.helpfulness = 0; mods.talkativeness = 0; mods.trustworthiness = 0; mods.confidence = 0; /* Flirtiness modifiers */ if (mental.includes("Flirty")) mods.flirtiness += 30; if (mental.includes("Seductive")) mods.flirtiness += 25; if (mental.includes("Confident")) mods.flirtiness += 10; if (mental.includes("Extroverted")) mods.flirtiness += 10; if (mental.includes("Shy")) mods.flirtiness -= 20; if (mental.includes("Awkward")) mods.flirtiness -= 15; if (physical.includes("Attractive")) mods.flirtiness += 15; /* Confident + Flirty = Bold advances */ if (mental.includes("Confident") && mental.includes("Flirty")) { mods.flirtiness += 20; mods.boldAdvances = true; } /* Aggression modifiers */ if (mental.includes("Aggressive")) mods.aggression += 30; if (mental.includes("Short Tempered")) mods.aggression += 20; if (mental.includes("Bitchy")) mods.aggression += 15; if (mental.includes("Arrogant")) mods.aggression += 10; if (mental.includes("Calm")) mods.aggression -= 25; if (mental.includes("Patient")) mods.aggression -= 20; if (mental.includes("Kind")) mods.aggression -= 15; /* Helpfulness modifiers */ if (mental.includes("Kind")) mods.helpfulness += 30; if (mental.includes("Nurturing")) mods.helpfulness += 25; if (mental.includes("Empathetic")) mods.helpfulness += 20; if (mental.includes("Friendly")) mods.helpfulness += 15; if (mental.includes("Selfish")) mods.helpfulness -= 25; if (mental.includes("Cold")) mods.helpfulness -= 15; /* Shy + Kind = Gentle, hesitant helpfulness */ if (mental.includes("Shy") && mental.includes("Kind")) { mods.helpfulness += 10; mods.gentleHelper = true; } /* Arrogant + Intelligent = Condescending expertise */ if (mental.includes("Arrogant") && mental.includes("Intelligent")) { mods.condescending = true; } /* Lazy + Friendly = Casual, low-effort friendliness */ if (mental.includes("Lazy") && mental.includes("Friendly")) { mods.casualFriendly = true; } /* Talkativeness modifiers */ if (mental.includes("Talkative")) mods.talkativeness += 30; if (mental.includes("Extroverted")) mods.talkativeness += 20; if (mental.includes("Energetic")) mods.talkativeness += 15; if (mental.includes("Quiet")) mods.talkativeness -= 30; if (mental.includes("Introverted")) mods.talkativeness -= 20; if (mental.includes("Shy")) mods.talkativeness -= 15; /* Confidence modifiers */ if (mental.includes("Confident")) mods.confidence += 30; if (mental.includes("Arrogant")) mods.confidence += 25; if (mental.includes("Brave")) mods.confidence += 15; if (mental.includes("Insecure")) mods.confidence -= 30; if (mental.includes("Shy")) mods.confidence -= 20; if (mental.includes("Anxious")) mods.confidence -= 15; /* Trust modifiers */ if (mental.includes("Trusting")) mods.trustworthiness += 25; if (mental.includes("Honest")) mods.trustworthiness += 20; if (mental.includes("Paranoid")) mods.trustworthiness -= 30; if (mental.includes("Deceitful")) mods.trustworthiness -= 25; /* Special combo: Dominant + Confident = Commanding presence */ if (mental.includes("Dominant") && mental.includes("Confident")) { mods.commandingPresence = true; } /* Special combo: Submissive + Shy = Easily flustered */ if (mental.includes("Submissive") && mental.includes("Shy")) { mods.easilyFlustered = true; } /* Special combo: Intelligent + Curious = Knowledge seeker */ if (mental.includes("Intelligent") && mental.includes("Curious")) { mods.knowledgeSeeker = true; } /* Clamp values */ mods.flirtiness = Math.max(-50, Math.min(100, mods.flirtiness)); mods.aggression = Math.max(-50, Math.min(100, mods.aggression)); mods.helpfulness = Math.max(-50, Math.min(100, mods.helpfulness)); mods.talkativeness = Math.max(-50, Math.min(100, mods.talkativeness)); mods.confidence = Math.max(-50, Math.min(100, mods.confidence)); mods.trustworthiness = Math.max(-50, Math.min(100, mods.trustworthiness)); }>> /* Get NPC behavior modifier for a specific trait type */ <<set setup.getNPCBehaviorModifier = function(npc, modType) { if (!npc || !npc.behaviorModifiers) return 0; return npc.behaviorModifiers[modType] || 0; }>> /* Check if NPC has a specific behavior flag from trait combinations */ <<set setup.hasNPCBehaviorFlag = function(npc, flagName) { if (!npc || !npc.behaviorModifiers) return false; return npc.behaviorModifiers[flagName] === true; }>> /* Update NPC schedule based on current traits */ <<set setup.updateNPCScheduleFromTraits = function(npc) { if (!npc) return; var v = State.variables; var originalName = npc.originalName || npc.name; /* Initialize schedule if needed */ if (!v.npcLocationSchedules) { v.npcLocationSchedules = {}; } if (!v.npcLocationSchedules[originalName]) { v.npcLocationSchedules[originalName] = { defaultLocation: null, customSchedule: {}, traitOverrides: [] }; } var schedule = v.npcLocationSchedules[originalName]; if (!schedule.traitOverrides) { schedule.traitOverrides = []; } /* Clear old trait-based overrides */ schedule.traitOverrides = []; /* Athletic/Muscular/Fit NPCs go to gym */ if (npc.physicalTraits.includes("Athletic") || npc.physicalTraits.includes("Muscular") || npc.mentalTraits.includes("Jock") || npc.physicalTraits.includes("Fit")) { schedule.traitOverrides.push({ location: "OpahFitness", day: ["Monday", "Wednesday", "Friday"], start: 18, end: 20, reason: "gym workout" }); } /* Intelligent/Curious NPCs visit library */ if (npc.mentalTraits.includes("Intelligent") || npc.mentalTraits.includes("Curious") || npc.mentalTraits.includes("Nerd")) { schedule.traitOverrides.push({ location: "Library", day: ["Tuesday", "Thursday"], start: 16, end: 18, reason: "reading/studying" }); } /* Outgoing/Flirty/Seductive NPCs go to social locations */ if (npc.mentalTraits.includes("Outgoing") || npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { schedule.traitOverrides.push({ location: "StripClub", day: ["Friday", "Saturday"], start: 20, end: 23, reason: "socializing" }); } /* Goth/Creative/Introverted NPCs visit alternative spots */ if (npc.mentalTraits.includes("Goth") || (npc.mentalTraits.includes("Creative") && npc.mentalTraits.includes("Introverted"))) { schedule.traitOverrides.push({ location: "EcentricShop", day: ["Saturday"], start: 14, end: 16, reason: "browsing" }); } /* Bimbo trait - frequent beauty salon visits */ if (npc.mentalTraits.includes("Bimbo")) { schedule.traitOverrides.push({ location: "BeautySalon", day: ["Monday", "Wednesday", "Friday"], start: 11, end: 13, reason: "beauty maintenance" }); } /* Lazy/Chill NPCs frequent park in afternoons */ if (npc.mentalTraits.includes("Lazy") || npc.mentalTraits.includes("Chill") || npc.mentalTraits.includes("Nonchalant")) { schedule.traitOverrides.push({ location: "Park", day: ["Sunday"], start: 14, end: 17, reason: "relaxing" }); } /* Ambitious/Workaholic NPCs stay late at their job location */ if (npc.mentalTraits.includes("Ambitious") || npc.mentalTraits.includes("Workaholic") || npc.mentalTraits.includes("Hardworking")) { schedule.traitOverrides.push({ location: "BusinessDistrict", day: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], start: 17, end: 20, reason: "working late" }); } /* Foodie/Gluttonous NPCs visit food locations */ if (npc.mentalTraits.includes("Foodie") || npc.mentalTraits.includes("Gluttonous")) { schedule.traitOverrides.push({ location: "Restaurant", day: ["Wednesday", "Saturday"], start: 18, end: 20, reason: "dining out" }); } /* Spiritual/Meditative NPCs visit peaceful locations */ if (npc.mentalTraits.includes("Spiritual") || npc.mentalTraits.includes("Meditative") || npc.mentalTraits.includes("Calm")) { schedule.traitOverrides.push({ location: "Park", day: ["Tuesday", "Thursday"], start: 6, end: 8, reason: "morning meditation" }); } /* Party-loving NPCs frequent clubs on weekends */ if (npc.mentalTraits.includes("Partier") || npc.mentalTraits.includes("Extroverted") && npc.mentalTraits.includes("Energetic")) { schedule.traitOverrides.push({ location: "StripClub", day: ["Friday", "Saturday"], start: 21, end: 24, reason: "partying" }); } /* Beach-loving NPCs visit beach on weekends */ if (npc.physicalTraits.includes("Athletic") || npc.mentalTraits.includes("Outgoing")) { schedule.traitOverrides.push({ location: "Beach", day: ["Saturday", "Sunday"], start: 10, end: 14, reason: "beach time" }); } /* Shopaholic NPCs visit shopping areas */ if (npc.mentalTraits.includes("Shopaholic") || npc.mentalTraits.includes("Materialistic")) { schedule.traitOverrides.push({ location: "ShoppingMall", day: ["Saturday"], start: 12, end: 17, reason: "shopping" }); } /* Rich/Wealthy NPCs visit upscale areas */ if (npc.mentalTraits.includes("Wealthy") || npc.mentalTraits.includes("Rich") || npc.mentalTraits.includes("Snobby")) { schedule.traitOverrides.push({ location: "BusinessDistrict", day: ["Monday", "Wednesday", "Friday"], start: 12, end: 14, reason: "business lunch" }); } }>> /* Determine how likely an NPC is to use their skills in personal life */ <<set setup.updateNPCSkillUsage = function(npc) { if (!npc || !npc.skills) return; if (!npc.skillUsageLikelihood) { npc.skillUsageLikelihood = {}; } /* Sexual skills - always used in personal life if NPC is outgoing/flirty/seductive */ var sexualSkills = ["Sexually Skilled", "High Heels Proficient", "Seduction"]; sexualSkills.forEach(function(skill) { if (npc.skills.includes(skill)) { var likelihood = 0.3; /* Base 30% */ if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { likelihood = 0.8; /* 80% if flirty/seductive */ } else if (npc.mentalTraits.includes("Outgoing") || npc.mentalTraits.includes("Confident")) { likelihood = 0.6; /* 60% if outgoing/confident */ } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Awkward") || npc.mentalTraits.includes("Prude")) { likelihood = 0.1; /* Only 10% if shy/awkward/prude */ } npc.skillUsageLikelihood[skill] = likelihood; } }); /* Makeup skill - depends on personality and gender */ if (npc.skills.includes("Makeup")) { var makeupChance = 0.5; /* Base 50% */ if (npc.mentalTraits.includes("Vain") || npc.mentalTraits.includes("Diva") || npc.physicalTraits.includes("Fashionable")) { makeupChance = 0.9; /* 90% if vain/diva/fashionable */ } else if (npc.mentalTraits.includes("Bimbo") || npc.mentalTraits.includes("Prep")) { makeupChance = 0.95; /* 95% if bimbo/prep */ } else if (npc.mentalTraits.includes("Tomboy") || npc.mentalTraits.includes("Jock")) { makeupChance = 0.1; /* 10% if tomboy/jock */ } else if (npc.mentalTraits.includes("Goth")) { makeupChance = 0.7; /* 70% if goth (dark makeup) */ } else if (npc.bodyParts.gender === "male" && !npc.mentalTraits.includes("Femboy")) { makeupChance = 0.05; /* 5% for masculine males */ } else if (npc.mentalTraits.includes("Femboy")) { makeupChance = 0.6; /* 60% for femboys */ } npc.skillUsageLikelihood["Makeup"] = makeupChance; } /* Creative skills (Art, Painting, Music, Writing) - used if creative/curious */ var creativeSkills = ["Art", "Painting", "Music", "Writing", "Dancing"]; creativeSkills.forEach(function(skill) { if (npc.skills.includes(skill)) { var chance = 0.3; /* Base 30% */ if (npc.mentalTraits.includes("Creative") || npc.mentalTraits.includes("Artistic")) { chance = 0.9; /* 90% if creative */ } else if (npc.mentalTraits.includes("Curious")) { chance = 0.6; /* 60% if curious */ } npc.skillUsageLikelihood[skill] = chance; } }); /* Athletic skills (Athletics, Heavy Lifting, Combat, Yoga) - used if athletic/energetic */ var athleticSkills = ["Athletics", "Heavy Lifting", "Combat", "Yoga"]; athleticSkills.forEach(function(skill) { if (npc.skills.includes(skill)) { var chance = 0.4; /* Base 40% */ if (npc.physicalTraits.includes("Athletic") || npc.physicalTraits.includes("Muscular") || npc.mentalTraits.includes("Jock")) { chance = 0.95; /* 95% if athletic/muscular/jock */ } else if (npc.mentalTraits.includes("Energetic") || npc.mentalTraits.includes("Active")) { chance = 0.7; /* 70% if energetic */ } else if (npc.mentalTraits.includes("Lazy")) { chance = 0.05; /* Only 5% if lazy */ } npc.skillUsageLikelihood[skill] = chance; } }); /* Cooking/Baking - depends on traits */ if (npc.skills.includes("Cooking") || npc.skills.includes("Baking")) { var cookingChance = 0.5; /* Base 50% */ if (npc.mentalTraits.includes("Nurturing") || npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Warm")) { cookingChance = 0.8; /* 80% if nurturing/kind */ } if (npc.skills.includes("Cooking")) npc.skillUsageLikelihood["Cooking"] = cookingChance; if (npc.skills.includes("Baking")) npc.skillUsageLikelihood["Baking"] = cookingChance; } }>> /* Update NPC appearance behavior based on traits and skills */ <<set setup.updateNPCAppearanceBehavior = function(npc) { if (!npc) return; if (!npc.appearanceBehavior) { npc.appearanceBehavior = {}; } /* Grooming frequency */ var groomingFreq = "moderate"; /* Base */ if (npc.mentalTraits.includes("Vain") || npc.mentalTraits.includes("Diva") || npc.mentalTraits.includes("Bimbo") || npc.physicalTraits.includes("Fashionable")) { groomingFreq = "very high"; } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Professional") || npc.mentalTraits.includes("Prep")) { groomingFreq = "high"; } else if (npc.mentalTraits.includes("Lazy") || npc.mentalTraits.includes("Sloppy")) { groomingFreq = "low"; } else if (npc.mentalTraits.includes("Goth") || npc.mentalTraits.includes("Nerd")) { groomingFreq = "moderate"; } npc.appearanceBehavior.grooming = groomingFreq; /* Fashion consciousness */ var fashionLevel = "casual"; /* Base */ if (npc.physicalTraits.includes("Fashionable") || npc.mentalTraits.includes("Diva") || npc.mentalTraits.includes("Prep")) { fashionLevel = "high"; } else if (npc.mentalTraits.includes("Vain") || npc.mentalTraits.includes("Confident")) { fashionLevel = "moderate"; } else if (npc.mentalTraits.includes("Tomboy") || npc.mentalTraits.includes("Jock")) { fashionLevel = "athletic"; } else if (npc.mentalTraits.includes("Goth")) { fashionLevel = "alternative"; } else if (npc.mentalTraits.includes("Simple") || npc.mentalTraits.includes("Lazy")) { fashionLevel = "minimal"; } npc.appearanceBehavior.fashion = fashionLevel; /* Fitness routine */ var fitnessLevel = "occasional"; /* Base */ if (npc.physicalTraits.includes("Athletic") || npc.physicalTraits.includes("Muscular") || npc.mentalTraits.includes("Jock") || npc.mentalTraits.includes("Disciplined")) { fitnessLevel = "dedicated"; } else if (npc.mentalTraits.includes("Energetic") || npc.mentalTraits.includes("Active")) { fitnessLevel = "regular"; } else if (npc.mentalTraits.includes("Lazy") || npc.mentalTraits.includes("Bimbo")) { fitnessLevel = "rare"; } npc.appearanceBehavior.fitness = fitnessLevel; }>>
/* ---------------------------------- */ /* --- NPC TRANSFORMATION DESCRIPTIONS --- */ /* ---------------------------------- */ /* Generate NPC transformation description for body part changes */ < 0) { desc = npc.name + " ages before your eyes. "; if (ageDiff >= 20) { desc += "Years pass rapidly across their face. Wrinkles form, skin loses elasticity. "; desc += "Their body matures significantly, growing older and more mature."; } else if (ageDiff >= 10) { desc += "They age noticeably, their features maturing as years pass in moments."; } else { desc += "They grow slightly older, their appearance maturing subtly."; } } else if (ageDiff < 0) { desc = npc.name + " grows younger. "; if (ageDiff <= -20) { desc += "Years melt away from their face. Wrinkles smooth out, skin tightens. "; desc += "Their body becomes significantly younger and more youthful."; } else if (ageDiff <= -10) { desc += "They grow noticeably younger, years falling away from their appearance."; } else { desc += "They become slightly younger, their features growing more youthful."; } } } /* SKIN TONE transformations */ else if (partName === "skinTone") { desc = npc.name + "'s skin tone shifts. "; desc += "Their " + oldValue + " skin gradually changes, transforming to " + newValue + "."; } /* HAIR COLOR transformations */ else if (partName === "hairColor") { desc = npc.name + "'s hair color transforms. "; desc += "The " + oldValue + " strands ripple with change, shifting to " + newValue + "."; } /* HAIR LENGTH transformations */ else if (partName === "hairLength") { if ((newValue === "long" || newValue === "very long") && (oldValue === "short" || oldValue === "medium")) { desc = npc.name + "'s hair begins to grow. "; desc += "The strands lengthen rapidly, cascading down past their shoulders"; if (newValue === "very long") { desc += " and continuing to grow until it reaches their lower back."; } else { desc += "."; } } else if (newValue === "short" && (oldValue === "long" || oldValue === "very long" || oldValue === "medium")) { desc = npc.name + "'s hair shortens dramatically. "; desc += "The long strands retract and shrink, pulling back until their hair is cropped short."; } else if (newValue === "medium") { desc = npc.name + "'s hair adjusts in length. "; if (oldValue === "short") { desc += "It grows out to a medium, shoulder-length style."; } else { desc += "It shortens to a medium, shoulder-length style."; } } } descriptions.push(desc); }); return descriptions.join(" "); }>>; /* Generate NPC transformation description for physical trait changes */ < 0) { gainedTraits.forEach(function(trait) { var desc = ""; if (trait === "Muscular") { desc = npc.name + "'s body begins to transform. Muscles swell and bulge beneath their skin. "; desc += "Their arms thicken with defined biceps and triceps. Their chest becomes hard and sculpted. "; desc += "Abs appear, forming a tight six-pack. Their legs grow powerful and defined. "; desc += "The transformation leaves them impressively muscular."; } else if (trait === "Athletic") { desc = npc.name + "'s body becomes leaner and more toned. "; desc += "Muscle definition increases across their frame, creating an athletic, fit appearance. "; desc += "They look ready to sprint or leap at any moment."; } else if (trait === "Curvy") { desc = npc.name + "'s body becomes more curvaceous. "; desc += "Their hips widen, waist narrows, creating an hourglass figure. "; desc += "Soft curves appear in all the right places."; } else if (trait === "Voluptuous") { desc = npc.name + "'s body transforms into a voluptuous figure. "; desc += "Curves expand dramatically - hips widen, waist cinches, creating an exaggerated hourglass. "; desc += "Their body becomes soft and plush with sensual curves."; } else if (trait === "Fit") { desc = npc.name + " becomes noticeably more fit. "; desc += "Their body tightens and tones, excess fat melting away to reveal lean muscle underneath."; } else if (trait === "Chubby") { desc = npc.name + "'s body softens and fills out. "; desc += "They gain a layer of soft padding, becoming pleasantly chubby."; } else if (trait === "Fat") { desc = npc.name + " gains significant weight. "; desc += "Their body expands, becoming soft and heavy with fat."; } else if (trait === "Obese") { desc = npc.name + " gains massive amounts of weight. "; desc += "Their body swells dramatically, becoming extremely obese."; } else if (trait === "Skinny") { desc = npc.name + " becomes very thin. "; desc += "Fat melts away from their frame, leaving them quite skinny."; } else if (trait === "Flexible") { desc = npc.name + "'s body becomes more limber. "; desc += "Their joints loosen, movements becoming fluid and graceful. They test their new flexibility with ease."; } else if (trait === "Attractive") { desc = npc.name + "'s features shift subtly. "; desc += "Their face becomes more symmetrical, more pleasing to the eye. "; desc += "They're now noticeably attractive."; } else if (trait === "Beautiful" || trait === "Gorgeous") { desc = npc.name + " becomes stunningly beautiful. "; desc += "Their features perfect themselves, creating breathtaking beauty. "; desc += "They're the kind of person who turns heads everywhere they go."; } else if (trait === "Ugly") { desc = npc.name + "'s features become less attractive. "; desc += "Asymmetries appear, their face becoming notably unappealing."; } else if (trait === "Tall") { desc = npc.name + " begins to grow taller. "; desc += "Their body stretches upward, bones lengthening until they stand notably tall."; } else if (trait === "Short") { desc = npc.name + " shrinks in height. "; desc += "Their body compresses, growing shorter until they're noticeably small."; } else if (trait === "Busty") { desc = npc.name + "'s chest swells significantly. "; desc += "Their breasts grow larger, becoming quite busty."; } else if (trait === "Lean") { desc = npc.name + "'s body becomes lean and efficient. "; desc += "Excess fat vanishes, leaving behind a slim, efficient physique."; } else if (trait === "Graceful") { desc = npc.name + " begins to move with newfound grace. "; desc += "Every motion becomes smooth and elegant, as if they're dancing through life."; } else if (trait === "Clumsy") { desc = npc.name + " becomes noticeably clumsier. "; desc += "They stumble slightly, their coordination deteriorating."; } else if (trait === "Pierced") { desc = npc.name + "'s body suddenly gains piercings. "; desc += "Metal studs and rings appear on their ears, nose, and other visible areas."; } else if (trait === "Tattooed") { desc = npc.name + "'s skin becomes decorated with tattoos. "; desc += "Ink spreads across their skin, forming intricate designs and patterns."; } else if (trait === "Smooth Skin") { desc = npc.name + "'s skin becomes perfectly smooth. "; desc += "All blemishes, scars, and imperfections fade away, leaving flawless skin."; } else if (trait === "Youthful") { desc = npc.name + " looks younger. "; desc += "Years seem to melt away from their face, leaving them looking more youthful and vibrant."; } else if (trait === "Mature") { desc = npc.name + " looks more mature. "; desc += "Their features age slightly, gaining a mature, distinguished appearance."; } if (desc) { descriptions.push(desc); } }); } /* Handle LOST physical traits */ if (lostTraits && lostTraits.length > 0) { lostTraits.forEach(function(trait) { var desc = ""; if (trait === "Muscular") { desc = npc.name + "'s muscles begin to shrink. "; desc += "Their impressive physique deflates, losing definition and bulk. "; desc += "Within moments, their muscular body is gone."; } else if (trait === "Athletic") { desc = npc.name + " loses their athletic build. "; desc += "Muscle tone fades, their body becoming less defined and fit."; } else if (trait === "Curvy") { desc = npc.name + "'s curves flatten out. "; desc += "Their hourglass figure straightens, becoming less curvy."; } else if (trait === "Flexible") { desc = npc.name + " loses their flexibility. "; desc += "Their joints stiffen, movements becoming less fluid."; } else if (trait === "Attractive") { desc = npc.name + " becomes less attractive. "; desc += "Their appealing features fade to something more average."; } if (desc) { descriptions.push(desc); } }); } return descriptions.length > 0 ? descriptions.join(" ") : null; }>>; /* Generate NPC transformation description for mental trait changes */ < 0 ? npc.personalityHistory[npc.personalityHistory.length - 1].from : null; var newPersonality = npc.primaryPersonality; /* Handle GAINED mental traits */ if (gainedTraits && gainedTraits.length > 0) { gainedTraits.forEach(function(trait) { var desc = ""; if (trait === "Dominant") { desc = npc.name + "'s demeanor shifts dramatically. "; desc += "Their posture straightens, shoulders back. Their eyes gain a commanding gleam. "; desc += "Confidence radiates from them - they now exude dominance and authority."; } else if (trait === "Submissive") { desc = npc.name + "'s presence softens considerably. "; desc += "Their eyes lower slightly, body language becoming more yielding. "; desc += "They seem more compliant, more eager to please."; } else if (trait === "Bimbo") { desc = npc.name + "'s expression becomes vacant for a moment. "; desc += "Then they giggle, eyes brightening with a new ditzy sparkle. "; desc += "Their posture shifts - chest out, hips cocked. They twirl their hair absently. "; desc += "'Like, omigod!' they squeal, their transformation into a bimbo complete."; } else if (trait === "Confident") { desc = npc.name + " stands taller, shoulders back. "; desc += "Their eyes gain a bold, self-assured gleam. Confidence flows through them."; } else if (trait === "Shy") { desc = npc.name + " becomes noticeably more reserved. "; desc += "They look down, cheeks flushing. Their voice drops to barely above a whisper."; } else if (trait === "Awkward") { desc = npc.name + " shifts uncomfortably. "; desc += "They fidget nervously, suddenly unsure of themselves. Social anxiety washes over them."; } else if (trait === "Flirty") { desc = npc.name + "'s eyes gain a playful, seductive sparkle. "; desc += "They smile with new mischief, their body language becoming inviting and teasing."; } else if (trait === "Intelligent") { desc = npc.name + "'s eyes sharpen with newfound clarity. "; desc += "You can almost see the gears turning as their mind quickens, thoughts becoming clearer and faster."; } else if (trait === "Simple") { desc = npc.name + "'s expression becomes more vacant. "; desc += "Complex thoughts seem to slip away, leaving them with a simpler outlook."; } else if (trait === "Kind") { desc = npc.name + "'s expression softens with warmth. "; desc += "Genuine kindness radiates from them, their eyes full of compassion."; } else if (trait === "Mean") { desc = npc.name + "'s expression hardens. "; desc += "Their eyes gain a cruel edge, lips curling into a slight sneer."; } else if (trait === "Bitchy") { desc = npc.name + "'s entire demeanor shifts. "; desc += "They roll their eyes, crossing their arms. Attitude radiates from their every pore. "; desc += "'Ugh, whatever,' they mutter with newfound bitchiness."; } else if (trait === "Arrogant") { desc = npc.name + " begins to look down on everything around them. "; desc += "Their nose tilts up slightly, expression dripping with superiority."; } else if (trait === "Energetic") { desc = npc.name + " becomes noticeably more energetic. "; desc += "They bounce on their toes, unable to stand still. Energy radiates from them."; } else if (trait === "Calm") { desc = npc.name + " becomes much calmer. "; desc += "Tension melts from their body, movements becoming slow and deliberate."; } else if (trait === "Creative") { desc = npc.name + "'s eyes light up with imagination. "; desc += "You can almost see ideas flowing through their mind as creativity blooms within them."; } else if (trait === "Curious") { desc = npc.name + " looks around with newfound curiosity. "; desc += "Everything seems to interest them now, their eyes wide with wonder."; } else if (trait === "Jock") { desc = npc.name + "'s entire demeanor shifts to that of a jock. "; desc += "They crack their knuckles, rolling their shoulders. 'Bro,' they say, grinning with athletic enthusiasm."; } else if (trait === "Goth") { desc = npc.name + "'s expression becomes more cynical and dark. "; desc += "They seem to embrace a darker, more alternative outlook on life."; } else if (trait === "Nerd") { desc = npc.name + " becomes noticeably nerdier. "; desc += "They push up invisible glasses, eyes brightening at the thought of knowledge and facts."; } else if (trait === "Femboy") { desc = npc.name + "'s mannerisms become more feminine and delicate. "; desc += "They move with graceful, soft gestures, embracing a more feminine presentation."; } if (desc) { descriptions.push(desc); } }); } /* Handle LOST mental traits */ if (lostTraits && lostTraits.length > 0) { lostTraits.forEach(function(trait) { var desc = ""; if (trait === "Dominant") { desc = npc.name + "'s commanding presence fades. "; desc += "The authority drains from their posture, leaving them less imposing."; } else if (trait === "Submissive") { desc = npc.name + " becomes less submissive. "; desc += "Their yielding nature fades, replaced with more assertiveness."; } else if (trait === "Bimbo") { desc = npc.name + "'s vacant expression clears. "; desc += "Intelligence returns to their eyes. 'Wait, what was I saying?' they ask, "; desc += "their voice no longer that high-pitched squeal. The bimbo persona fades away completely."; } else if (trait === "Shy") { desc = npc.name + " becomes less shy. "; desc += "They make eye contact more easily, their voice growing stronger."; } else if (trait === "Intelligent") { desc = npc.name + "'s sharp mind dulls slightly. "; desc += "Complex thoughts become harder to grasp."; } if (desc) { descriptions.push(desc); } }); } /* Add personality change commentary if applicable */ if (newPersonality && oldPersonality && newPersonality !== oldPersonality) { var transitionDesc = ""; if (newPersonality === "Bimbo") { transitionDesc = npc.name + " giggles, their old " + oldPersonality.toLowerCase() + " personality completely replaced by their new bimbo mindset."; } else if (oldPersonality === "Bimbo") { transitionDesc = npc.name + " shakes their head, the bimbo fog lifting. They're now clearly " + newPersonality.toLowerCase() + "."; } else { transitionDesc = npc.name + " is no longer " + oldPersonality.toLowerCase() + " - they're now distinctly " + newPersonality.toLowerCase() + "."; } descriptions.push(transitionDesc); } return descriptions.length > 0 ? descriptions.join(" ") : null; }>>; /* Generate complete NPC transformation description */ < 0 ? transformations.join("") : null; }>>;
/* ---------------------------------- */ /* --- MONEY SYSTEM FUNCTIONS --- */ /* ---------------------------------- */ /* Format money display */ <<set setup.formatMoney = function(amount) { return "$" + amount.toLocaleString(); }>> /* Add money to player */ <<set setup.addMoney = function(amount) { var v = State.variables; amount = Number(amount); if (!Number.isNaN(amount) && amount > 0) { v.money += amount; /* Check for $10 million achievement */ if (v.money >= 10000000) { setup.achievements.unlock("earn_10_million"); } /* Check for billionaire achievement */ if (v.money >= 1000000000) { setup.achievements.unlock("billionaire"); } return true; } return false; }>> /* Remove money from player */ <<set setup.removeMoney = function(amount) { var v = State.variables; amount = Number(amount); if (!Number.isNaN(amount) && amount > 0 && v.money >= amount) { v.money -= amount; return true; } return false; }>> /* Check if player can afford something */ <<set setup.canAfford = function(amount) { var v = State.variables; amount = Number(amount); return !Number.isNaN(amount) && v.money >= amount; }>>
/* ---------------------------------- */ /* --- NPC DIALOGUE SYSTEM --- */ /* ---------------------------------- */ /* ====================================================================== */ /* DYNAMIC CONVERSATION OPTIONS SYSTEM */ /* ====================================================================== */ /* Conversation Options Data Structure */ <<set setup.conversationOptions = { /* CORE OPTIONS - Available to most NPCs */ core: { compliment: { id: "compliment", label: "Give them a compliment", color: "#51cf66", basePoints: 1, minRelLevel: -1, maxRelLevel: 5, category: "core", traitModifiers: { boosted: ["Insecure", "Shy", "Vain", "Attention Seeker"], reduced: ["Arrogant", "Cynical", "Cold"], blocked: [] } }, smalltalk: { id: "smalltalk", label: "Make small talk", color: "#667eea", basePoints: 0, minRelLevel: -1, maxRelLevel: 5, category: "core", traitModifiers: { boosted: ["Friendly", "Talkative", "Outgoing", "Warm"], reduced: ["Bitchy", "Impatient", "Cold", "Antisocial"], blocked: [] } }, askJob: { id: "job", label: "Ask about their job", color: "#17a2b8", basePoints: 0, minRelLevel: 0, maxRelLevel: 5, category: "core", traitModifiers: { boosted: ["Workaholic", "Ambitious", "Proud"], reduced: ["Lazy", "Unmotivated"], blocked: [] } }, askOpinion: { id: "opinion", label: "Ask what they think of you", color: "#9b59b6", basePoints: 1, minRelLevel: 0, maxRelLevel: 5, category: "core", traitModifiers: { boosted: ["Arrogant", "Vain", "Confident", "Honest"], reduced: ["Shy", "Reserved"], blocked: [] } }, askTrading: { id: "trading", label: "Ask what they're interested in trading", color: "#ffc107", basePoints: 0, minRelLevel: 0, maxRelLevel: 5, category: "core", traitModifiers: { boosted: ["Greedy", "Shrewd", "Ambitious"], reduced: ["Generous"], blocked: [] } }, whatsNew: { id: "whatsNew", label: "Ask what's new with them", color: "#20c997", basePoints: 1, minRelLevel: 1, maxRelLevel: 5, category: "core", traitModifiers: { boosted: ["Talkative", "Outgoing", "Friendly", "Energetic"], reduced: ["Cold", "Antisocial", "Reserved"], blocked: [] } } }, /* PERSONALITY-SPECIFIC OPTIONS - Require matching NPC traits */ personality: { debate: { id: "debate", label: "Debate ideas with them", color: "#00bcd4", basePoints: 1, minRelLevel: 1, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Nerd", "Intelligent", "Analytical", "Philosophical", "Curious"] }, traitModifiers: { boosted: ["Intelligent", "Competitive", "Confident"], reduced: ["Stubborn", "Impatient"], blocked: [] } }, fitness: { id: "fitness", label: "Talk about fitness and sports", color: "#ff5722", basePoints: 1, minRelLevel: 0, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Jock", "Athletic", "Competitive", "Energetic"] }, traitModifiers: { boosted: ["Jock", "Competitive", "Energetic"], reduced: ["Lazy", "Nerd"], blocked: [] } }, gossip: { id: "gossip", label: "Share some gossip", color: "#ff9800", basePoints: 1, minRelLevel: 1, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Gossipy", "Nosy", "Social Butterfly", "Talkative", "Diva", "Prep"] }, traitModifiers: { boosted: ["Gossipy", "Nosy", "Social Butterfly"], reduced: ["Honest", "Loyal", "Reserved"], blocked: [] } }, darkTopics: { id: "darkTopics", label: "Discuss deeper, darker topics", color: "#4a0080", basePoints: 2, minRelLevel: 1, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Goth", "Pessimistic", "Cynical", "Depressed", "Philosophical"] }, traitModifiers: { boosted: ["Goth", "Cynical", "Philosophical"], reduced: ["Optimistic", "Bubbly", "Naive"], blocked: [] } }, beSubmissive: { id: "beSubmissive", label: "Let them take the lead in conversation", color: "#9c27b0", basePoints: 2, minRelLevel: 0, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Dominant", "Arrogant", "Bossy", "Alpha"] }, traitModifiers: { boosted: ["Dominant", "Arrogant", "Bossy"], reduced: [], blocked: [] } }, takeCharge: { id: "takeCharge", label: "Take charge of the conversation", color: "#673ab7", basePoints: 2, minRelLevel: 0, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Submissive", "Shy", "Timid", "Nervous"] }, traitModifiers: { boosted: ["Submissive", "Shy", "Timid"], reduced: ["Rebellious"], blocked: [] } }, playAlong: { id: "playAlong", label: "Play along with their energy", color: "#ff69b4", basePoints: 2, minRelLevel: 0, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Bimbo", "Airhead", "Ditzy", "Bubbly"] }, traitModifiers: { boosted: ["Bimbo", "Airhead", "Bubbly"], reduced: ["Intelligent", "Analytical"], blocked: [] } }, fashion: { id: "fashion", label: "Talk about fashion and style", color: "#e91e63", basePoints: 1, minRelLevel: 0, maxRelLevel: 5, category: "personality", requiredNPCTraits: { any: ["Prep", "Diva", "Vain", "Fashionable"] }, traitModifiers: { boosted: ["Vain", "Diva", "Prep"], reduced: ["Practical", "Simple"], blocked: [] } } }, /* RELATIONSHIP-GATED OPTIONS - Unlock at friendship levels */ relationship: { askAdvice: { id: "advice", label: "Ask for their advice", color: "#4dabf7", basePoints: 2, minRelLevel: 1, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Kind", "Wise", "Experienced", "Nurturing"], reduced: ["Selfish", "Impatient"], blocked: [] } }, shareSecrets: { id: "secrets", label: "Share a secret with them", color: "#9b59b6", basePoints: 3, minRelLevel: 2, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Trustworthy", "Loyal", "Kind", "Empathetic"], reduced: ["Gossipy", "Untrustworthy", "Manipulative"], blocked: [] }, riskLevel: "high" }, emotionalSupport: { id: "support", label: "Offer emotional support", color: "#e91e63", basePoints: 3, minRelLevel: 2, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Sensitive", "Anxious", "Insecure", "Depressed"], reduced: ["Cold", "Arrogant", "Dominant"], blocked: [] } }, planTogether: { id: "plan", label: "Make plans for hanging out", color: "#00bcd4", basePoints: 2, minRelLevel: 2, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Friendly", "Outgoing", "Social Butterfly"], reduced: ["Antisocial", "Busy", "Reserved"], blocked: [] } }, deepConversation: { id: "deep", label: "Have a deep, meaningful conversation", color: "#3f51b5", basePoints: 4, minRelLevel: 3, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Empathetic", "Philosophical", "Intelligent", "Sensitive"], reduced: ["Shallow", "Impatient", "Cold"], blocked: [] } }, confide: { id: "confide", label: "Confide your worries", color: "#795548", basePoints: 3, minRelLevel: 3, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Kind", "Nurturing", "Empathetic", "Patient"], reduced: ["Impatient", "Selfish", "Cold"], blocked: [] } }, bestFriendExclusive: { id: "bestFriend", label: "Share your deepest thoughts", color: "#ff6b9d", basePoints: 5, minRelLevel: 4, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Loyal", "Trustworthy", "Kind"], reduced: [], blocked: [] } }, inviteHomeFriend: { id: "inviteHomeFriend", label: "Come hang out at my place", color: "#51cf66", basePoints: 2, minRelLevel: 2, maxRelLevel: 5, category: "relationship", traitModifiers: { boosted: ["Friendly", "Outgoing", "Warm", "Social Butterfly"], reduced: ["Antisocial", "Cold"], blocked: [] } } }, /* RISKY OPTIONS - Can backfire */ risky: { flirt: { id: "flirt", label: "Flirt with them", color: "#e91e63", basePoints: 2, minRelLevel: 0, maxRelLevel: 5, category: "risky", traitModifiers: { boosted: ["Flirty", "Seductive", "Romantic", "Charming"], reduced: ["Prudish", "Cold", "Reserved"], blocked: [] }, riskLevel: "medium", alwaysAvailable: true }, tease: { id: "tease", label: "Tease them playfully", color: "#ffc107", basePoints: 1, minRelLevel: 1, maxRelLevel: 5, category: "risky", traitModifiers: { boosted: ["Playful", "Witty", "Confident", "Flirty"], reduced: ["Sensitive", "Serious", "Insecure"], blocked: [] }, riskLevel: "low" }, challenge: { id: "challenge", label: "Challenge their beliefs", color: "#ff5722", basePoints: 0, minRelLevel: 0, maxRelLevel: 5, category: "risky", traitModifiers: { boosted: ["Competitive", "Confident", "Intelligent", "Respectful"], reduced: ["Hot-Headed", "Stubborn", "Arrogant"], blocked: [] }, riskLevel: "medium" }, pushBoundaries: { id: "pushBoundaries", label: "Push the conversation further...", color: "#9c27b0", basePoints: 0, minRelLevel: 2, maxRelLevel: 5, category: "risky", requiredNPCTraits: { any: ["Flirty", "Seductive", "Perverted", "Lustful"] }, traitModifiers: { boosted: ["Flirty", "Seductive", "Perverted"], reduced: ["Prudish", "Reserved", "Shy"], blocked: [] }, riskLevel: "high" }, insult: { id: "insult", label: "Say something mean", color: "#ff6b6b", basePoints: -5, minRelLevel: -1, maxRelLevel: 5, category: "risky", traitModifiers: { boosted: ["Sensitive", "Insecure", "Anxious", "Emotional", "Shy", "Timid"], reduced: ["Thick-Skinned"], blocked: [] }, riskLevel: "high", alwaysAvailable: true } }, /* SHARED-TRAIT OPTIONS - Require both player AND NPC to share traits */ shared: { geekOut: { id: "geekOut", label: "Geek out together", color: "#00bcd4", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "shared", requiredNPCTraits: { any: ["Nerd", "Intelligent", "Analytical", "Curious"] }, requiredPlayerTraits: { any: ["Nerd", "Intelligent", "Analytical", "Curious"] }, traitModifiers: { boosted: ["Nerd", "Curious", "Intelligent"], reduced: [], blocked: [] } }, workoutTalk: { id: "workoutTalk", label: "Bond over fitness", color: "#ff5722", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "shared", requiredNPCTraits: { any: ["Jock", "Athletic", "Competitive", "Energetic"] }, requiredPlayerTraits: { any: ["Jock", "Athletic", "Competitive", "Energetic"] }, traitModifiers: { boosted: ["Jock", "Athletic", "Competitive"], reduced: [], blocked: [] } }, fashionBond: { id: "fashionBond", label: "Bond over fashion", color: "#e91e63", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "shared", requiredNPCTraits: { any: ["Fashionable", "Prep", "Diva", "Vain"] }, requiredPlayerTraits: { any: ["Fashionable", "Prep", "Diva", "Vain"] }, traitModifiers: { boosted: ["Fashionable", "Prep", "Diva"], reduced: [], blocked: [] } }, darkHumor: { id: "darkHumor", label: "Share dark humor", color: "#4a0080", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "shared", requiredNPCTraits: { any: ["Goth", "Cynical", "Pessimistic", "Sarcastic"] }, requiredPlayerTraits: { any: ["Goth", "Cynical", "Pessimistic", "Sarcastic"] }, traitModifiers: { boosted: ["Goth", "Cynical", "Sarcastic"], reduced: [], blocked: [] } }, flirtPlayfully: { id: "flirtPlayfully", label: "Flirt playfully", color: "#ff69b4", basePoints: 4, minRelLevel: 0, maxRelLevel: 5, category: "shared", requiredNPCTraits: { any: ["Flirty", "Seductive", "Charming"] }, requiredPlayerTraits: { any: ["Flirty", "Seductive", "Charming"] }, traitModifiers: { boosted: ["Flirty", "Seductive", "Charming"], reduced: [], blocked: [] }, replacesOption: "flirt" } }, /* MOOD-GATED OPTIONS - Appear based on NPC's current mood */ moodGated: { askWhatsWrong: { id: "askWhatsWrong", label: "Ask what's wrong", color: "#5C6BC0", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "moodGated", requiredMood: ["sad", "anxious"], traitModifiers: { boosted: ["Sensitive", "Empathetic", "Kind", "Emotional"], reduced: ["Cold", "Arrogant"], blocked: [] } }, matchEnergy: { id: "matchEnergy", label: "Match their energy", color: "#FF5722", basePoints: 2, minRelLevel: 0, maxRelLevel: 5, category: "moodGated", requiredMood: ["excited", "happy"], traitModifiers: { boosted: ["Energetic", "Outgoing", "Bubbly", "Friendly"], reduced: ["Reserved", "Cold", "Antisocial"], blocked: [] } }, calmDown: { id: "calmDown", label: "Calm them down", color: "#FF7043", basePoints: 3, minRelLevel: 1, maxRelLevel: 5, category: "moodGated", requiredMood: ["angry", "irritated"], traitModifiers: { boosted: ["Patient", "Calm", "Kind", "Empathetic"], reduced: ["Hot-Headed", "Aggressive", "Impatient"], blocked: [] } } }, /* MEMORY-GATED OPTIONS - Appear based on interaction history */ memoryGated: { reminisce: { id: "reminisce", label: "Remember when we first met?", color: "#CE93D8", basePoints: 3, minRelLevel: 1, maxRelLevel: 5, category: "memoryGated", memoryRequirement: "reminisce", traitModifiers: { boosted: ["Sentimental", "Warm", "Romantic", "Friendly"], reduced: ["Cold", "Antisocial"], blocked: [] } }, insideJoke: { id: "insideJoke", label: "Crack an inside joke", color: "#FFD54F", basePoints: 4, minRelLevel: 2, maxRelLevel: 5, category: "memoryGated", memoryRequirement: "insideJoke", traitModifiers: { boosted: ["Humorous", "Playful", "Witty", "Outgoing"], reduced: ["Serious", "Cold"], blocked: [] } }, apologize: { id: "apologize", label: "Apologize for being mean", color: "#90CAF9", basePoints: 5, minRelLevel: 0, maxRelLevel: 5, category: "memoryGated", memoryRequirement: "apologize", traitModifiers: { boosted: ["Humble", "Kind", "Sensitive", "Empathetic"], reduced: ["Proud", "Arrogant"], blocked: [] } }, thankGifts: { id: "thankGifts", label: "Thank them for accepting your gifts", color: "#A5D6A7", basePoints: 3, minRelLevel: 1, maxRelLevel: 5, category: "memoryGated", memoryRequirement: "thankGifts", traitModifiers: { boosted: ["Grateful", "Warm", "Kind"], reduced: ["Cold", "Ungrateful"], blocked: [] } }, noticedChange: { id: "noticedChange", label: "You seem different lately...", color: "#FFD54F", basePoints: 2, minRelLevel: 1, maxRelLevel: 5, category: "memoryGated", memoryRequirement: "noticedChange", traitModifiers: { boosted: ["Perceptive", "Empathetic", "Warm", "Friendly"], reduced: ["Cold", "Insensitive"], blocked: [] } } }, npcSocial: { askAboutNPC: { id: "askAboutNPC", label: "Ask about someone...", color: "#26c6da", basePoints: 1, minRelLevel: 0, maxRelLevel: 5, category: "npcSocial", traitModifiers: { boosted: ["Gossipy", "Social", "Outgoing"], reduced: ["Secretive", "Cold"], blocked: [] } }, positiveGossip: { id: "positiveGossip", label: "Say something nice about someone", color: "#66bb6a", basePoints: 1, minRelLevel: 1, maxRelLevel: 5, category: "npcSocial", traitModifiers: { boosted: ["Kind", "Diplomatic"], reduced: ["Cynical"], blocked: [] } }, negativeGossip: { id: "negativeGossip", label: "Talk bad about someone...", color: "#ef5350", basePoints: 0, minRelLevel: 1, maxRelLevel: 5, category: "npcSocial", riskLevel: "risky", traitModifiers: { boosted: ["Gossipy", "Sly", "Manipulative"], reduced: ["Kind", "Honest"], blocked: [] } }, introduceNPCs: { id: "introduceNPCs", label: "Suggest they meet someone", color: "#42a5f5", basePoints: 2, minRelLevel: 2, maxRelLevel: 5, category: "npcSocial", traitModifiers: { boosted: ["Social", "Outgoing", "Charming"], reduced: ["Shy", "Introverted"], blocked: [] } }, takeSides: { id: "takeSides", label: "Take their side in a conflict", color: "#ffa726", basePoints: 3, minRelLevel: 1, maxRelLevel: 5, category: "npcSocial", traitModifiers: { boosted: ["Loyal", "Dominant"], reduced: ["Diplomatic"], blocked: [] } }, mendRelationship: { id: "mendRelationship", label: "Help mend a relationship", color: "#ab47bc", basePoints: 2, minRelLevel: 2, maxRelLevel: 5, category: "npcSocial", traitModifiers: { boosted: ["Diplomatic", "Kind", "Empathetic"], reduced: ["Aggressive"], blocked: [] } }, romanticNudge: { id: "romanticNudge", label: "Play matchmaker...", color: "#ec407a", basePoints: 1, minRelLevel: 2, maxRelLevel: 5, category: "npcSocial", traitModifiers: { boosted: ["Flirty", "Romantic", "Charming"], reduced: ["Cold"], blocked: [] } } }, romantic: { confessFeelings: { id: "confessFeelings", label: "I have feelings for you...", color: "#e91e63", basePoints: 0, minRelLevel: 5, maxRelLevel: 5, category: "romantic", romanceRequirement: "notRomantic", traitModifiers: { boosted: ["Flirty", "Romantic", "Charming", "Confident"], reduced: ["Shy"], blocked: [] } }, holdHands: { id: "holdHands", label: "Hold their hand", color: "#f48fb1", basePoints: 2, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "dating", traitModifiers: { boosted: ["Romantic", "Kind", "Warm"], reduced: ["Cold"], blocked: [] } }, kissNPC: { id: "kissNPC", label: "Kiss them", color: "#ec407a", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "dating", traitModifiers: { boosted: ["Romantic", "Flirty", "Seductive"], reduced: ["Shy"], blocked: [] } }, romanticDate: { id: "romanticDate", label: "Go on a date", color: "#f06292", basePoints: 5, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "dating", traitModifiers: { boosted: ["Romantic", "Charming", "Outgoing"], reduced: ["Lazy"], blocked: [] } }, askExclusive: { id: "askExclusive", label: "Be exclusive with me?", color: "#e91e63", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "exclusiveReady", traitModifiers: { boosted: ["Romantic", "Loyal", "Confident"], reduced: ["Shy"], blocked: [] } }, makeOutNPC: { id: "makeOutNPC", label: "Make out", color: "#d81b60", basePoints: 4, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "exclusive", traitModifiers: { boosted: ["Flirty", "Seductive", "Passionate"], reduced: ["Prudish"], blocked: [] } }, initiateIntimacy: { id: "initiateIntimacy", label: "Let's go somewhere private...", color: "#c2185b", basePoints: 5, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "lover", traitModifiers: { boosted: ["Seductive", "Confident", "Flirty"], reduced: ["Shy", "Prudish"], blocked: [] } }, pillowTalk: { id: "pillowTalk", label: "Talk about us", color: "#f48fb1", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "lover", traitModifiers: { boosted: ["Romantic", "Empathetic", "Warm"], reduced: ["Cold"], blocked: [] } }, deeperBond: { id: "deeperBond", label: "I want more with you", color: "#c2185b", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "soulmateReady", traitModifiers: { boosted: ["Romantic", "Loyal", "Kind"], reduced: [], blocked: [] } }, inviteHomeRomantic: { id: "inviteHomeRomantic", label: "Come back with me...", color: "#e91e63", basePoints: 3, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "dating", traitModifiers: { boosted: ["Romantic", "Flirty", "Confident"], reduced: ["Shy"], blocked: [] } }, endThings: { id: "endThings", label: "We need a talk...", color: "#9e9e9e", basePoints: 0, minRelLevel: 0, maxRelLevel: 5, category: "romantic", romanceRequirement: "anyRomance", traitModifiers: { boosted: [], reduced: [], blocked: [] } } } }>> /* ====================================================================== */ /* ORIENTATION COMPATIBILITY CHECK */ /* ====================================================================== */ <<set setup.checkOrientationCompatibility = function(npc, playerGender) { var npcGender = npc.gender; var orientation = null; /* Find NPC's orientation from their mental traits */ var orientations = ["Straight", "Gay", "Lesbian", "Bisexual", "Pansexual", "Asexual", "Demisexual", "Questioning", "Fluid"]; for (var i = 0; i < npc.mentalTraits.length; i++) { if (orientations.includes(npc.mentalTraits[i])) { orientation = npc.mentalTraits[i]; break; } } /* Default to Bisexual if no orientation set (most flexible) */ if (!orientation) orientation = "Bisexual"; var sameGender = (npcGender === playerGender); switch(orientation) { case "Straight": return sameGender ? "incompatible" : "compatible"; case "Gay": return (npcGender === "male" && sameGender) ? "compatible" : "incompatible"; case "Lesbian": return (npcGender === "female" && sameGender) ? "compatible" : "incompatible"; case "Bisexual": case "Pansexual": return "compatible"; case "Asexual": return "asexual"; case "Demisexual": return "demisexual"; case "Questioning": return "questioning"; case "Fluid": return Math.random() > 0.5 ? "compatible" : "incompatible"; default: return "compatible"; } }>> /* ====================================================================== */ /* FLIRT OUTCOME CALCULATION */ /* ====================================================================== */ <<set setup.calculateFlirtOutcome = function(npc, relLevel) { var v = State.variables; var playerGender = v.bodyParts.gender; var compatibility = setup.checkOrientationCompatibility(npc, playerGender); var result = { success: false, points: 0, responseType: "neutral", message: "" }; /* Handle special orientations */ if (compatibility === "asexual") { if (relLevel >= 3 && (npc.mentalTraits.includes("Romantic") || npc.mentalTraits.includes("Kind"))) { result.responseType = "polite_decline"; result.points = 0; result.message = "appreciates_attention"; } else { result.responseType = "uncomfortable"; result.points = -1; result.message = "not_interested"; } return result; } if (compatibility === "demisexual") { if (relLevel >= 3) { compatibility = "compatible"; } else { result.responseType = "confused"; result.points = -1; result.message = "too_soon"; return result; } } if (compatibility === "questioning") { compatibility = Math.random() > 0.3 ? "compatible" : "incompatible"; } /* Incompatible orientation */ if (compatibility === "incompatible") { if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Polite") || npc.mentalTraits.includes("Friendly")) { result.responseType = "polite_rejection"; result.points = 0; } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude")) { result.responseType = "harsh_rejection"; result.points = -3; } else if (npc.mentalTraits.includes("Awkward") || npc.mentalTraits.includes("Shy")) { result.responseType = "awkward_rejection"; result.points = -1; } else { result.responseType = "standard_rejection"; result.points = -1; } return result; } /* Romance boost: Lover+ partners always respond well */ if (setup.romance && setup.romance.isRomantic(npc.name)) { var romLvl = setup.romance.getRomanceLevel(npc.name); if (romLvl === "lover" || romLvl === "soulmate") { result.success = true; result.points = 3; result.responseType = "romantic_partner"; return result; } } /* Compatible orientation - check other factors */ result.success = true; /* Base points - successful flirts always give at least +5 */ var basePoints = 5; /* Check for sexual/erotic traits on both sides for more explicit responses */ var playerSexualTraits = ["Seductive", "Flirty", "Lustful", "Nymphomaniac", "Perverted", "Lewd"]; var npcSexualTraits = ["Seductive", "Flirty", "Lustful", "Nymphomaniac", "Perverted", "Lewd"]; var playerHasSexualTrait = playerSexualTraits.some(function(trait) { return v.mentalTraits && v.mentalTraits.includes(trait); }); var npcHasSexualTrait = npcSexualTraits.some(function(trait) { return npc.mentalTraits && npc.mentalTraits.includes(trait); }); /* Both have sexual traits - unlock erotic responses */ var enableEroticResponse = playerHasSexualTrait && npcHasSexualTrait && relLevel >= 1; /* Even more explicit at higher relationship levels */ var enableExplicitResponse = playerHasSexualTrait && npcHasSexualTrait && relLevel >= 3; /* Set intensity level for response generation */ result.sexualIntensity = 0; if (enableExplicitResponse) { result.sexualIntensity = 2; /* Very explicit */ basePoints += 3; } else if (enableEroticResponse) { result.sexualIntensity = 1; /* Moderately erotic */ basePoints += 2; } /* Personality modifiers */ if (npc.mentalTraits.includes("Nymphomaniac") || npc.mentalTraits.includes("Lustful")) { basePoints += 3; result.responseType = enableExplicitResponse ? "explicit_eager" : (enableEroticResponse ? "sexual_eager" : "flirty_response"); } else if (npc.mentalTraits.includes("Seductive")) { basePoints += 2; result.responseType = enableExplicitResponse ? "explicit_seductive" : (enableEroticResponse ? "sexual_seductive" : "flirty_response"); } else if (npc.mentalTraits.includes("Flirty")) { basePoints += 2; result.responseType = enableEroticResponse ? "sexual_flirty" : "flirty_response"; } else if (npc.mentalTraits.includes("Romantic")) { basePoints += 1; result.responseType = enableEroticResponse ? "sexual_romantic" : "romantic_response"; } else if (npc.mentalTraits.includes("Shy")) { result.responseType = enableEroticResponse ? "sexual_shy" : "flustered_response"; } else if (npc.mentalTraits.includes("Confident")) { result.responseType = enableEroticResponse ? "sexual_confident" : "confident_response"; } else if (npc.mentalTraits.includes("Dominant")) { result.responseType = enableEroticResponse ? "sexual_dominant" : "confident_response"; basePoints += 1; } else if (npc.mentalTraits.includes("Submissive")) { result.responseType = enableEroticResponse ? "sexual_submissive" : "flustered_response"; basePoints += 1; } else if (npc.mentalTraits.includes("Cold")) { basePoints -= 1; result.responseType = "cool_response"; } else if (npc.mentalTraits.includes("Prudish")) { basePoints -= 1; result.responseType = "reserved_response"; } else { result.responseType = enableEroticResponse ? "sexual_positive" : "positive_response"; } /* Strangers might find it too forward */ if (relLevel <= 0) { if (!npc.mentalTraits.includes("Flirty") && !npc.mentalTraits.includes("Outgoing")) { if (Math.random() < 0.3) { result.success = false; result.responseType = "too_forward"; basePoints = -2; } } } /* Ensure successful flirts always give at least +5 points */ if (result.success && basePoints < 5) { basePoints = 5; } result.points = basePoints; return result; }>> /* ====================================================================== */ /* GET AVAILABLE CONVERSATION OPTIONS */ /* ====================================================================== */ <<set setup.getAvailableConversationOptions = function(npc, relLevel) { var options = []; var npcTraits = (npc.mentalTraits || []).concat(npc.physicalTraits || []); var v = State.variables; var playerTraits = (v.mentalTraits || []).concat(v.physicalTraits || []).concat(v.negativeTraits || []); var npcMood = setup.calculateNPCMood(npc, false); var replacedOptions = {}; /* Helper to check NPC trait requirements */ function meetsTraitRequirements(option) { if (option.requiredNPCTraits) { if (option.requiredNPCTraits.any) { var hasAny = option.requiredNPCTraits.any.some(function(trait) { return npc.mentalTraits && npc.mentalTraits.includes(trait); }); if (!hasAny) return false; } if (option.requiredNPCTraits.all) { var hasAll = option.requiredNPCTraits.all.every(function(trait) { return npc.mentalTraits && npc.mentalTraits.includes(trait); }); if (!hasAll) return false; } } if (option.requiredNPCPhysical) { if (option.requiredNPCPhysical.any) { var hasAnyPhysical = option.requiredNPCPhysical.any.some(function(trait) { return npc.physicalTraits && npc.physicalTraits.includes(trait); }); if (!hasAnyPhysical) return false; } } return true; } /* Helper to check player trait requirements */ function meetsPlayerTraitRequirements(option) { if (!option.requiredPlayerTraits) return true; if (option.requiredPlayerTraits.any) { return option.requiredPlayerTraits.any.some(function(trait) { return playerTraits.includes(trait); }); } if (option.requiredPlayerTraits.all) { return option.requiredPlayerTraits.all.every(function(trait) { return playerTraits.includes(trait); }); } return true; } /* Helper to check mood requirements */ function meetsMoodRequirements(option) { if (!option.requiredMood) return true; return option.requiredMood.includes(npcMood.name); } /* Helper to check memory requirements */ function meetsMemoryRequirements(option) { if (!option.memoryRequirement) return true; var v = State.variables; var mem = v.npcMemory && v.npcMemory[npc.name]; if (!mem) return false; var req = option.memoryRequirement; if (req === "reminisce") { return mem.ms.met > 0 && mem.ti >= 10 && ((v.dayNumber || 0) - mem.ms.met) >= 14; } if (req === "insideJoke") { return mem.ti >= 15 && mem.imp.fun >= 10; } if (req === "apologize") { return mem.imp.hostile >= 8 || (mem.tc.insult && mem.tc.insult >= 3); } if (req === "thankGifts") { return mem.gc >= 5; } if (req === "noticedChange") { return setup.traitEvolution && setup.traitEvolution.hasRecentEvolution(npc.name) !== null; } return false; } /* Helper to check if blocked */ function isBlocked(option) { if (!option.traitModifiers || !option.traitModifiers.blocked) return false; return option.traitModifiers.blocked.some(function(trait) { return npcTraits.includes(trait); }); } /* Process shared options first to track replacements */ var sharedOptions = setup.conversationOptions.shared || {}; for (var sKey in sharedOptions) { var sOpt = sharedOptions[sKey]; if (relLevel < sOpt.minRelLevel || relLevel > sOpt.maxRelLevel) continue; if (!meetsTraitRequirements(sOpt)) continue; if (!meetsPlayerTraitRequirements(sOpt)) continue; if (isBlocked(sOpt)) continue; options.push({ option: sOpt, category: "shared" }); if (sOpt.replacesOption) { replacedOptions[sOpt.replacesOption] = true; } } /* Process standard categories */ var categories = ["core", "personality", "relationship", "risky"]; categories.forEach(function(category) { var categoryOptions = setup.conversationOptions[category]; for (var key in categoryOptions) { var option = categoryOptions[key]; /* Skip if replaced by a shared-trait option */ if (replacedOptions[option.id]) continue; /* Check relationship level requirements */ if (relLevel < option.minRelLevel || relLevel > option.maxRelLevel) continue; /* Check trait requirements (except for always available options) */ if (!option.alwaysAvailable && !meetsTraitRequirements(option)) continue; /* Check if blocked */ if (isBlocked(option)) continue; options.push({ option: option, category: category }); } }); /* Process mood-gated options */ var moodOptions = setup.conversationOptions.moodGated || {}; for (var mKey in moodOptions) { var mOpt = moodOptions[mKey]; if (relLevel < mOpt.minRelLevel || relLevel > mOpt.maxRelLevel) continue; if (!meetsMoodRequirements(mOpt)) continue; if (isBlocked(mOpt)) continue; options.push({ option: mOpt, category: "moodGated" }); } /* Process memory-gated options */ var memoryOptions = setup.conversationOptions.memoryGated || {}; for (var memKey in memoryOptions) { var memOpt = memoryOptions[memKey]; if (relLevel < memOpt.minRelLevel || relLevel > memOpt.maxRelLevel) continue; if (!meetsMemoryRequirements(memOpt)) continue; if (isBlocked(memOpt)) continue; options.push({ option: memOpt, category: "memoryGated" }); } /* Process NPC social options */ var socialOptions = setup.conversationOptions.npcSocial || {}; for (var socKey in socialOptions) { var socOpt = socialOptions[socKey]; if (relLevel < socOpt.minRelLevel || relLevel > socOpt.maxRelLevel) continue; if (isBlocked(socOpt)) continue; if (typeof setup.meetsSocialRequirements === "function" && !setup.meetsSocialRequirements(npc, socOpt)) continue; options.push({ option: socOpt, category: "npcSocial" }); } /* Process romantic options */ var romanticOptions = setup.conversationOptions.romantic || {}; for (var romKey in romanticOptions) { var romOpt = romanticOptions[romKey]; if (isBlocked(romOpt)) continue; /* Check romance-specific requirements */ if (!setup.romance.meetsRomanceRequirement(npc, romOpt)) continue; options.push({ option: romOpt, category: "romantic" }); } /* Filter home invite options by runtime state */ options = options.filter(function(entry) { if (entry.option.id === "inviteHomeFriend") { if (setup.romance && setup.romance.isRomantic(npc.name)) return false; return setup.homeVisit && setup.homeVisit.canInvite(npc); } if (entry.option.id === "inviteHomeRomantic") { return setup.homeVisit && setup.homeVisit.canInvite(npc); } return true; }); return options; }>> /* ====================================================================== */ /* CALCULATE DYNAMIC RELATIONSHIP CHANGE */ /* ====================================================================== */ <<set setup.calculateDynamicRelationshipChange = function(npc, optionId, relLevel) { var option = null; var categories = ["core", "personality", "relationship", "risky", "shared", "moodGated", "memoryGated", "npcSocial", "romantic"]; /* Find the option */ for (var i = 0; i < categories.length; i++) { var cat = setup.conversationOptions[categories[i]]; for (var key in cat) { if (cat[key].id === optionId) { option = cat[key]; break; } } if (option) break; } if (!option) return { points: 0, backfired: false }; var npcTraits = (npc.mentalTraits || []).concat(npc.physicalTraits || []); var change = option.basePoints; var backfired = false; /* Apply trait modifiers */ if (option.traitModifiers) { if (option.traitModifiers.boosted) { var boostCount = option.traitModifiers.boosted.filter(function(trait) { return npcTraits.includes(trait); }).length; if (change > 0) { change += boostCount; } else if (change < 0) { change += Math.floor(boostCount / 2); } } if (option.traitModifiers.reduced) { var reduceCount = option.traitModifiers.reduced.filter(function(trait) { return npcTraits.includes(trait); }).length; if (change > 0) { change = Math.max(0, change - reduceCount); } else if (change < 0) { change -= reduceCount; } } } /* Relationship level bonus for positive interactions */ if (relLevel >= 3 && change > 0) { change += 1; } if (relLevel >= 4 && change > 0) { change += 1; } /* Risk mechanics for risky options */ if (option.riskLevel && option.category === "risky") { var backfireChance = 0; if (option.riskLevel === "low") backfireChance = 0.10; else if (option.riskLevel === "medium") backfireChance = 0.20; else if (option.riskLevel === "high") backfireChance = 0.30; if (Math.random() < backfireChance && option.id !== "flirt" && option.id !== "insult") { backfired = true; change = -Math.abs(change) - 1; } } return { points: change, backfired: backfired }; }>> /* ====================================================================== */ /* ORIGINAL NPC GREETING FUNCTION */ /* ====================================================================== */ <<set setup.getNPCGreeting = function(npc, relLevel) { var v = State.variables; var memInsert = setup.getMemoryGreetingInsert ? setup.getMemoryGreetingInsert(npc.name, relLevel) : ""; var socialInsert = setup.npcSocial && setup.npcSocial.getSocialGreetingInsert ? setup.npcSocial.getSocialGreetingInsert(npc.name) : ""; var romInsert = setup.romance && setup.romance.getRomanticGreetingInsert ? setup.romance.getRomanticGreetingInsert(npc.name) : ""; /* Priority: romantic overrides memory; cap at one prefix + one suffix */ var prefixInsert = romInsert || memInsert; var suffixInsert = socialInsert; if (prefixInsert && suffixInsert && Math.random() < 0.5) { suffixInsert = ""; } /* Initialize lastSeen on first conversation if npcMemory exists */ if (State.variables.npcMemory && State.variables.npcMemory[npc.name] && !State.variables.npcMemory[npc.name].lastSeen) { setup.updateLastSeen(npc.name); } /* Context-aware greeting check — weather, time, player changes. Skipped for NPCs with uniqueDialogue.greetings so their custom lines always play. */ if (!(npc.uniqueDialogue && npc.uniqueDialogue.greetings)) { var contextGreeting = setup.getContextualGreeting(npc, relLevel); if (contextGreeting) { var cFlavor = setup.getSpeechFlavor(npc); return cFlavor.prefix + setup.getMoodGreetingPrefix(npc) + contextGreeting + cFlavor.suffix; } } /* Check for unique dialogue first (for special 7 key NPCs only) */ if (npc.uniqueDialogue && npc.uniqueDialogue.greetings) { var relKey; /* Lover tier overrides relationship level if NPC is in lover/soulmate romance state */ var loverState = false; if (setup.romance && setup.romance.isRomantic && setup.romance.isRomantic(npc.name)) { var rl = setup.romance.getRomanceLevel(npc.name); if (rl === "lover" || rl === "soulmate") loverState = true; } if (loverState && npc.uniqueDialogue.greetings.lover && npc.uniqueDialogue.greetings.lover.length > 0) { relKey = "lover"; } else if (relLevel === -1) { relKey = "disliked"; } else if (relLevel === 0) { relKey = "stranger"; } else if (relLevel === 1) { relKey = "acquaintance"; } else if (relLevel === 2) { relKey = "friend"; } else if (relLevel === 3) { relKey = "closeFriend"; } else { relKey = "bestFriend"; } if (npc.uniqueDialogue.greetings[relKey] && npc.uniqueDialogue.greetings[relKey].length > 0) { var uniqueGreetings = npc.uniqueDialogue.greetings[relKey]; var finalGreeting = setup.getMoodGreetingPrefix(npc) + prefixInsert + uniqueGreetings[Math.floor(Math.random() * uniqueGreetings.length)] + suffixInsert; var V_PNS = State.variables; var pName = V_PNS.firstName || (V_PNS.dreamPlayer && V_PNS.dreamPlayer.firstName) || "you"; finalGreeting = String(finalGreeting).replace(/\{\{playerName\}\}/g, pName); var flavor = setup.getSpeechFlavor(npc); return flavor.prefix + finalGreeting + flavor.suffix; } } /* Use trait-based dialogue generation for all other NPCs */ var finalGreeting = setup.getMoodGreetingPrefix(npc) + prefixInsert + setup.generateTraitBasedGreeting(npc, relLevel) + suffixInsert; var flavor = setup.getSpeechFlavor(npc); return flavor.prefix + finalGreeting + flavor.suffix; }>> /* ====================================================================== */ /* TRAIT-BASED DIALOGUE GENERATION SYSTEM */ /* ====================================================================== */ /* Generate greeting based on NPC's current trait combination */ <<set setup.generateTraitBasedGreeting = function(npc, relLevel) { if (!npc || !npc.mentalTraits) return "Hello."; var v = State.variables; var greeting = ""; var addOn = ""; /* Determine relationship level text */ var relLevels = ["stranger", "acquaintance", "friend", "closeFriend", "bestFriend"]; var relKey = relLevel === -1 ? "disliked" : (relLevels[Math.min(relLevel, 4)] || "stranger"); /* Get dominant personality traits (top 3 mental traits) */ var dominantTraits = npc.mentalTraits.slice(0, 3); /* GREETING OPENER - Based on primary personality trait */ var primaryTrait = npc.primaryPersonality || npc.mentalTraits[0]; /* Generate greeting based on personality + relationship */ if (relKey === "disliked") { greeting = setup.generateDislikedGreeting(npc, primaryTrait, dominantTraits); } else if (relKey === "stranger") { greeting = setup.generateStrangerGreeting(npc, primaryTrait, dominantTraits); } else if (relKey === "acquaintance") { greeting = setup.generateAcquaintanceGreeting(npc, primaryTrait, dominantTraits); } else if (relKey === "friend") { greeting = setup.generateFriendGreeting(npc, primaryTrait, dominantTraits); } else if (relKey === "closeFriend") { greeting = setup.generateCloseFriendGreeting(npc, primaryTrait, dominantTraits); } else { greeting = setup.generateBestFriendGreeting(npc, primaryTrait, dominantTraits); } /* Add physical trait observations (if relationship level allows) */ if (relLevel >= 1) { var physicalComment = setup.generatePhysicalTraitComment(npc, v); if (physicalComment) { addOn = " " + physicalComment; } } /* Add job-related comment (if applicable and relationship allows) */ if (relLevel >= 1 && Math.random() < 0.3) { var jobComment = setup.generateJobRelatedComment(npc, dominantTraits); if (jobComment && !addOn) { addOn = " " + jobComment; } } return greeting + addOn; }>> /* Generate DISLIKED greeting based on traits - they actively dislike the player */ <<set setup.generateDislikedGreeting = function(npc, primaryTrait, traits) { var greetings = []; /* Aggressive/Violent types */ if (traits.includes("Aggressive") || traits.includes("Violent") || traits.includes("Short Tempered")) { greetings.push("*glares menacingly* What the hell do YOU want? Get out of my face before I make you."); greetings.push("*clenches fists* Oh, it's YOU. You've got some nerve showing your face around here."); greetings.push("*steps forward aggressively* I suggest you leave. Now. Before I do something I won't regret."); greetings.push("*cracks knuckles* Keep walking. I'm not in the mood for your bullshit today."); greetings.push("*blocks your path* You really don't learn, do you? Get. Lost."); } /* Bitchy/Rude types */ else if (traits.includes("Bitchy") || traits.includes("Rude") || traits.includes("Mean")) { greetings.push("*rolls eyes dramatically* Oh god, not you again. Don't you have anyone else to annoy?"); greetings.push("*sneers* Well, well... if it isn't my least favorite person. What do you want?"); greetings.push("*scoffs* Ugh. I was having a decent day until you showed up."); greetings.push("*looks at you with disgust* Can you just... not? I really don't want to deal with you."); greetings.push("*fake smile* Oh look, the human headache is back. Joy."); } /* Cold/Cynical types */ else if (traits.includes("Cold") || traits.includes("Cynical") || traits.includes("Emotionless")) { greetings.push("*expressionless stare* You. Leave."); greetings.push("*flat tone* I have nothing to say to you. Goodbye."); greetings.push("*looks through you* We have no business together. Stop wasting my time."); greetings.push("*doesn't even look up* Still here? I thought I made my position clear."); greetings.push("*blank expression* You exist. Unfortunately."); } /* Shy/Sensitive types (hurt rather than angry) */ else if (traits.includes("Shy") || traits.includes("Sensitive") || traits.includes("Insecure")) { greetings.push("*avoids eye contact* Oh... it's you. I... I'd rather not talk to you right now..."); greetings.push("*looks away, hurt* Why are you talking to me? Haven't you done enough?"); greetings.push("*voice trembling* Please just... leave me alone. Please."); greetings.push("*flinches and steps back* I... I don't want any trouble. Can you please go?"); greetings.push("*hugs self protectively* Not you... please, I can't handle this right now..."); } /* Kind/Warm types (disappointed rather than hostile) */ else if (traits.includes("Kind") || traits.includes("Warm") || traits.includes("Friendly")) { greetings.push("*sighs sadly* I really hoped things between us would be different. What do you want?"); greetings.push("*looks at you with disappointment* I don't understand why you act the way you do. Is there something I can help you with?"); greetings.push("*crosses arms* Look, I try to see the best in people, but you make it really hard sometimes."); greetings.push("*pained expression* I keep hoping you'll surprise me, but... what is it this time?"); } /* Confident/Arrogant types */ else if (traits.includes("Confident") || traits.includes("Arrogant") || traits.includes("Dominant")) { greetings.push("*looks at you with contempt* Oh, it's you. Still haven't learned to stay in your lane, I see."); greetings.push("*dismissive wave* What could you possibly want from me? Make it quick, I have better things to do."); greetings.push("*smirks coldly* You're brave, I'll give you that. Stupid, but brave. What is it?"); greetings.push("*barely acknowledges your presence* Oh, you're still around? I assumed you'd figured out you're outclassed by now."); } /* Flirty/Seductive types (weaponized charm) */ else if (traits.includes("Flirty") || traits.includes("Seductive")) { greetings.push("*icy smile* Oh, sweetie... I'd rather kiss a dumpster than waste my time on you."); greetings.push("*looks you up and down dismissively* Hmm, no. Not interested. Try someone with lower standards."); greetings.push("*laughs coldly* You? Talking to me? After everything? That's adorable."); greetings.push("*inspects nails with disinterest* Oh, it's you. Don't you have someone else to bore?"); greetings.push("*venomous smile* Back for more rejection? Some people really are gluttons for punishment."); } /* Default hostile greeting */ else { greetings.push("*frowns* Oh. It's you. What do you want?"); greetings.push("*sighs heavily* I thought I made it clear I don't want to talk to you."); greetings.push("*crosses arms* We're not friends. What is it?"); greetings.push("*turns away slightly* Honestly, I'd rather not deal with you right now."); greetings.push("*flat stare* Is there a reason you keep bothering me?"); } return setup.pickWithoutRepeat(greetings, npc.name, "greetings"); }>> /* Generate stranger greeting based on traits */ <<set setup.generateStrangerGreeting = function(npc, primaryTrait, traits) { var greetings = []; /* Dominant/Arrogant/Diva */ if (traits.includes("Dominant") || traits.includes("Arrogant") || traits.includes("Diva")) { greetings.push("*looks you over* And you are?"); greetings.push("I don't believe we've met. Make it quick."); greetings.push("*barely glances up* Yes? What do you want?"); greetings.push("*sizing you up* You'd better have a good reason for approaching me."); if (traits.includes("Bitchy") || traits.includes("Rude")) { greetings.push("*sighs* Another stranger wasting my time."); greetings.push("Do I look like I have time for random people?"); } } /* Submissive/Shy/Awkward */ else if (traits.includes("Submissive") || traits.includes("Shy") || traits.includes("Awkward")) { greetings.push("*looks down nervously* H-hi... um..."); greetings.push("Oh! Um... c-can I help you with something?"); greetings.push("*fidgets* Hello... I don't think we've... um... met?"); greetings.push("*plays with hem of shirt* S-sorry, are you... talking to me?"); if (traits.includes("Kind") || traits.includes("Warm")) { greetings.push("*smiles shyly* Hi there... welcome..."); } } /* Flirty/Seductive */ else if (traits.includes("Flirty") || traits.includes("Seductive")) { greetings.push("*smiles playfully* Well hello there... new face?"); greetings.push("Mmm, I like what I see. What brings you to me?"); greetings.push("*leans in* Hey gorgeous. I don't think we've been... properly introduced."); greetings.push("*tilts head with a smile* Fresh meat? I like that. Come closer."); if (traits.includes("Confident")) { greetings.push("*looks you up and down with a grin* You're interesting. I'm " + npc.name + "."); } } /* Bimbo */ else if (traits.includes("Bimbo")) { greetings.push("*giggles* Hiiii! Like, who are you? You're cute!"); greetings.push("Omigod, hi! I, like, totally don't know you yet!"); greetings.push("*twirls hair* Heyyy there! I'm " + npc.name + "! What's your name?"); greetings.push("*gasps* Oh em gee, a new person! I love meeting new people! Hi hi hi!"); } /* Cold/Cynical */ else if (traits.includes("Cold") || traits.includes("Cynical")) { greetings.push("*expressionless* What is it?"); greetings.push("*barely acknowledges you* Something you need?"); greetings.push("Yeah? State your business."); greetings.push("*side-eye* I don't do small talk. Get to the point."); if (traits.includes("Intelligent")) { greetings.push("I don't have time for pleasantries. What do you want?"); } } /* Bitchy/Rude/Mean */ else if (traits.includes("Bitchy") || traits.includes("Rude") || traits.includes("Mean")) { greetings.push("What? Can't you see I'm busy?"); greetings.push("*rolls eyes* Great. Another person bothering me."); greetings.push("Do I know you? No? Then why are you in my space?"); greetings.push("*looks you up and down* Hmm. Nobody important. What do you want?"); } /* Kind/Warm/Friendly */ else if (traits.includes("Kind") || traits.includes("Warm") || traits.includes("Friendly")) { greetings.push("*smiles warmly* Hello! I don't think we've met. I'm " + npc.name + "!"); greetings.push("Hi there! Welcome! How can I help you today?"); greetings.push("*friendly wave* Hey! New around here? Nice to meet you!"); greetings.push("*bright smile* Oh, hello! I always love meeting new faces around the island!"); if (traits.includes("Nurturing")) { greetings.push("Hello dear. You look like you could use some kindness. What brings you here?"); } } /* Energetic/Excited/Outgoing */ else if (traits.includes("Energetic") || traits.includes("Excited") || traits.includes("Outgoing")) { greetings.push("*bounces over* Hey! Oh wow, a new person! Hi hi hi!"); greetings.push("Yo! What's up! I'm " + npc.name + "! Who are you?!"); greetings.push("*enthusiastically* HEY THERE! New face! That's so cool!"); greetings.push("*jogs up grinning* Dude! Haven't seen you around before! You new?!"); if (traits.includes("Jock")) { greetings.push("Yo bro! Haven't seen you around! You here to work out?"); } } /* Calm/Patient/Chill */ else if (traits.includes("Calm") || traits.includes("Patient") || traits.includes("Chill")) { greetings.push("*nods calmly* Hello. Something I can do for you?"); greetings.push("Hey. Don't think we've met. What's up?"); greetings.push("*relaxed smile* Hi there. New around here?"); greetings.push("*easy-going nod* Hey. No rush, take your time."); } /* Goth */ else if (traits.includes("Goth")) { greetings.push("*looks up from book* Mmm? Need something?"); greetings.push("*barely interested* Yeah, hi. What do you want?"); greetings.push("Another normie. Great. What is it?"); greetings.push("*dark stare* You have a vibe. I haven't decided if it's a good one yet."); } /* Nerd */ else if (traits.includes("Nerd")) { greetings.push("*adjusts glasses* Oh, hello. Can I help you with something?"); greetings.push("Hi! I don't believe we've been introduced. I'm " + npc.name + "."); greetings.push("*looks up curiously* Oh, a new person. Interesting."); greetings.push("*pauses mid-thought* Hm? Oh, hi. Sorry, I was working something out in my head."); } /* Default */ else { greetings.push("Hi there. Something I can do for you?"); greetings.push("Hello. Don't think we've met."); greetings.push("Hey. What brings you here?"); greetings.push("*glances over* Oh, hey. You looking for someone?"); } return setup.pickWithoutRepeat(greetings, npc.name, "greetings"); }>> /* Generate acquaintance, friend, close friend, and best friend greetings */ <<set setup.generateAcquaintanceGreeting = function(npc, primaryTrait, traits) { var greetings = []; if (traits.includes("Dominant") || traits.includes("Arrogant")) { greetings.push("*acknowledges with a nod* You again. What is it this time?"); greetings.push("Ah yes, I remember you. What do you need?"); greetings.push("*crosses arms appraisingly* You're persistent. I respect that. Barely."); greetings.push("*looks up from what they're doing* You. Speak. I'm listening."); if (traits.includes("Confident")) greetings.push("Back for more? I suppose you've proven you're not completely useless."); } else if (traits.includes("Submissive") || traits.includes("Shy")) { greetings.push("*smiles nervously* Oh, hi again... nice to see you..."); greetings.push("*waves shyly* H-hey... you came back..."); greetings.push("*fidgets with hands* I... I was hoping I'd run into you again..."); greetings.push("*looks up with wide eyes* Oh! It's you... h-hi..."); greetings.push("*small voice* Hey... I remembered your name this time... is that weird?"); } else if (traits.includes("Flirty") || traits.includes("Seductive")) { greetings.push("*playful smile* Well well, look who's back. Couldn't stay away?"); greetings.push("Hey gorgeous. Miss me already?"); greetings.push("*winks* There's that face I've been thinking about. How you been?"); greetings.push("*leans against wall* Mm, I was wondering when you'd come find me again."); greetings.push("*bites lip* Oh good, you're here. I was getting bored without eye candy."); } else if (traits.includes("Bimbo")) { greetings.push("*giggles* Omigod hiiii! You came back! That's so sweet!"); greetings.push("Heyyyy! I remember you! Like, totally!"); greetings.push("*claps excitedly* Ohmigosh, it's you again! I was literally just talking about you!"); greetings.push("*bounces* Yaaay, a familiar face! How are you? Wait, don't tell me, let me guess!"); } else if (traits.includes("Friendly") || traits.includes("Warm")) { greetings.push("Hey! Good to see you again! How have you been?"); greetings.push("*smiles warmly* Oh hello again! Welcome back!"); greetings.push("*waves cheerfully* Hey there! I was hoping we'd bump into each other again!"); greetings.push("*bright smile* Oh it's you! How's your day going so far?"); } else if (traits.includes("Cold") || traits.includes("Cynical")) { greetings.push("*glances up* Oh. You again."); greetings.push("Back already? What now?"); greetings.push("*dry tone* We keep running into each other. What a coincidence."); greetings.push("*brief nod* You. I remember you. That's... something, I guess."); } else if (traits.includes("Energetic")) { greetings.push("Hey hey! You're back! What's up!"); greetings.push("*enthusiastic wave* Yo! Good to see you again!"); greetings.push("*grins wide* Dude! There you are! I was just thinking about something wild!"); greetings.push("*punches your arm lightly* Heyyy! What's been happening? Catch me up!"); } else { greetings.push("Hey, I remember you. What's up?"); greetings.push("Oh hey. Back again?"); greetings.push("*nods in recognition* Hey. Good to see a familiar face around here."); greetings.push("*casual wave* Oh, hey. I was just thinking I haven't seen you in a while."); } return setup.pickWithoutRepeat(greetings, npc.name, "greetings"); }>> <<set setup.generateFriendGreeting = function(npc, primaryTrait, traits) { var greetings = []; if (traits.includes("Dominant")) { greetings.push("*approving nod* There you are. I was wondering when you'd show up."); greetings.push("Good. Someone competent finally arrives."); greetings.push("*beckons you over* Come. I've been saving something important to discuss with you."); greetings.push("*firm handshake* Right on time. I expect nothing less from you."); greetings.push("About time. You're one of the few people I actually want around."); } else if (traits.includes("Submissive")) { greetings.push("*lights up* Oh! You're here! I'm so happy to see you!"); greetings.push("*blushes* Hi... I was hoping you'd come by..."); greetings.push("*reaches for your hand* You're here... I always feel safer when you're around."); greetings.push("*soft gasp* Oh! I... I kept looking at the door hoping it would be you!"); greetings.push("*smiles shyly* I saved you a spot next to me... if you want it..."); } else if (traits.includes("Flirty") || traits.includes("Seductive")) { greetings.push("*grins* There's my favorite person. Come here."); greetings.push("Hey sexy. Been thinking about you."); greetings.push("*traces a finger along your arm* Mmm, there you are. My day just got way more interesting."); greetings.push("*slow smile* You know, you always show up right when I need a distraction."); greetings.push("*leans close* Hey you. I had a dream about you. Want to hear about it?"); } else if (traits.includes("Bimbo")) { greetings.push("OMIGOD! *squeals and bounces* You're here! Yaaay!"); greetings.push("*hugs excitedly* Hiii bestie! I missed you soooo much!"); greetings.push("*grabs your arm* Oh em gee, you are NOT going to believe what happened to me today!"); greetings.push("*jumps up and down* Ahhh! My favorite person! Come come come, sit with me!"); greetings.push("*waves frantically* Over here! Over here! I saved you a seat and EVERYTHING!"); } else if (traits.includes("Warm") || traits.includes("Kind")) { greetings.push("*warm hug* There you are! I've missed you!"); greetings.push("Hey friend! It's so good to see you! How have you been?"); greetings.push("*touches your shoulder gently* Hey you. I was just thinking about you."); greetings.push("*beaming* There's that smile! My day always gets better when you show up."); greetings.push("*pulls out a chair for you* I got your favorite. Come sit with me!"); } else if (traits.includes("Cold") || traits.includes("Cynical")) { greetings.push("*slight smile* You. Good. At least there's one tolerable person here."); greetings.push("Finally, someone with a brain. Hey."); greetings.push("*rare smirk* You again. I don't completely hate it."); greetings.push("*deadpan* Oh good, the one person who doesn't make me want to walk into the ocean."); greetings.push("You showed up. I might even admit I'm glad. Might."); } else if (traits.includes("Energetic") || traits.includes("Jock")) { greetings.push("YO! My buddy! *enthusiastic fist bump* Let's DO this!"); greetings.push("There's my bro! What's good! Ready to crush it?"); greetings.push("*bear hug* DUDE! Perfect timing! I need a partner for this wild idea I had!"); greetings.push("*slaps your back* There you are! I was about to come find you! Let's go!"); greetings.push("*pumped* Yo, I've been waiting for you! We gotta hit the beach today!"); } else if (traits.includes("Calm")) { greetings.push("*genuine smile* Hey. Always good to see you."); greetings.push("There you are. Good timing."); greetings.push("*relaxed wave* Hey. Pull up a chair. No rush."); greetings.push("*nods contentedly* Good to see you. Been a peaceful day so far."); greetings.push("*easy smile* Hey friend. How's the island treating you?"); } else { greetings.push("Hey friend! Good to see you!"); greetings.push("*smiles* There you are. I was hoping you'd stop by."); greetings.push("*waves you over* Hey! Come hang out. I could use the company."); greetings.push("*grins* There's a face I'm happy to see. What's going on?"); greetings.push("*nods warmly* Perfect timing. I was just about to take a break."); } return setup.pickWithoutRepeat(greetings, npc.name, "greetings"); }>> <<set setup.generateCloseFriendGreeting = function(npc, primaryTrait, traits) { var greetings = []; if (traits.includes("Dominant")) { greetings.push("*rare genuine smile* There you are. I've been wanting to discuss something with you."); greetings.push("Finally, someone I can actually rely on. Come here."); greetings.push("*clasps your shoulder firmly* You and I need to talk. In a good way, for once."); greetings.push("*softens visibly* Good. You're here. I don't trust anyone else with what I'm about to say."); greetings.push("*nods with quiet respect* I saved you a seat. Don't let it go to your head."); } else if (traits.includes("Submissive")) { greetings.push("*practically glowing* You came! I... I really needed to see you today."); greetings.push("*runs over happily* You're here! Everything's better when you're around..."); greetings.push("*grabs your hand tightly* Please don't go anywhere today... I need you close..."); greetings.push("*voice cracks with relief* I was so afraid you wouldn't come... thank you..."); greetings.push("*presses close* You're like my anchor. I feel lost without you sometimes."); } else if (traits.includes("Flirty") || traits.includes("Seductive")) { greetings.push("*pulls you close* There you are. I've been thinking about you all day."); greetings.push("*intimate smile* Finally. Come here, I want you close."); greetings.push("*wraps arms around you* Mmm, you smell incredible. Don't ever stop coming to see me."); greetings.push("*whispers in your ear* I saved something special for you. Stay awhile."); greetings.push("*heated gaze* You have no idea what you do to me when you walk in like that."); } else if (traits.includes("Bimbo")) { greetings.push("*squeals and tackles you in a hug* OMG OMG OMG! You're here! I have SO much to tell you!"); greetings.push("BABE! *grabs your hands* Like, where have you BEEN? I missed you so so so much!"); greetings.push("*literally jumping* Oh my GAWD I have been DYING to see you! Okay okay okay, sit down, you need to hear this!"); greetings.push("*clings to your arm* You're not leaving my side today! I already decided! We're hanging out ALL day!"); greetings.push("*happy tears* You always come when I need you! You're, like, literally my guardian angel or whatever!"); } else if (traits.includes("Kind") || traits.includes("Warm")) { greetings.push("*emotional embrace* There you are. You know you're one of the most important people in my life, right?"); greetings.push("*beaming* My dear friend! I'm so happy you're here!"); greetings.push("*holds you at arm's length, smiling* Let me look at you. There's that face I love."); greetings.push("*cups your face gently* Hey you. I made you something. It's nothing big, but I thought of you."); greetings.push("*eyes shining* You know, every time I see you, my heart feels a little fuller."); } else if (traits.includes("Cold") || traits.includes("Cynical")) { greetings.push("*genuine emotion breaks through* You. Thank fuck. Everyone else is insufferable."); greetings.push("*drops the cold act* Finally. Someone I can actually talk to."); greetings.push("*exhales with relief* I was surrounded by morons all day. You're a breath of fresh air."); greetings.push("*almost smiles* Don't tell anyone, but I actually looked forward to seeing you today."); greetings.push("*quiet, honest tone* You're the only person I don't have to pretend around. Get over here."); } else if (traits.includes("Energetic")) { greetings.push("YES! THERE YOU ARE! Dude I have SO MUCH to tell you!"); greetings.push("MY PERSON! *excited* I was literally just about to text you!"); greetings.push("*grabs you by the shoulders* OKAY. You are not going to BELIEVE what just happened!"); greetings.push("*practically vibrating* Dude! DUDE! I had the BEST idea and I need you for it!"); greetings.push("*tackles you in a hug* I missed you SO BAD! We have catching up to do! Let's GO!"); } else { greetings.push("*genuine warmth* There you are. I'm really glad you're here."); greetings.push("Hey you. Perfect timing. I really wanted to see you."); greetings.push("*warm embrace* I don't say it enough, but you really make my day brighter."); greetings.push("*quiet smile* Hey. I was thinking about you earlier. How are you, really?"); greetings.push("*squeezes your hand* There's my person. Come on, let's catch up properly."); } return setup.pickWithoutRepeat(greetings, npc.name, "greetings"); }>> <<set setup.generateBestFriendGreeting = function(npc, primaryTrait, traits) { var greetings = []; if (traits.includes("Dominant")) { greetings.push("*completely drops façade* Finally. You're the only person who truly understands me."); greetings.push("*rare vulnerability* Thank god you're here. I need your counsel on something important."); greetings.push("*voice drops to honest quiet* I would never say this to anyone else, but... I missed you."); greetings.push("*pulls you aside* Listen. You're the only one I trust completely. I need you to know that."); greetings.push("*grips your arm, eyes intense* You and me. We're a team. Don't ever forget that."); } else if (traits.includes("Submissive")) { greetings.push("*tears up with happiness* You're here... You always know when I need you most..."); greetings.push("*emotional* I don't know what I'd do without you. You mean everything to me."); greetings.push("*buries face in your chest* Don't leave... please... you're the only one who makes me feel safe..."); greetings.push("*whispers* I had a rough day, but just seeing you... everything's okay now..."); greetings.push("*clings to you* Promise you won't ever leave me? I... I need you so much..."); } else if (traits.includes("Flirty") || traits.includes("Seductive")) { greetings.push("*intimate and genuine* There's no one I'd rather see right now. Come here, beautiful."); greetings.push("*drops all pretense* You know you're special, right? Like, actually special to me."); greetings.push("*forehead pressed to yours* Forget everyone else. You're the only one who matters."); greetings.push("*takes your face in both hands* Hey. I love you. For real. No games."); greetings.push("*pulls you into a long embrace* I've been aching to hold you. Don't let go yet."); } else if (traits.includes("Bimbo")) { greetings.push("*literally squeals* MY BESTIE! MY FAVORITE PERSON IN THE WHOLE WORLD! *won't let go of hug*"); greetings.push("YOU! Like, seriously, you're literally the BEST thing in my life! I love you SO much!"); greetings.push("*sobbing happy tears* I just... I love you SO much and you're SO amazing and I don't deserve you!"); greetings.push("*won't stop hugging* You are my PERSON! Like, my SOUL person! Nothing makes sense without you!"); greetings.push("*grabs your face, dead serious for once* No really though. You're, like, the most important person ever. EVER."); } else if (traits.includes("Kind") || traits.includes("Warm")) { greetings.push("*overcome with emotion* You... You're family to me. You know that, right?"); greetings.push("*tight hug* There's my person. I love you so much."); greetings.push("*tears forming* Every day I thank the universe for putting you in my life. Come here."); greetings.push("*holds both your hands* I was thinking about all we've been through together, and I just... I'm grateful."); greetings.push("*long, warm embrace* You're home to me. No matter where we are, if you're here, I'm home."); } else if (traits.includes("Cold") || traits.includes("Cynical")) { greetings.push("*all walls down* You're the only real thing in this fake-ass city. Get over here."); greetings.push("*actually smiles* Took you long enough. I was starting to think you'd abandoned me to these idiots."); greetings.push("*quietly* You know I'd burn this whole island down for you, right? ...Don't make me say it twice."); greetings.push("*voice raw with emotion they can't hide* I hate everyone. Except you. You already knew that."); greetings.push("*rare, unguarded moment* If I had to pick one person to face the end of the world with... yeah. It's you."); } else if (traits.includes("Energetic")) { greetings.push("THERE'S MY BEST FRIEND! *tackles you* Dude, DUDE! I love you so much!"); greetings.push("MY PERSON! The BEST person! You make everything better just by existing!"); greetings.push("*screaming with joy* YOU'RE HERE! I have been COUNTING THE MINUTES! I swear! I actually counted!"); greetings.push("*lifts you off the ground in a hug* BEST! FRIEND! EVER! Don't you DARE argue with me on this!"); greetings.push("*literally can't contain themself* Oh my god oh my god oh my god YOU'RE HERE! Today is officially the best day!"); } else { greetings.push("*completely genuine* You're here. You're my best friend. Thank you for existing."); greetings.push("*emotional* I don't say this enough, but you mean the world to me."); greetings.push("*quiet, meaningful look* I don't have the words. But you know. You always know."); greetings.push("*long embrace* I never have to pretend around you. Thank you for being you."); greetings.push("*voice thick with feeling* There's my best friend. My life wouldn't be the same without you in it."); } return setup.pickWithoutRepeat(greetings, npc.name, "greetings"); }>> /* Generate physical trait observation comments */ <<set setup.generatePhysicalTraitComment = function(npc, playerVars) { if (!npc || !playerVars) return null; var comments = []; var traits = npc.mentalTraits; if (playerVars.physicalTraits.includes("Attractive")) { if (traits.includes("Flirty") || traits.includes("Seductive")) { comments.push("Damn, you're looking fine today."); comments.push("You know you're hot, right?"); } else if (traits.includes("Shy")) { comments.push("You... um... you look really nice..."); } else if (traits.includes("Bimbo")) { comments.push("Omigod, you're like, SO pretty!"); } else if (traits.includes("Confident")) { comments.push("Looking good as always."); } } if (playerVars.physicalTraits.includes("Muscular")) { if (traits.includes("Jock") || npc.physicalTraits.includes("Muscular")) { comments.push("Bro, those gains! Looking swole!"); comments.push("Been hitting the gym hard, I can tell!"); } else if (traits.includes("Flirty")) { comments.push("*touches your arm* Mmm, someone's been working out..."); } } if (playerVars.physicalTraits.includes("Curvy") || playerVars.physicalTraits.includes("Voluptuous") || (playerVars.mentalTraits.includes("Succubus") || playerVars.mentalTraits.includes("Voluptuous Succubus")) || playerVars.mentalTraits.includes("Hucow")) { if (traits.includes("Flirty") || traits.includes("Seductive")) { comments.push("Those curves though... damn."); } else if (traits.includes("Bimbo")) { comments.push("Your body is like, totally amazing!"); } } if (playerVars.physicalTraits.includes("Fashionable")) { if (traits.includes("Diva") || traits.includes("Prep") || npc.physicalTraits.includes("Fashionable")) { comments.push("Love your outfit. You have great taste."); } else if (traits.includes("Bimbo")) { comments.push("Your clothes are SO cute!"); } } if (playerVars.physicalTraits.includes("Tattooed")) { if (traits.includes("Goth") || npc.physicalTraits.includes("Tattooed")) { comments.push("Digging the ink."); } else if (traits.includes("Arrogant")) { comments.push("Tattoos? Interesting choice."); } } return comments.length > 0 ? comments[Math.floor(Math.random() * comments.length)] : null; }>> /* Generate job-related comments */ <<set setup.generateJobRelatedComment = function(npc, traits) { if (!npc || !npc.jobs || npc.jobs.length === 0) return null; var job = npc.jobs[0]; var comments = []; if (traits.includes("Hardworking") || traits.includes("Workaholic")) { comments.push("Work's been crazy busy lately."); comments.push("Been putting in extra hours at " + job + "."); } else if (traits.includes("Lazy")) { comments.push("Ugh, don't even get me started on work."); comments.push("Can't wait until this shift is over."); } else if (traits.includes("Passionate") || traits.includes("Dedicated")) { comments.push("I actually love this job, you know?"); comments.push("Being a " + job + " is really fulfilling."); } return comments.length > 0 ? comments[Math.floor(Math.random() * comments.length)] : null; }>> /* OLD CODE BELOW - TO BE REMOVED */ <<if false>> /* Base greeting on relationship level AND personality */ if (relLevel === 0) { /* Stranger greetings - personality driven */ if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude")) { greetings.push("What? Can't you see I'm busy?"); greetings.push("Do I know you? No? Then why are you talking to me?"); greetings.push("*sighs* What do you want?"); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Awkward")) { greetings.push("Oh... um, hi. Can I... help you with something?"); greetings.push("H-hello there..."); greetings.push("Um... yes?"); } else if (npc.mentalTraits.includes("Arrogant") || npc.mentalTraits.includes("Diva")) { greetings.push("Yes? Make it quick, I have places to be."); greetings.push("You have my attention. For now."); greetings.push("I don't believe we've been introduced. You are...?"); } else if (npc.mentalTraits.includes("Cold") || npc.mentalTraits.includes("Cynical")) { greetings.push("Yeah? What is it?"); greetings.push("Something you need?"); greetings.push("I'm listening."); } else if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Warm")) { greetings.push("Oh, hi there! I don't think we've met. I'm " + npc.name + "!"); greetings.push("Hey! New face around here? Nice to meet you!"); greetings.push("Hello! How can I help you today?"); } else { greetings.push("Hi there. Something I can do for you?"); greetings.push("Yeah? Can I help you with something?"); greetings.push("Oh, it's you. What's up?"); } } else if (relLevel === 1) { /* Acquaintance greetings */ if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Outgoing")) { greetings.push("Hey! Good to see you again! How've you been?"); greetings.push("Oh hey! What brings you by today?"); greetings.push("There you are! Was just thinking about you the other day."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Awkward")) { greetings.push("Oh, hi again... nice to see you..."); greetings.push("Hey... um, how are things?"); greetings.push("*waves nervously* Hi there..."); } else if (npc.mentalTraits.includes("Nonchalant") || npc.mentalTraits.includes("Chill")) { greetings.push("Oh hey, what's up?"); greetings.push("Yo. How's it going?"); greetings.push("Sup. Need something?"); } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Cynical")) { greetings.push("Oh. You again. What now?"); greetings.push("Back already? This should be interesting."); greetings.push("*looks up* Yeah?"); } else { greetings.push("Hey! Good to see you again."); greetings.push("Oh hey, what's up?"); greetings.push("Nice to see a familiar face."); } } else if (relLevel === 2) { /* Friend greetings */ if (npc.mentalTraits.includes("Warm") || npc.mentalTraits.includes("Friendly")) { greetings.push("Hey friend! I'm so glad you stopped by! How have you been?"); greetings.push("There's my favorite person! Come here, tell me everything!"); greetings.push("Perfect timing! I was hoping I'd see you today!"); } else if (npc.mentalTraits.includes("Excited") || npc.mentalTraits.includes("Energetic")) { greetings.push("Omg hey!! How are you?! I have so much to tell you!"); greetings.push("YES! You're here! Okay so you won't believe what happened!"); greetings.push("Hey hey hey! Finally! I've been dying to talk to you!"); } else if (npc.mentalTraits.includes("Calm") || npc.mentalTraits.includes("Chill")) { greetings.push("Hey there. Always good to see you."); greetings.push("What's up, friend? How's life treating you?"); greetings.push("Good to see you. Want to hang out for a bit?"); } else if (npc.mentalTraits.includes("Shy")) { greetings.push("Oh! Hi! I'm... I'm really happy you're here..."); greetings.push("*smiles warmly* Hey... I was hoping you'd come by..."); greetings.push("You came! That makes me really happy..."); } else { greetings.push("Hey friend! How have you been?"); greetings.push("Always happy to see you!"); greetings.push("There you are! I was hoping you'd stop by."); } } else { /* Best friend/Close friend greetings */ if (npc.mentalTraits.includes("Warm") || npc.mentalTraits.includes("Loyal")) { greetings.push("There's my best friend! I've missed you so much! Come sit, we have catching up to do!"); greetings.push("You! Oh my god, finally! I always feel better when you're around!"); greetings.push("Hey you! You know you can always brighten my day just by showing up, right?"); } else if (npc.mentalTraits.includes("Excited") || npc.mentalTraits.includes("Energetic")) { greetings.push("THERE YOU ARE!! I have been WAITING for you! So much to talk about!!"); greetings.push("Finally!! Okay okay, sit down, you NEED to hear this!"); greetings.push("YES! My favorite person in the whole city! Get over here!"); } else if (npc.mentalTraits.includes("Chill") || npc.mentalTraits.includes("Calm")) { greetings.push("Hey bestie. You know I'm always glad when you show up."); greetings.push("There's my person. What's new with you?"); greetings.push("Perfect timing as always. Want to chill for a bit?"); } else if (npc.mentalTraits.includes("Cynical")) { greetings.push("Well well, if it isn't my favorite person. One of the few people in this city worth talking to."); greetings.push("You're here. Good. At least now I have someone interesting to talk to."); greetings.push("Finally, someone with a brain. How are you?"); } else { greetings.push("My dear friend! It's wonderful to see you!"); greetings.push("You! I'm so glad you're here!"); greetings.push("If it isn't my favorite person! Come, sit with me."); } } var baseGreeting = greetings[Math.floor(Math.random() * greetings.length)]; /* Add reactions based on player's physical traits and NPC personality */ var reactions = []; /* React to attractive/ugly based on personality */ if (v.physicalTraits.includes("Attractive") && relLevel >= 1) { if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { reactions.push(" Looking good today... like always."); reactions.push(" Damn, you look fine."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Awkward")) { reactions.push(" You... you look really nice today..."); } else if (!npc.mentalTraits.includes("Cold") && !npc.mentalTraits.includes("Insensitive")) { reactions.push(" You're looking good today."); } } else if (v.physicalTraits.includes("Ugly")) { if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude")) { if (relLevel === 0) { reactions.push(" ...Rough day?"); reactions.push(" Yikes."); } } else if (npc.mentalTraits.includes("Insensitive") || npc.mentalTraits.includes("Blunt")) { reactions.push(" You uh... you alright? You look tired."); } } /* React to muscular based on NPC's own physique */ if (v.physicalTraits.includes("Muscular") && npc.physicalTraits.includes("Muscular") && relLevel >= 1) { if (npc.mentalTraits.includes("Competitive")) { reactions.push(" Been hitting the gym hard, I see. Trying to catch up to me?"); } else if (npc.mentalTraits.includes("Jock")) { reactions.push(" Looking swole! Keep up the gains, bro!"); } else { reactions.push(" Been hitting the gym, I see. Nice work."); } } /* React to curvy/voluptuous */ if ((v.physicalTraits.includes("Curvy") || v.physicalTraits.includes("Voluptuous") || (v.mentalTraits.includes("Succubus") || v.mentalTraits.includes("Voluptuous Succubus")) || v.mentalTraits.includes("Hucow"))) { if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { reactions.push(" Those curves though... damn."); reactions.push(" Looking like a whole meal, as always."); } else if (npc.jobs.includes("Brothel Worker") && relLevel >= 2) { reactions.push(" You've got that body that makes heads turn everywhere."); } } /* React to fashionable */ if (v.physicalTraits.includes("Fashionable")) { if (npc.mentalTraits.includes("Prep") || npc.mentalTraits.includes("Diva") || npc.physicalTraits.includes("Fashionable")) { reactions.push(" Love the outfit! You've got great style!"); } else if (npc.mentalTraits.includes("Goth") && v.physicalTraits.includes("Tattooed")) { reactions.push(" Digging the look."); } } /* React to shared job */ if (v.jobs.length > 0 && npc.jobs.includes(v.jobs[0]) && relLevel >= 1) { if (npc.mentalTraits.includes("Workaholic") || npc.mentalTraits.includes("Hardworking")) { reactions.push(" How's work been treating you? Staying busy?"); } else if (npc.mentalTraits.includes("Lazy")) { reactions.push(" Another day at the grind, huh? Ugh."); } else { reactions.push(" How's work been?"); } } /* React to player being well-dressed and NPC being prep/diva */ if (v.mentalTraits.includes("Prep") && npc.mentalTraits.includes("Prep") && relLevel >= 1) { reactions.push(" You're looking very put-together today. I appreciate that."); } /* React to shared stereotypes */ if (v.mentalTraits.includes("Nerd") && npc.mentalTraits.includes("Nerd") && relLevel >= 1) { reactions.push(" Hey, did you see that new tech release?"); } if (v.mentalTraits.includes("Goth") && npc.mentalTraits.includes("Goth") && relLevel >= 1) { reactions.push(" Dark aesthetic today. I respect it."); } if (reactions.length > 0) { baseGreeting += reactions[Math.floor(Math.random() * reactions.length)]; } return baseGreeting; }>> <</if>> <<set setup.getNPCResponse = function(npc, topic, relLevel) { var v = State.variables; var prefs = setup.getNPCPreferences(npc.name); var responses = []; /* NPC with no mental traits gives hollow, empty responses */ if (!npc.mentalTraits || npc.mentalTraits.length === 0) { var emptyResp = setup.emptyNPCResponses[Math.floor(Math.random() * setup.emptyNPCResponses.length)]; var emptyFlavor = setup.getSpeechFlavor(npc); return emptyFlavor.prefix + setup.getMoodTonedResponse(emptyResp, npc) + emptyFlavor.suffix; } /* Unique dialogue override: per-NPC topic responses (Bun Bun and any future NPC with uniqueDialogue.responses) */ if (npc.uniqueDialogue && npc.uniqueDialogue.responses && setup.pickDialogueLine) { var topicTable = npc.uniqueDialogue.responses[topic]; if (!topicTable && npc.uniqueDialogue.romance) { topicTable = npc.uniqueDialogue.romance[topic]; } if (topicTable) { var picked = setup.pickDialogueLine(npc, topicTable, relLevel); if (picked) { var uFlavor = setup.getSpeechFlavor(npc); return uFlavor.prefix + setup.getMoodTonedResponse(picked, npc) + uFlavor.suffix; } } } if (topic === "job") { var job = npc.jobs.length > 0 ? npc.jobs[0] : "Unemployed"; if (job === "Unemployed") { if (npc.mentalTraits.includes("Lazy")) { responses.push("Job? Nah, I'm good. Work is overrated anyway. Why slave away when you can just... not? Life's too short for all that stress."); } else if (npc.mentalTraits.includes("Ambitious")) { responses.push("Between jobs right now. I'm looking for the right opportunity, something that matches my potential. I'm not going to settle for just anything - I have goals, you know?"); } else if (npc.mentalTraits.includes("Anxious") || npc.mentalTraits.includes("Insecure")) { responses.push("I... I've been trying to find work. It's tough out there. The rejections are... *sighs* they really get to you after a while. I'm trying to stay positive but..."); } else if (npc.mentalTraits.includes("Depressed") || npc.mentalTraits.includes("Pessimistic")) { responses.push("Not working at the moment. The job market is terrible, and honestly, does any of it even matter? We work to live, live to work... it's all a cycle."); } else if (npc.mentalTraits.includes("Nonchalant") || npc.mentalTraits.includes("Chill")) { responses.push("Not working right now. Taking some time to figure things out, you know? No rush."); } else { responses.push("I'm... currently between opportunities. Looking for work, you know? Something will turn up eventually."); } } else { var jobResponse = ""; /* Opening based on personality */ if (npc.mentalTraits.includes("Hardworking") || npc.mentalTraits.includes("Workaholic")) { jobResponse = "I work as a " + job + ". Long hours, demanding work, but I take pride in what I do. Hard work pays off, you know? I'm usually the first one in and the last one out. That's just how I operate."; } else if (npc.mentalTraits.includes("Lazy") || npc.mentalTraits.includes("Unmotivated")) { jobResponse = "Technically I'm a " + job + ". It's a paycheck, that's all I really care about. I do the bare minimum to get by. Why stress myself out for a job that doesn't care about me anyway?"; } else if (npc.mentalTraits.includes("Ambitious") || npc.mentalTraits.includes("Determined")) { jobResponse = "I'm a " + job + " right now, but it's just a stepping stone. I've got bigger plans. Way bigger. I'm not staying in this position forever - I'm going places."; } else if (npc.mentalTraits.includes("Passionate") || npc.mentalTraits.includes("Enthusiastic")) { jobResponse = "I'm a " + job + " and I absolutely love it! Every day is exciting. I wake up looking forward to getting to work. Not everyone can say that about their job, right?"; } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Cynical")) { jobResponse = "Ugh, I'm stuck being a " + job + ". It's not great, but what choice do I have? Bills don't pay themselves. The people are annoying, the pay could be better, but whatever. It is what it is."; } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Anxious")) { jobResponse = "I, um, work as a " + job + ". It's... it's okay. Sometimes stressful, but I manage. The people are mostly nice... I think..."; } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Arrogant")) { jobResponse = "I'm a " + job + ", and I'm damn good at it. Probably one of the best, actually. I know my worth and I make sure everyone else knows it too."; } else if (npc.mentalTraits.includes("Nonchalant") || npc.mentalTraits.includes("Chill")) { jobResponse = "I work as a " + job + ". It's alright, you know? Keeps me busy, pays the bills. Can't really complain."; } else { jobResponse = "I work as a " + job + ". It's decent work, pays the bills. Can't complain too much."; } /* Add job-specific flavor based on actual job */ if (job === "Brothel Worker" || job === "Prostitute") { if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Seductive")) { jobResponse += " I'm good at what I do, and the money's great. Plus, I meet interesting people."; } else if (npc.mentalTraits.includes("Shy")) { jobResponse += " It... it's not what I thought I'd be doing, but the money helps..."; } else if (npc.mentalTraits.includes("Practical") || npc.mentalTraits.includes("Pragmatic")) { jobResponse += " It pays well, that's what matters. People can judge all they want."; } } else if (job === "Stripper") { if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Flirty")) { jobResponse += " The stage is my home. I love performing, feeling all eyes on me."; } else if (npc.mentalTraits.includes("Ambitious")) { jobResponse += " It's temporary. I'm building up my savings for bigger things."; } } else if (job === "Construction Worker" || job === "Dock Worker") { if (npc.mentalTraits.includes("Jock") || npc.mentalTraits.includes("Strong")) { jobResponse += " It's hard physical work, but that's what I'm built for. Keeps me in shape too."; } else if (npc.mentalTraits.includes("Hardworking")) { jobResponse += " Honest work for honest pay. That's all I need."; } } else if (job.includes("Clerk") || job.includes("Salon")) { if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Outgoing")) { jobResponse += " I love interacting with customers. Meeting new people every day is the best part."; } else if (npc.mentalTraits.includes("Tired") || npc.mentalTraits.includes("Frustrated")) { jobResponse += " Dealing with customers all day can be exhausting though. People can be so demanding."; } } else if (job === "City Mayor" || job === "Mayor's Secretary") { if (npc.mentalTraits.includes("Ambitious") || npc.mentalTraits.includes("Arrogant")) { jobResponse += " I have real power here. I shape this city's future."; } else if (npc.mentalTraits.includes("Stressed") || npc.mentalTraits.includes("Overworked")) { jobResponse += " The responsibility is immense. Everyone wants something from you in this position."; } } /* Add comment about player's job if they share it */ if (v.jobs.length > 0 && v.jobs[0] === job) { if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Warm")) { jobResponse += " Hey, you work there too, right? That's awesome! How are you finding it? We should swap stories sometime."; } else if (npc.mentalTraits.includes("Competitive")) { jobResponse += " Oh, you work there too? Interesting. May the best worker win."; } else if (npc.mentalTraits.includes("Nonchalant")) { jobResponse += " Oh yeah, you're there too. Cool."; } else { jobResponse += " Hey, you work there too, right? How are you finding it?"; } } /* Schedule awareness - is NPC at work or off-duty? */ var schedKey = npc.scheduleSource || npc.originalName || npc.permanentId || npc.name; var npcSchedule = setup.npcLocationSchedules[schedKey]; var jobLoc = setup.jobLocations[job] || null; if (npcSchedule && jobLoc) { var curHour = Math.floor(v.timeInMinutes / 60) % 24; var scheduledLoc = setup.getNPCLocation(npc, v.dayOfWeek || "Monday", curHour); if (scheduledLoc === jobLoc) { /* NPC is at their work location */ if (npc.mentalTraits.includes("Hardworking") || npc.mentalTraits.includes("Workaholic")) { jobResponse += " I'm on the clock right now, actually. No rest for the dedicated."; } else if (npc.mentalTraits.includes("Lazy")) { jobResponse += " Yeah, I'm technically working right now. Can't you tell by my enthusiasm?"; } else if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Warm")) { jobResponse += " I'm working right now, but I always have time for a chat. Makes the shift go faster."; } else { jobResponse += " I'm on shift right now, so I should probably get back to it soon."; } } else { /* NPC is off-duty / at a different location */ if (npc.mentalTraits.includes("Chill") || npc.mentalTraits.includes("Nonchalant")) { jobResponse += " But I'm off right now, so let's not talk about work. I'm enjoying my free time."; } else if (npc.mentalTraits.includes("Ambitious")) { jobResponse += " I'm off the clock right now, but honestly I'm always thinking about the next move."; } else if (npc.mentalTraits.includes("Enthusiastic") || npc.mentalTraits.includes("Energetic")) { jobResponse += " Day off today though! Figured I'd get out and enjoy the city while I can."; } else { jobResponse += " Not working today though, so that's nice. Everyone needs a break."; } } } responses.push(jobResponse); } } else if (topic === "opinion") { /* Negative-only trait NPCs give harsh or dismissive opinions */ if (!setup.hasPositiveMentalTraits(npc)) { responses.push("My opinion? I don't care enough to have one."); responses.push("Why should I tell you what I think?"); responses.push("You really want my opinion? You won't like it."); } var opinions = []; /* React to player appearance changes (transformation, hair, job) */ var playerChanges = setup.detectPlayerChanges(npc.name); if (playerChanges) { if (playerChanges.transformation) { if (npc.mentalTraits.includes("Observant") || npc.mentalTraits.includes("Analytical")) { opinions.push(`Something is different about you. Physically different. I noticed the moment I saw you`); } else if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Warm")) { opinions.push(`You look... different. Are you okay? Whatever happened, I hope you're doing alright`); } else if (npc.mentalTraits.includes("Blunt") || npc.mentalTraits.includes("Direct")) { opinions.push(`Whoa, you look totally different. What happened to you?`); } else { opinions.push(`Have you... changed? You look different from the last time I saw you`); } } if (playerChanges.hair) { if (npc.mentalTraits.includes("Fashionable") || npc.mentalTraits.includes("Prep")) { opinions.push(`New hair! I love it. A fresh look can change everything, and this suits you`); } else { opinions.push(`Did you change your hair? It looks good on you`); } } if (playerChanges.job) { if (npc.mentalTraits.includes("Ambitious")) { opinions.push(`I heard you switched jobs. Smart move if the new gig pays better`); } else { opinions.push(`New job, huh? How's that going for you?`); } } } /* React to player's physical appearance with personality filters */ if (v.physicalTraits.includes("Attractive")) { if (relLevel >= 2) { if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { opinions.push(`You? You're gorgeous, honestly. Like seriously stunning. I could look at you all day`); } else if (npc.mentalTraits.includes("Shy")) { opinions.push(`You're... you're really attractive. I hope that's okay to say...`); } else if (npc.mentalTraits.includes("Direct") || npc.mentalTraits.includes("Blunt")) { opinions.push(`You're good-looking. That's just a fact`); } else { opinions.push(`You? You're gorgeous, honestly`); } } else { if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Awkward")) { opinions.push(`You... you look nice`); } else { opinions.push(`You look... nice`); } } } else if (v.physicalTraits.includes("Ugly")) { if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Warm")) { opinions.push(`You have a nice personality. That's what really matters in the end, you know?`); } else if (npc.mentalTraits.includes("Blunt") || npc.mentalTraits.includes("Insensitive")) { if (relLevel === 0) { opinions.push(`You want my honest opinion? ...Maybe work on your appearance a bit. I'm just being real with you`); } } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude")) { if (relLevel === 0) { opinions.push(`Honestly? You could use some work. But hey, at least you asked`); } } } /* React to shared traits with personality */ if (v.physicalTraits.includes("Muscular") && npc.physicalTraits.includes("Muscular")) { if (npc.mentalTraits.includes("Competitive")) { opinions.push(`I respect the muscle, even if I'm clearly more built. You put in work though`); } else if (npc.mentalTraits.includes("Jock")) { opinions.push(`Bro! The gains are real! Respect! You clearly put in the work at the gym`); } else { opinions.push(`I respect the muscle. You clearly put in the work`); } } /* React to fashionable */ if (v.physicalTraits.includes("Fashionable")) { if (npc.physicalTraits.includes("Fashionable") || npc.mentalTraits.includes("Prep")) { opinions.push(`Your fashion sense? Immaculate. You clearly care about your appearance and it shows`); } else if (npc.mentalTraits.includes("Goth")) { opinions.push(`I see you've got your own style. I can respect that`); } } /* React to body types */ if (v.physicalTraits.includes("Curvy") || v.physicalTraits.includes("Voluptuous") || (v.mentalTraits.includes("Succubus") || v.mentalTraits.includes("Voluptuous Succubus")) || v.mentalTraits.includes("Hucow")) { if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { opinions.push(`Your curves? Absolutely stunning. You must turn heads everywhere you go. I know I'm looking`); } else if (npc.mentalTraits.includes("Jealous") && npc.physicalTraits.includes("Flat")) { opinions.push(`You've got... quite the figure. Lucky you`); } else { opinions.push(`You've got a great figure`); } } /* React to personality matches */ if (v.mentalTraits.includes("Kind") && npc.mentalTraits.includes("Kind")) { opinions.push(`You're one of the genuinely good people in this city. I really appreciate that about you. We need more people like you around here`); } if (v.mentalTraits.includes("Ambitious") && npc.mentalTraits.includes("Ambitious")) { opinions.push(`I like your drive and determination. You're going places, I can tell. People like us, we don't stop until we get what we want`); } if (v.mentalTraits.includes("Nerd") && npc.mentalTraits.includes("Nerd")) { opinions.push(`You actually understand what I'm talking about when I get technical. That's... rare. It's refreshing`); } if (v.mentalTraits.includes("Goth") && npc.mentalTraits.includes("Goth")) { opinions.push(`You get the aesthetic. Most people don't understand it, but you do`); } if (v.mentalTraits.includes("Jock") && npc.mentalTraits.includes("Jock")) { opinions.push(`You're athletic and competitive. I respect that. We should work out together sometime`); } if (v.mentalTraits.includes("Bitchy") && !npc.mentalTraits.includes("Patient") && !npc.mentalTraits.includes("Kind")) { opinions.push(`You can be pretty abrasive sometimes, not gonna lie. But at least you're real about it`); } /* React to job matches/differences */ if (v.jobs.length > 0 && npc.jobs.length > 0) { if (v.jobs[0] === npc.jobs[0]) { if (npc.mentalTraits.includes("Friendly")) { opinions.push(`Fellow ${v.jobs[0]}! It's nice having someone who actually gets what the job is like. We should share war stories`); } else if (npc.mentalTraits.includes("Competitive")) { opinions.push(`So we're both ${v.jobs[0]}s. May the best one succeed`); } else { opinions.push(`Fellow ${v.jobs[0]}! It's nice having someone who gets the job`); } } } /* Relationship-based closing */ if (opinions.length > 0) { var response = opinions[Math.floor(Math.random() * opinions.length)] + ". "; if (relLevel >= 3) { if (npc.mentalTraits.includes("Warm") || npc.mentalTraits.includes("Loyal")) { response += `Overall? I think you're pretty amazing. One of the best people I know, honestly.`; } else if (npc.mentalTraits.includes("Chill") || npc.mentalTraits.includes("Nonchalant")) { response += `You're cool. That's about it.`; } else { response += `Overall? I think you're pretty amazing.`; } } else if (relLevel >= 2) { if (npc.mentalTraits.includes("Friendly")) { response += `You're good people. I'm glad we're friends.`; } else { response += `You're good people.`; } } else { response += `That's my honest take.`; } responses.push(response); } else { if (relLevel >= 3) { if (npc.mentalTraits.includes("Warm")) { responses.push(`What do I think? I think you're wonderful. One of my favorite people, honestly. I'm really glad we met.`); } else { responses.push(`What do I think? I think you're wonderful. One of my favorite people, honestly.`); } } else if (relLevel >= 2) { responses.push(`You're cool. I like hanging out with you. We should do it more often.`); } else { responses.push(`We haven't talked enough for me to have a strong opinion yet. You seem okay though.`); } } } else if (topic === "smalltalk") { /* Negative-only trait NPCs give cold, dismissive responses */ if (!setup.hasPositiveMentalTraits(npc)) { responses.push("...What do you want?"); responses.push("I don't do small talk."); responses.push("Why are you still talking?"); } else if (npc.mentalTraits.includes("Talkative") || npc.mentalTraits.includes("Outgoing") || npc.mentalTraits.includes("Energetic")) { responses.push("Oh man, you know what I was thinking about? This tropical heat has been WILD lately! I was sweating just walking here, but honestly, I love it. Sunfish City vibes, right? Never a dull moment around here!"); responses.push("So get this - I was down by the boardwalk yesterday and saw the most ridiculous thing! This seagull just snatched a hot dog right out of some guy's hand! Classic Sunfish City. Anyway, what's new with you?"); responses.push("I've been running around all day, honestly. There's always something happening in this city. Did you see the new place that opened up downtown? We should check it out sometime!"); if (v.timeOfDay === "Morning") { responses.push("Morning energy is the BEST energy! I already went for a run along the boardwalk before sunrise. This city is gorgeous when nobody else is awake yet!"); } else if (v.timeOfDay === "Evening" || v.timeOfDay === "Late Night") { responses.push("The city at night is something else, right? All the lights, the music coming from everywhere. I could stay out all night! Actually, I probably will."); } else { responses.push("The afternoon heat is hitting hard today but I'm not slowing down! Just grabbed an iced coffee and I'm ready to keep going. What are you up to?"); } } else if (npc.mentalTraits.includes("Introverted") || npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Quiet")) { responses.push("Um... yeah, things are... fine. It's been warm out. So... yeah."); responses.push("Oh, hi. Not much going on, really. Just... the usual stuff. You know."); responses.push("I've been... staying in mostly. Reading. It's nice. Quiet."); if (v.currentWeather === "Rainy" || v.currentWeather === "Stormy") { responses.push("The rain is... actually nice. Gives me an excuse to stay inside with a book. Not that I needed one..."); } else { responses.push("It's so bright out today. I kind of wish it would cloud over a little. The sun is... a lot sometimes."); } } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude") || npc.mentalTraits.includes("Impatient")) { responses.push("Small talk? Really? Fine. Yes, the sun exists. The city is still standing. Congratulations on stating the obvious. There, happy?"); responses.push("Can we not do this? I have better things to do than chat about nothing."); responses.push("Ugh, you're still here? Fine. What do you want?"); if (v.timeOfDay === "Morning") { responses.push("It's too early for this. I haven't even had my coffee yet and you're already bothering me."); } else { responses.push("This heat is making everyone annoying. Including you. Especially you."); } } else if (npc.mentalTraits.includes("Nerd") || npc.mentalTraits.includes("Intelligent") || npc.mentalTraits.includes("Analytical")) { responses.push("Did you hear about the new development project in the business district? Fascinating urban planning implications. The way they're redesigning the traffic flow could reduce congestion by up to 30%."); responses.push("I've been reading about marine biology lately. Did you know Sunfish City's reef system is one of the most biodiverse in the region? The ecosystem here is incredible."); responses.push("Actually, I was just thinking about something interesting. The humidity patterns here follow a really predictable cycle if you track them. I keep a spreadsheet."); if (v.currentWeather === "Stormy") { responses.push("Fascinating weather pattern today. Tropical convection cells are remarkably powerful this close to the coast. I've been tracking the barometric pressure all morning."); } else if (v.timeOfDay === "Late Night") { responses.push("Did you know light pollution from Sunfish City is visible from space? I was reading a satellite study about it. The night sky would be incredible if we could see it properly."); } else { responses.push("I was just reading about the tidal patterns around Sunfish City. Apparently the reef system creates unique wave interference patterns. It's quite elegant from a physics standpoint."); } } else if (npc.mentalTraits.includes("Nonchalant") || npc.mentalTraits.includes("Chill") || npc.mentalTraits.includes("Relaxed")) { responses.push("Yeah, things have been pretty normal. Same routine, you know? Can't complain. Life's just... happening."); responses.push("Eh, not much going on. Been taking it easy. Sometimes that's all you need, right?"); responses.push("Just vibing, honestly. The breeze has been nice. No complaints."); if (v.currentWeather === "Rainy") { responses.push("Rain's kinda nice, actually. Everything slows down. Good vibes."); } else if (v.timeOfDay === "Evening") { responses.push("Evenings in Sunfish City hit different. The sunset, the warm breeze... yeah, this is the life."); } else { responses.push("I found this perfect shady spot the other day. Just sat there for like two hours doing nothing. Best afternoon ever."); } } else if (npc.mentalTraits.includes("Goth") || npc.mentalTraits.includes("Cynical")) { responses.push("Small talk. The ultimate display of social conformity. We talk about meaningless things because confronting the void is too scary. But sure, the weather's fine, I guess."); responses.push("Another day in paradise, right? That's what they say. Personally, I think the relentless sunshine is nature's way of mocking us."); responses.push("I read somewhere that most human conversation is just noise filling silence. Makes you think, doesn't it?"); if (v.currentWeather === "Stormy") { responses.push("At least the storm matches my mood for once. There's something honest about bad weather. It doesn't pretend to be something it's not."); } else if (v.timeOfDay === "Late Night") { responses.push("Late night is the only tolerable time in this city. Everyone else is asleep and the world finally gets quiet. Almost peaceful."); } else { responses.push("Another day of relentless tropical sunshine. How exhausting. I miss clouds."); } } else if (npc.mentalTraits.includes("Jock") || npc.mentalTraits.includes("Athletic") || npc.mentalTraits.includes("Competitive")) { responses.push("Bro, did you catch the game last night? That final play was INSANE! Also hit a new PR at the gym yesterday. Things are going pretty good!"); responses.push("Been getting my reps in every morning. The heat makes the workouts brutal but the gains are worth it. You lift?"); responses.push("I swam down at the beach this morning. Current was strong today. Best workout I've had all week."); if (v.timeOfDay === "Morning") { responses.push("Nothing beats a morning workout. Got my run in before the heat gets crazy. Already feeling pumped for the rest of the day!"); } else if (v.currentWeather === "Rainy") { responses.push("Rain workout! Best kind. Nobody else is out there so I had the whole track to myself. Plus you cool down way faster."); } else { responses.push("The heat today is brutal but that just makes the workout harder. No pain no gain, right? I was dripping before I even started."); } } else if (npc.mentalTraits.includes("Prep") || npc.mentalTraits.includes("Fashionable")) { responses.push("Oh, things have been fabulous! Did you see the new collection that just dropped downtown? I'm thinking about picking up a few pieces. Fashion waits for no one!"); responses.push("I just got the cutest outfit for this weekend. The summer styles here are everything. Have you been keeping up with the trends?"); responses.push("They're opening a new boutique near the marina. I already know I'm going to spend way too much money there."); if (v.currentWeather === "Rainy") { responses.push("This humidity is wreaking havoc on my hair, honestly. But at least rain gives me an excuse to wear my cute new rain boots."); } else { responses.push("The summer collections this year are to die for. I saw the most gorgeous sundress in a window display earlier. Already planning my outfit for the weekend."); } } else if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Warm") || npc.mentalTraits.includes("Empathetic")) { responses.push("It's so nice running into you! How have you been? I hope you're taking care of yourself in this heat. You know, if you ever need anything, I'm here."); responses.push("Hey! I was just thinking about you, actually. Everything going okay? You seem like you've been busy."); responses.push("Isn't it a beautiful day? I always feel grateful for days like this. Tell me what's been going on with you!"); if (v.currentWeather === "Stormy") { responses.push("Rough weather out there. Are you staying safe? Make sure you have an umbrella. I worry about people walking around in storms like this."); } else if (v.timeOfDay === "Late Night") { responses.push("It's getting late. You're taking care of yourself, right? Don't stay out too late. But I'm glad I ran into you!"); } else { responses.push("I love days like this. The warmth, the sound of the ocean in the distance. Sunfish City really is something special, isn't it?"); } } else if (npc.mentalTraits.includes("Ambitious") || npc.mentalTraits.includes("Hardworking") || npc.mentalTraits.includes("Determined")) { responses.push("Things have been busy. I've got a lot on my plate right now, but that's how I like it. Can't slow down, you know?"); responses.push("I barely have time for small talk, honestly. I've been grinding non-stop. But it'll all pay off eventually."); responses.push("Every day is progress. I set three goals this morning and I've already hit two of them. What have you been working on?"); if (v.timeOfDay === "Morning") { responses.push("I've been up since dawn planning my day. Morning hours are the most productive. You should try waking up earlier, it changes everything."); } else { responses.push("Already got three meetings done today. Networking is everything in this city. You never know who might open the next door for you."); } } else if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive") || npc.mentalTraits.includes("Alluring")) { responses.push("Oh, you want to chat? I can think of more... interesting things we could do. But sure, let's talk."); responses.push("Just another gorgeous day, almost as gorgeous as the company I'm keeping right now."); responses.push("Mmm, it's hot out today. Then again, it's always hot when you're around."); if (v.timeOfDay === "Evening" || v.timeOfDay === "Late Night") { responses.push("Something about the night air makes everything more... intimate, don't you think? The warm breeze, the low lighting... I could get used to this."); } else { responses.push("This tropical heat just makes everyone look so good. All that sun-kissed skin on display. Present company included."); } } else if (npc.mentalTraits.includes("Sarcastic") || npc.mentalTraits.includes("Witty") || npc.mentalTraits.includes("Humorous")) { responses.push("Oh wow, small talk. My favorite activity. Right up there with watching paint dry. But go on, I'm all ears."); responses.push("You know what's funny? I was just standing here wondering when someone would come by and ask me about my day. And here you are. Must be fate."); responses.push("The city's as chaotic as ever. Saw a guy arguing with a palm tree yesterday. Peak Sunfish City behavior."); if (v.currentWeather === "Rainy") { responses.push("Ah, rain. Nature's way of telling everyone to stay home. Too bad nobody in Sunfish City ever listens. Myself included, apparently."); } else if (v.timeOfDay === "Morning") { responses.push("Is it too early for sarcasm? Trick question. It's never too early. Anyway, how's your morning? Mine's already absurd."); } else { responses.push("You know what's funny about this city? Every day is exactly the same temperature and somehow people still complain about the weather. Never change, Sunfish City."); } } else if (npc.mentalTraits.includes("Artistic") || npc.mentalTraits.includes("Creative")) { responses.push("I've been finding inspiration everywhere lately. The sunsets here are just breathtaking. The way the light hits the water..."); responses.push("I started a new project yesterday. Not sure where it's going yet, but that's the exciting part, right?"); if (v.currentWeather === "Stormy") { responses.push("Storms are incredible for creativity. All that raw energy in the sky, the contrast of the dark clouds against the city. I need to paint this."); } else if (v.timeOfDay === "Evening") { responses.push("The evening light in this city is magical. Everything turns golden for about twenty minutes before sunset. I try to capture it every time."); } else { responses.push("I've been sketching people at the park lately. There's so much character in the faces around here. Everyone has a story."); } } else if (npc.mentalTraits.includes("Paranoid") || npc.mentalTraits.includes("Anxious")) { responses.push("Have you noticed anything... weird lately? No? Just me? Okay. Never mind. Forget I said anything."); responses.push("I keep looking over my shoulder today. I know it sounds crazy but something just feels off, you know?"); if (v.timeOfDay === "Late Night") { responses.push("Why are we out this late? It's not safe. I keep hearing footsteps behind me. Please tell me you hear them too."); } else if (v.currentWeather === "Stormy") { responses.push("This storm is making me nervous. What if the power goes out? What if there's flooding? I should have stayed home. I should definitely have stayed home."); } else { responses.push("Does anything feel... off to you today? No? It's probably nothing. Forget I asked. Actually, don't forget. Stay alert."); } } else if (npc.mentalTraits.includes("Cold") || npc.mentalTraits.includes("Cruel") || npc.mentalTraits.includes("Aggressive")) { responses.push("Why are you bothering me with this? I was perfectly fine before you showed up."); responses.push("Do I look like I want to chat? Read the room."); if (v.currentWeather === "Rainy" || v.currentWeather === "Stormy") { responses.push("Great, now it's raining. As if talking to you wasn't bad enough."); } else { responses.push("I was enjoying the silence before you showed up."); } } else { responses.push("Yeah, things have been pretty normal. Same old routine, you know? How about you? Anything interesting going on?"); responses.push("Not a whole lot happening on my end. The usual Sunfish City stuff. It's a nice day though, right?"); responses.push("Oh you know, just the same old same old. Been keeping busy. What's new with you?"); if (v.currentWeather === "Rainy") { responses.push("This rain is something, huh? At least it cools things down a little. What brings you out in this weather?"); } else if (v.timeOfDay === "Evening") { responses.push("Nice evening out, isn't it? The city always feels different once the sun starts going down. More relaxed somehow."); } else { responses.push("Just another day in paradise, right? That's what they say about Sunfish City. Can't argue with that."); } } } else if (topic === "insult") { if (npc.mentalTraits.includes("Aggressive") || npc.mentalTraits.includes("Short Tempered") || npc.mentalTraits.includes("Violent")) { responses.push("Excuse me? You want to say that again? Get the hell out of my face RIGHT NOW before I make you regret it."); responses.push("Oh you've got a death wish, huh? Keep talking and find out what happens."); responses.push("*cracks knuckles* Wrong person to mess with today. Walk away. Now."); } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude")) { responses.push("Oh, that's rich coming from YOU. You've got some nerve. Get out of my sight before I really let you have it."); responses.push("Wow, rude much? Takes one to know one, sweetie. Except I'm better at it."); responses.push("Ha! Bold of you. Let me know when you come up with something that actually stings."); } else if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Patient") || npc.mentalTraits.includes("Sensitive")) { responses.push("That... that really hurt. I don't know what I did to deserve that, but... I think you should just go. Please."); responses.push("Why would you say something like that? I've never been anything but nice to you..."); responses.push("*looks away* ...Okay. I see how it is. I hope you feel better about yourself now."); } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Arrogant")) { responses.push("Wow, really? That's the best you've got? I've heard worse from better people. Try harder."); responses.push("Cute. You think that bothers me? I know exactly who I am. Do you?"); responses.push("*laughs* Oh honey. I'm way too secure for that to land. Nice try though."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Insecure")) { responses.push("What? Why would you... That's really mean... I... please just go..."); responses.push("*looks down* ...I knew it. I knew people thought that about me..."); responses.push("*voice shaking* Please don't... I can't deal with this right now..."); } else if (npc.mentalTraits.includes("Cold") || npc.mentalTraits.includes("Stoic")) { responses.push("...Is that all? Are you done? Okay. Leave."); responses.push("Noted. Now get out of my face."); } else if (npc.mentalTraits.includes("Sarcastic") || npc.mentalTraits.includes("Witty")) { responses.push("Oh wow, what a devastating insult. I'm so hurt. Really. Can't you tell how wounded I am?"); responses.push("That was so bad it actually circled back around and became amusing. Thanks for the laugh."); responses.push("Ooh, burn. Wait, no. What's the opposite of a burn? That. That's what that was."); } else if (npc.mentalTraits.includes("Nonchalant") || npc.mentalTraits.includes("Chill")) { responses.push("...Okay? Cool. Anyway."); responses.push("Huh. That's one way to spend your time. Whatever, I guess."); } else if (npc.mentalTraits.includes("Dominant") || npc.mentalTraits.includes("Assertive")) { responses.push("You think you can talk to ME like that? Know your place. We're done here."); responses.push("Interesting choice. Let me be clear: don't ever speak to me that way again."); } else { responses.push("What the hell? Why would you say that? Just... just leave me alone. Seriously."); responses.push("Wow. Okay then. I thought we were cool, but I guess not."); responses.push("That was uncalled for. I don't know what your problem is, but don't take it out on me."); } } else if (topic === "compliment") { /* Negative-only trait NPCs deflect or dismiss compliments */ if (!setup.hasPositiveMentalTraits(npc)) { responses.push("...Okay."); responses.push("Don't try to butter me up."); responses.push("Save it."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Insecure")) { responses.push("Oh... um... thank you. That's... that's really nice of you to say..."); responses.push("Really? You think so? That... that means a lot..."); responses.push("I... wow. Nobody ever says stuff like that to me. Thank you."); responses.push("*fidgets* You... you really mean that? I don't know what to say... that made my whole day."); } else if (npc.mentalTraits.includes("Arrogant") || npc.mentalTraits.includes("Vain")) { responses.push("Well, obviously. But it's nice to hear you recognize it."); responses.push("I know. But thanks for noticing."); responses.push("Tell me something I don't already know. But... appreciate it."); responses.push("*inspects nails* I know, right? It's exhausting being this perfect. But someone has to do it."); } else if (npc.mentalTraits.includes("Confident")) { responses.push("Hey, thanks! I appreciate that!"); responses.push("That's kind of you to say. Thank you!"); responses.push("Right back at you! But seriously, that means a lot."); responses.push("*grins* You have great taste in people, clearly. But really, thanks for that."); } else if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Warm") || npc.mentalTraits.includes("Kind")) { responses.push("Aww, that's so sweet of you! Thank you so much!"); responses.push("You're so kind! That really made my day!"); responses.push("That's the nicest thing anyone's said to me all week! You're wonderful."); responses.push("*beaming* Stop it, you're going to make me cry! In a good way. Seriously, you just made my entire week."); } else if (npc.mentalTraits.includes("Sarcastic") || npc.mentalTraits.includes("Witty")) { responses.push("Flattery will get you... actually, flattery will get you pretty far with me. Thanks."); responses.push("Oh stop it. No wait, keep going. I'm enjoying this."); responses.push("Did you rehearse that, or does charm just come naturally to you?"); responses.push("I should charge admission for compliments this good. Lucky for you, today it's free. Thanks."); } else if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { responses.push("Mmm, I love it when people notice. You've got good taste."); responses.push("Keep talking like that and I might start blushing. Or... something else."); responses.push("Well aren't you charming? I like that in a person."); responses.push("*traces a finger along your arm* If you keep saying things like that, I might start getting ideas..."); } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude")) { responses.push("Uh huh. What do you want?"); responses.push("Is that supposed to impress me? Whatever. Thanks, I guess."); responses.push("Okay. Cool. Are we done?"); responses.push("*rolls eyes* Cute. Are you always this try-hard, or is today special?"); } else if (npc.mentalTraits.includes("Cynical") || npc.mentalTraits.includes("Pessimistic")) { responses.push("You don't have to say nice things just to say them. But... thanks."); responses.push("I'm sure you say that to everyone. But I appreciate the effort."); responses.push("Compliments feel weird. But I'll take it, I guess."); responses.push("*suspicious look* What do you want? People don't just say nice things for no reason. But... thanks, I guess."); } else if (npc.mentalTraits.includes("Nerd") || npc.mentalTraits.includes("Bookworm") || npc.mentalTraits.includes("Intelligent")) { responses.push("Oh! That's... statistically unlikely for someone to say unprompted. But genuinely appreciated!"); responses.push("Thanks! Most people don't notice, honestly. It's refreshing."); responses.push("*adjusts glasses, smiling* That's very kind. Most people think I'm just weird, so hearing something positive is... nice."); } else if (npc.mentalTraits.includes("Goth")) { responses.push("...Huh. That's... actually kind of nice. Don't tell anyone I said that."); responses.push("Careful with the positivity. I have a reputation to maintain. But... thanks."); responses.push("*almost smiles* I'm not supposed to care about that sort of thing. But... that was weirdly sweet. Don't tell anyone."); } else if (npc.mentalTraits.includes("Humble") || npc.mentalTraits.includes("Considerate")) { responses.push("Oh, that's really kind. I don't think I deserve that, but thank you."); responses.push("You're being way too generous, but I appreciate it. Truly."); responses.push("That means a lot coming from you. I try my best, but I don't always feel like it's enough. So thank you."); } else if (npc.mentalTraits.includes("Cold") || npc.mentalTraits.includes("Stoic")) { responses.push("Noted."); responses.push("Thanks. I think."); responses.push("*brief nod* ...Acknowledged."); } else { responses.push("Oh, thank you. That's nice of you to say."); responses.push("I appreciate that. Thanks."); responses.push("Hey, that means a lot. Really."); responses.push("That's sweet. I don't hear things like that often enough. Thank you."); } } else if (topic === "trading" && prefs) { var mentions = []; if (prefs.desires && relLevel >= 1) { if (prefs.desires.skills && prefs.desires.skills.length > 0) { mentions.push("I've been wanting to learn " + prefs.desires.skills[0]); } if (prefs.desires.mental && prefs.desires.mental.length > 0) { mentions.push("I wish I could be more " + prefs.desires.mental[0].toLowerCase()); } } if (mentions.length > 0) { var mainMention = mentions[Math.floor(Math.random() * mentions.length)]; if (npc.mentalTraits.includes("Honest") || npc.mentalTraits.includes("Direct")) { responses.push("Well, to be honest, " + mainMention + ". But I'm open to hearing offers!"); } else if (npc.mentalTraits.includes("Shrewd")) { responses.push("Hmm, let's just say " + mainMention + ". But everything has a price, doesn't it?"); } else { responses.push("Trading? Sure. " + mainMention.charAt(0).toUpperCase() + mainMention.slice(1) + "."); } } else { responses.push("I'm open to trading, depends on what you're offering."); } } /* ====================================================================== */ /* NEW DYNAMIC CONVERSATION TOPIC RESPONSES */ /* ====================================================================== */ else if (topic === "flirt") { /* Flirt responses are handled by calculateFlirtOutcome */ var flirtResult = setup.calculateFlirtOutcome(npc, relLevel); /* EXPLICIT/VERY EROTIC RESPONSES (sexualIntensity 2) - requires mutual sexual traits + Close Friend+ */ if (flirtResult.responseType === "explicit_eager") { responses.push("*pulls you close, eyes hungry* Mmm... I've been waiting for you to make a move. Let's skip the small talk and find somewhere private..."); responses.push("*bites lip seductively* You have no idea how badly I want you right now. My body is aching for your touch..."); responses.push("*presses against you* God, the things I want to do to you... I can't stop thinking about how good you'd feel..."); } else if (flirtResult.responseType === "explicit_seductive") { responses.push("*runs finger down your chest* I've been fantasizing about this... about us... about what I'd do if I got you alone..."); responses.push("*whispers in your ear* I want to taste every inch of you. I want to hear you moan my name..."); responses.push("*locks eyes with intense desire* Why don't we continue this somewhere more... comfortable? I promise to make it worth your while..."); } /* EROTIC RESPONSES (sexualIntensity 1) - requires mutual sexual traits + Acquaintance+ */ else if (flirtResult.responseType === "sexual_eager") { responses.push("*eyes roam over you hungrily* Mmm, I like what I see. Very much. I wonder what you look like without those clothes..."); responses.push("*licks lips* You're making it very hard to behave. My mind is going to some very dirty places right now..."); responses.push("*moves closer* I've been thinking about you... thinking about what we could do together..."); } else if (flirtResult.responseType === "sexual_seductive") { responses.push("*traces your jawline* I love how you look at me. It makes me want to give you a private show..."); responses.push("*voice drops to a sultry whisper* Keep talking like that and I might just have to show you what else I can do with my mouth..."); responses.push("*presses close* I want to feel your hands on me. Everywhere."); } else if (flirtResult.responseType === "sexual_flirty") { responses.push("*winks* Careful, keep flirting like that and I might have to drag you somewhere private..."); responses.push("*playfully bites lower lip* You're turning me on, you know that? In all the right ways..."); responses.push("*giggles seductively* Someone's being naughty. I like it. A lot."); } else if (flirtResult.responseType === "sexual_romantic") { responses.push("*blushes but moves closer* You make me feel things... intense things. I want to be closer to you..."); responses.push("*takes your hand, places it on their hip* My heart races when you look at me like that. Among other things..."); responses.push("*soft moan* The way you talk to me... it does things to me. Makes me want more..."); } else if (flirtResult.responseType === "sexual_shy") { responses.push("*face bright red, squirming* I... oh god... I've been thinking about you too... about us... *voice drops to whisper* ...together..."); responses.push("*stammers* You... you make me feel... *quietly* ...really aroused... sorry, that's embarrassing..."); responses.push("*can't meet your eyes* W-when you say things like that I... I want... *trails off, trembling*"); } else if (flirtResult.responseType === "sexual_confident") { responses.push("*smirks knowingly* I like your confidence. I bet you know how to use that body of yours..."); responses.push("*looks you up and down approvingly* Not bad. Not bad at all. I'd definitely be interested in exploring this further..."); responses.push("*leans in* You've got my attention now. Show me what else you've got..."); } else if (flirtResult.responseType === "sexual_dominant") { responses.push("*grabs you firmly* Mmm, I like when you flirt with me. But remember, I'm the one in control here..."); responses.push("*commanding tone* Get over here. I want to see if you're as good as you think you are..."); responses.push("*pulls you close by the waist* Such a tease. Maybe I need to teach you who's boss..."); } else if (flirtResult.responseType === "sexual_submissive") { responses.push("*whimpers softly* Y-yes... I'll do whatever you want... just tell me what you need..."); responses.push("*looks up at you with need* Please... I want you to take charge... use me however you like..."); responses.push("*trembling* I... I'm yours. Completely. Just... please touch me..."); } else if (flirtResult.responseType === "sexual_positive") { responses.push("*pulls you closer* I've been hoping you'd say something like that. Want to take this somewhere more private?"); responses.push("*breathing heavier* The way you look at me... it's making me very distracted... in a good way..."); responses.push("*smiles seductively* I think we both know where this is heading. And I am very much into it."); } /* STANDARD FLIRT RESPONSES (non-sexual/lower intensity) */ else if (flirtResult.responseType === "flirty_response") { responses.push("*leans in with a smile* Well, aren't you bold? I like that..."); responses.push("*twirls hair* Mmm, I like where this is going..."); responses.push("*bites lip* You know just what to say, don't you?"); } else if (flirtResult.responseType === "romantic_response") { responses.push("*blushes slightly* That's... really sweet of you to say."); responses.push("*smiles warmly* You're quite charming, aren't you?"); responses.push("*tucks hair behind ear* That was really sweet. You always know just what to say to make me smile."); } else if (flirtResult.responseType === "flustered_response") { responses.push("*face turns red* I-I... um... *fidgets nervously* ...thank you?"); responses.push("W-what? You... you can't just SAY things like that... *looks away*"); responses.push("*stammers* I... oh... um... *mumbles incoherently*"); } else if (flirtResult.responseType === "confident_response") { responses.push("*smirks* Smooth. Real smooth. I might just be interested."); responses.push("*raises eyebrow* Bold move. I can respect that."); responses.push("*crosses arms with a grin* You've got guts. I like that. Keep impressing me and we'll see where this goes."); } else if (flirtResult.responseType === "cool_response") { responses.push("*raises an eyebrow* Noted. Was there something else?"); responses.push("*unimpressed* That was... adequate. I suppose."); responses.push("*barely glances up* Cute attempt. You'll have to try harder than that to get my attention."); } else if (flirtResult.responseType === "reserved_response") { responses.push("*looks away* That's... inappropriate. But... not entirely unwelcome."); responses.push("*stiffens* I... let's not go there. Yet."); responses.push("*cautious look* I'm... flattered. I think. Just... give me some time to process that."); } /* REJECTION RESPONSES */ else if (flirtResult.responseType === "polite_rejection") { responses.push("That's flattering, but I'm not really interested in that way. No offense!"); responses.push("*smiles politely* I appreciate the thought, but I don't swing that way."); responses.push("Oh, that's sweet, but I'm afraid you're not my type. Nothing personal!"); } else if (flirtResult.responseType === "harsh_rejection") { responses.push("*scoffs* Seriously? Not a chance. You're not my type. At all."); responses.push("Ew, no. Just... no. What made you think that was a good idea?"); responses.push("*laughs* Oh, that's precious. You actually thought I'd be interested?"); } else if (flirtResult.responseType === "awkward_rejection") { responses.push("Oh... um... I don't... I mean... it's not you, it's just..."); responses.push("*awkward silence* ...I'm... going to pretend that didn't happen."); } else if (flirtResult.responseType === "too_forward") { responses.push("*steps back* Whoa, we just met. Maybe slow down a bit?"); responses.push("*uncomfortable* That's... a bit much, don't you think? We barely know each other."); responses.push("*holds up hands* Easy there. I appreciate the confidence, but maybe buy me a drink first? Or at least learn my name."); } else if (flirtResult.responseType === "confused") { responses.push("I... I need to know someone better before I can feel that way about them."); responses.push("*puzzled* That's... we don't know each other well enough for that."); responses.push("*tilts head* Wait, are you... flirting? With me? I genuinely can't tell. We should get to know each other better first."); } else if (flirtResult.responseType === "uncomfortable") { responses.push("*uncomfortable* I'm... not really interested in that kind of thing. Sorry."); responses.push("*shifts away* I don't really feel attraction like that. It's nothing personal."); responses.push("*looks down* That kind of attention makes me uncomfortable. Can we just... talk normally? Please?"); } else if (flirtResult.responseType === "polite_decline") { responses.push("*soft smile* I appreciate the attention, really. But that's not something I'm looking for."); } else { responses.push("*chuckles* That's flattering, I suppose."); responses.push("*amused* Smooth. Real smooth."); } } else if (topic === "debate") { if (npc.mentalTraits.includes("Nerd") || npc.mentalTraits.includes("Intelligent")) { responses.push("*eyes light up* Oh, you want to discuss ideas? Finally, someone with intellectual curiosity!"); responses.push("Interesting perspective. However, have you considered the counterargument...?"); responses.push("*adjusts glasses* This is exactly the kind of stimulating conversation I've been craving."); } else if (npc.mentalTraits.includes("Competitive")) { responses.push("*grins* A debate? Prepare to lose. I'm very well-read on this topic."); responses.push("Oh, you want to challenge me? Bring it on!"); } else if (npc.mentalTraits.includes("Stubborn")) { responses.push("*crosses arms* I know what I know. You're not changing my mind."); responses.push("My opinion is my opinion. But sure, let's 'debate'."); } else { responses.push("*shrugs* I guess we can talk about that. What's your angle?"); responses.push("Hmm, that's an interesting topic to explore. What do you think?"); } } else if (topic === "fitness") { if (npc.mentalTraits.includes("Jock") || npc.physicalTraits.includes("Muscular")) { responses.push("*flexes* You wanna talk gains? Let's GO! I've been crushing it at the gym lately."); responses.push("Bro, my workout routine is insane right now. You lifting? What's your max?"); responses.push("Finally someone who gets it! Fitness isn't just a hobby, it's a lifestyle."); } else if (npc.mentalTraits.includes("Competitive")) { responses.push("*sizing you up* You look like you work out. Bet I could still outrun you though."); } else if (npc.mentalTraits.includes("Lazy")) { responses.push("*yawns* Sports? Exercise? Hard pass. I get tired just thinking about it."); } else { responses.push("I'm not super athletic, but I try to stay active. What about you?"); } } else if (topic === "gossip") { if (npc.mentalTraits.includes("Gossipy") || npc.mentalTraits.includes("Nosy")) { responses.push("*leans in excitedly* Oh my god, you have to tell me EVERYTHING. I heard the craziest thing the other day..."); responses.push("Spill the tea! I've been dying for some good gossip. Did you hear about...?"); responses.push("*eyes widen* Ooh, gossip? I know SO much about everyone in this city!"); } else if (npc.mentalTraits.includes("Honest") || npc.mentalTraits.includes("Loyal")) { responses.push("*frowns* I'm not really into gossip. It can hurt people, you know?"); responses.push("I try not to talk about people behind their backs. It just feels wrong."); } else { responses.push("*glances around* Okay, but you didn't hear this from me..."); } } else if (topic === "darkTopics") { if (npc.mentalTraits.includes("Goth") || npc.mentalTraits.includes("Philosophical")) { responses.push("*eyes soften* Finally, someone who gets it. Life is fleeting, existence is meaningless, and yet... here we are."); responses.push("*nods thoughtfully* The darkness is where truth lives. Most people are too afraid to look."); responses.push("Death, entropy, the void... these are the topics that truly matter. I appreciate your depth."); } else if (npc.mentalTraits.includes("Optimistic") || npc.mentalTraits.includes("Bubbly")) { responses.push("*uncomfortable* Um... that's kind of heavy? Can we talk about something happier?"); responses.push("*shifts uncomfortably* I don't really like thinking about sad stuff..."); } else if (npc.mentalTraits.includes("Depressed") || npc.mentalTraits.includes("Pessimistic")) { responses.push("*sighs deeply* Yeah... I think about this stuff a lot. Too much, probably."); responses.push("*looks away* The futility of it all... sometimes I wonder what the point is."); } else { responses.push("*pauses* That's... deep. I don't usually think about stuff like that."); } } else if (topic === "beSubmissive") { if (npc.mentalTraits.includes("Dominant") || npc.mentalTraits.includes("Bossy")) { responses.push("*smirks* Good. I like when people know their place. Now, let me tell you what I think..."); responses.push("*nods approvingly* Smart move, letting me take charge. As I was saying..."); responses.push("*straightens up* Finally, someone who respects the natural order of things."); } else if (npc.mentalTraits.includes("Arrogant")) { responses.push("*pleased* Obviously I should be leading this conversation. So, as I was saying..."); } else { responses.push("*surprised* Oh, you want me to take the lead? Alright then..."); } } else if (topic === "takeCharge") { if (npc.mentalTraits.includes("Submissive") || npc.mentalTraits.includes("Shy")) { responses.push("*relaxes visibly* Oh, that's... actually nice. I'm not great at leading conversations..."); responses.push("*nods quietly* I appreciate you taking charge. What did you want to talk about?"); } else if (npc.mentalTraits.includes("Timid")) { responses.push("*looks grateful* Thank you... I always feel so awkward deciding what to talk about."); } else { responses.push("*shrugs* Sure, go ahead. I'm listening."); } } else if (topic === "playAlong") { if (npc.mentalTraits.includes("Bimbo") || npc.mentalTraits.includes("Airhead")) { responses.push("*giggles* Oh my gosh, you totally get me! Like, we're vibing so hard right now!"); responses.push("*bounces excitedly* Yay! You're like, SO fun to talk to! This is amazing!"); responses.push("*twirls hair* Right?! I know, right?! Omigosh, we should hang out more!"); } else if (npc.mentalTraits.includes("Bubbly")) { responses.push("*beams* You're so positive! I love your energy! This is great!"); } else { responses.push("*smiles* You're fun to be around!"); } } else if (topic === "fashion") { if (npc.mentalTraits.includes("Prep") || npc.mentalTraits.includes("Diva")) { responses.push("*eyes light up* Oh my god, YES! Fashion is EVERYTHING. Have you seen the latest trends?"); responses.push("*looks you over approvingly* Finally, someone who appreciates style. Your outfit is..."); responses.push("*excitedly* Okay so I was just looking at this amazing designer piece and..."); } else if (npc.mentalTraits.includes("Vain")) { responses.push("*preens* Of course you want to talk about fashion. It's one of my specialties."); } else if (npc.mentalTraits.includes("Goth")) { responses.push("*nods* Fashion as self-expression? The aesthetic of darkness? Now we're talking."); } else { responses.push("*shrugs* I try to look good. What's your style like?"); } } else if (topic === "advice") { if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Nurturing")) { responses.push("*softens* Of course I'll help. What's on your mind? I'm here for you."); responses.push("*concerned* Tell me everything. I want to help if I can."); } else if (npc.mentalTraits.includes("Wise")) { responses.push("*nods thoughtfully* I may have some insight. What's the situation?"); } else { responses.push("*considers* I can try to help. What do you need advice about?"); } } else if (topic === "secrets") { if (npc.mentalTraits.includes("Trustworthy") || npc.mentalTraits.includes("Loyal")) { responses.push("*moves closer* Your secrets are safe with me. I'd never betray your trust."); responses.push("*serious expression* I appreciate that you trust me with this. I won't let you down."); } else if (npc.mentalTraits.includes("Gossipy")) { responses.push("*eyes widen* Ooh, a secret? Tell me, tell me! *already thinking about who to tell*"); } else if (npc.mentalTraits.includes("Manipulative")) { responses.push("*files information away* How... interesting. I appreciate your candor."); } else { responses.push("*listens intently* Wow, that's... thank you for trusting me with that."); } } else if (topic === "support") { if (npc.mentalTraits.includes("Sensitive") || npc.mentalTraits.includes("Anxious")) { responses.push("*tears up slightly* That means so much to me... I really needed to hear that."); responses.push("*voice wavers* Thank you... I don't get much support usually."); } else if (npc.mentalTraits.includes("Cold")) { responses.push("*uncomfortable* I... appreciate the thought. This is awkward."); } else { responses.push("*touched* That's really kind of you. Thank you."); } } else if (topic === "plan") { if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Outgoing")) { responses.push("*excited* Yes! We should totally hang out! What did you have in mind?"); responses.push("*beams* I'd love that! Let's make it happen!"); } else if (npc.mentalTraits.includes("Antisocial") || npc.mentalTraits.includes("Reserved")) { responses.push("*hesitant* I don't know... I'm not really a 'going out' kind of person."); } else { responses.push("*nods* Sure, that could be fun. What were you thinking?"); } } else if (topic === "deep") { if (npc.mentalTraits.includes("Empathetic") || npc.mentalTraits.includes("Philosophical")) { responses.push("*takes your hand* These conversations are what real connection is about. I feel like I really understand you."); responses.push("*thoughtful* I've been thinking about life a lot lately too. It's nice to have someone to really talk to."); } else if (npc.mentalTraits.includes("Shallow")) { responses.push("*fidgets* This is getting really heavy. Can we talk about something else?"); } else { responses.push("*nods slowly* I never really open up like this. But with you... it feels right."); } } else if (topic === "confide") { if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Nurturing")) { responses.push("*puts arm around you* I'm here for you. Whatever you're going through, you don't have to face it alone."); responses.push("*concerned* Tell me what's bothering you. I want to help."); } else if (npc.mentalTraits.includes("Impatient")) { responses.push("*sighs* Okay, what is it? Just tell me."); } else { responses.push("*listens carefully* I'm glad you feel comfortable enough to tell me this."); } } else if (topic === "bestFriend") { responses.push("*emotional* You mean so much to me. I can't imagine my life without you in it."); responses.push("*hugs you* We've been through so much together. You're like family to me."); responses.push("*teary-eyed* I don't know what I'd do without you. Seriously."); } else if (topic === "tease") { if (npc.mentalTraits.includes("Playful") || npc.mentalTraits.includes("Witty")) { responses.push("*laughs* Oh, you think you're funny? Two can play at that game!"); responses.push("*grins* Getting cheeky, are we? I like it."); } else if (npc.mentalTraits.includes("Sensitive") || npc.mentalTraits.includes("Insecure")) { responses.push("*hurt* That's... why would you say that?"); responses.push("*looks away* I know you're joking, but... that kind of stings."); } else if (npc.mentalTraits.includes("Serious")) { responses.push("*unamused* I don't really appreciate that kind of humor."); } else { responses.push("*chuckles* Alright, alright. Laugh it up."); } } else if (topic === "challenge") { if (npc.mentalTraits.includes("Competitive") || npc.mentalTraits.includes("Confident")) { responses.push("*stands straighter* You want to challenge me? Interesting. I respect that."); responses.push("*grins* Finally, someone with the guts to push back. I like it."); } else if (npc.mentalTraits.includes("Hot-Headed") || npc.mentalTraits.includes("Stubborn")) { responses.push("*bristles* What did you just say? You think you know better than me?!"); responses.push("*angry* Don't you DARE question me. I know what I'm talking about!"); } else { responses.push("*considers* Hmm, you make an interesting point. I'll have to think about it."); } } else if (topic === "pushBoundaries") { if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { responses.push("*leans in closer* Oh? And just how far are you willing to go...?"); responses.push("*smoldering look* I was hoping you'd say something like that..."); } else if (npc.mentalTraits.includes("Perverted") || npc.mentalTraits.includes("Lustful")) { responses.push("*eyes darken* Now we're getting to the good stuff..."); } else { responses.push("*intrigued* Well this got interesting..."); } } /* === Shared Trait Options (Phase 2B) === */ else if (topic === "geekOut") { if (npc.mentalTraits.includes("Nerd") || npc.mentalTraits.includes("Intellectual")) { responses.push("*eyes light up* Oh my god, FINALLY someone who gets it! Okay so listen..."); responses.push("*excitedly pulls out phone* Wait wait wait — you HAVE to see this thing I found."); responses.push("*grabs your arm* We need to talk about this for at least an hour. Minimum."); } else { responses.push("*nods enthusiastically* Right?! I was just reading about that!"); responses.push("*grinning* You're speaking my language! Tell me more."); } } else if (topic === "workoutTalk") { if (npc.mentalTraits.includes("Competitive")) { responses.push("*flexes* I bet I could out-lift you though. Just saying."); responses.push("*grins* Oh you work out? Name your max. Let's compare."); } else if (npc.mentalTraits.includes("Friendly")) { responses.push("*excited* Yes! We should totally be gym buddies!"); responses.push("*nods* I love having someone to talk shop with. What's your split?"); } else { responses.push("*stretches* Nothing like a good workout, right? Keeps the mind sharp."); responses.push("*nods* The gym is basically my second home. What about you?"); } } else if (topic === "fashionBond") { if (npc.mentalTraits.includes("Prep") || npc.mentalTraits.includes("Diva")) { responses.push("*gasps* Okay we NEED a shopping trip. Your taste is amazing!"); responses.push("*looks you over approvingly* Someone who actually understands aesthetics? I'm obsessed."); } else if (npc.mentalTraits.includes("Vain")) { responses.push("*preens* I mean, obviously I have great taste. But yours isn't bad either!"); } else { responses.push("*smiles* I love that we can talk about this stuff! Not everyone appreciates fashion."); responses.push("*nods* Style is so important. It's how you tell the world who you are."); } } else if (topic === "darkHumor") { if (npc.mentalTraits.includes("Goth") || npc.mentalTraits.includes("Cynical")) { responses.push("*dark chuckle* Now THAT's funny. Most people are too soft for that kind of humor."); responses.push("*smirks* Finally, someone who doesn't flinch. I like you."); } else if (npc.mentalTraits.includes("Sarcastic")) { responses.push("*snorts* Okay that was actually hilarious. We're terrible people."); } else { responses.push("*laughs* Oh that's wrong. That's so wrong. ...Tell me another one."); responses.push("*covering mouth* I shouldn't be laughing at that but here we are."); } } else if (topic === "flirtPlayfully") { if (npc.mentalTraits.includes("Seductive")) { responses.push("*moves closer* Mmm, I like this game we play. Don't stop."); responses.push("*lowers voice* You're dangerous, you know that? I like it."); } else if (npc.mentalTraits.includes("Confident")) { responses.push("*matching your grin* Oh, we're doing this? Game on."); responses.push("*winks back* Don't start something you can't finish."); } else { responses.push("*blushes but smiles* You always know how to make me feel special."); responses.push("*playful shove* Stop it, you're making me all flustered!"); responses.push("*giggles* You're such a flirt! ...I love it though."); } } /* === Mood-Gated Options (Phase 2B) === */ else if (topic === "askWhatsWrong") { if (npc.mentalTraits.includes("Open") || npc.mentalTraits.includes("Emotional")) { responses.push("*voice cracks* I... thank you for asking. It's been a really rough day."); responses.push("*sighs* You noticed, huh? I didn't want to burden anyone but... yeah, things aren't great."); } else if (npc.mentalTraits.includes("Proud") || npc.mentalTraits.includes("Stubborn")) { responses.push("*crosses arms* I'm fine. ...Okay, maybe I'm not fine. But I don't want to talk about it."); responses.push("*looks away* It's nothing. Just... having a day. But thanks for asking."); } else { responses.push("*surprised* You can tell? I... yeah, something's been on my mind. Thanks for caring."); responses.push("*softens* It means a lot that you asked. Most people don't notice."); responses.push("*small smile* I appreciate you checking in. Really."); } } else if (topic === "matchEnergy") { if (npc.mentalTraits.includes("Bubbly") || npc.mentalTraits.includes("Energetic")) { responses.push("*bouncing* YES! Right?! Everything is just AMAZING right now!"); responses.push("*high fives you* I LOVE that you get it! Most people tell me to calm down!"); } else if (npc.mentalTraits.includes("Friendly")) { responses.push("*beaming* It's so great having someone to share this with! You're awesome!"); responses.push("*laughs* Your enthusiasm is everything! This is why I like hanging out with you!"); } else { responses.push("*grins widely* Ha! I like your energy! Let's keep this going!"); responses.push("*pumps fist* That's what I'm talking about! Good vibes only!"); } } else if (topic === "calmDown") { if (npc.mentalTraits.includes("Hot-Headed") || npc.mentalTraits.includes("Aggressive")) { responses.push("*still fuming* I... *takes a breath* ...Fine. Maybe I do need a second."); responses.push("*clenches fists then releases* Don't tell me to calm down! ...But okay, yeah, give me a minute."); } else if (npc.mentalTraits.includes("Proud")) { responses.push("*huffs* I'm perfectly calm. ...Okay, I'm not. But I have good reason!"); } else { responses.push("*exhales slowly* ...Yeah. Yeah, you're right. Sorry about that."); responses.push("*rubs temples* I didn't mean to snap. Thanks for being patient with me."); responses.push("*deep breath* Okay... okay. I appreciate you not just walking away."); } } /* --- MEMORY-GATED TOPICS --- */ else if (topic === "reminisce") { if (npc.mentalTraits.includes("Sentimental") || npc.mentalTraits.includes("Romantic")) { responses.push("*eyes light up* Oh my gosh, yes! I think about that day sometimes. We were so different back then, weren't we?"); responses.push("*smiles softly* I remember it perfectly. Feels like yesterday and forever ago at the same time."); } else if (npc.mentalTraits.includes("Cynical") || npc.mentalTraits.includes("Cold")) { responses.push("*shrugs* Yeah, I remember. We didn't exactly hit it off at first. But look at us now."); } else if (npc.mentalTraits.includes("Playful") || npc.mentalTraits.includes("Humorous")) { responses.push("Ha! Yeah, I remember. You were so awkward! ...Okay, maybe I was too. Good times though."); responses.push("*laughs* Our first meeting? Classic. We had no idea we'd end up as close as we are."); } else { responses.push("*nods* Yeah, I remember. A lot has changed since then. I'm glad we stuck around for each other."); responses.push("That was a while ago, huh? I'm really glad we kept talking after that first time."); responses.push("*smiles* I do remember. Honestly? Meeting you is one of my favorite memories in this city."); } } else if (topic === "insideJoke") { if (npc.mentalTraits.includes("Humorous") || npc.mentalTraits.includes("Playful")) { responses.push("*bursts out laughing* STOP, don't — *wheezing* — every time! It NEVER gets old!"); responses.push("*cracks up immediately* I swear, no one else would get why that's funny. But WE know."); } else if (npc.mentalTraits.includes("Serious") || npc.mentalTraits.includes("Reserved")) { responses.push("*tries not to smile* ...You're ridiculous. *corners of mouth twitching* ...Okay, fine, it's funny."); } else { responses.push("*snorts* Oh no, not again — *laughing* — okay, you got me. That's always going to be our thing."); responses.push("*grinning ear to ear* See, THIS is why I keep hanging out with you. Nobody else gets me like this."); responses.push("*laughing* I can't believe that still cracks us up. I love that we have this."); } } else if (topic === "apologize") { if (npc.mentalTraits.includes("Forgiving") || npc.mentalTraits.includes("Kind")) { responses.push("*softens* ...Thank you. That actually means a lot. I know that wasn't easy for you."); responses.push("*nods slowly* I appreciate you saying that. Really. Let's just... move forward, okay?"); } else if (npc.mentalTraits.includes("Proud") || npc.mentalTraits.includes("Stubborn")) { responses.push("*crosses arms* ...Yeah, you were pretty harsh. *pauses* But... thanks for owning up."); responses.push("*studies you* You mean it? ...Okay. I won't forget, but I appreciate the honesty."); } else if (npc.mentalTraits.includes("Sensitive") || npc.mentalTraits.includes("Emotional")) { responses.push("*eyes watering* You have no idea how much I needed to hear that. Those things really hurt me."); responses.push("*voice wavering* Thank you... I was starting to wonder if you even cared that it hurt me."); } else { responses.push("*quiet for a moment* ...I appreciate that. It takes guts. We're cool."); responses.push("*nods* Thanks for saying that. Let's just try and be better going forward, deal?"); responses.push("*exhales* Okay. I forgive you. Just... please try not to do it again."); } } else if (topic === "thankGifts") { if (npc.mentalTraits.includes("Warm") || npc.mentalTraits.includes("Friendly")) { responses.push("*beams* Are you kidding? I LOVE when you bring me stuff! It always makes my whole day."); responses.push("*hugs you* You're seriously the sweetest. Every single gift has made me so happy."); } else if (npc.mentalTraits.includes("Humble") || npc.mentalTraits.includes("Shy")) { responses.push("*blushes* Oh gosh, you don't have to thank ME. If anything, I feel spoiled!"); responses.push("*looks down shyly* I always feel a little guilty accepting them... but honestly? They brighten my day."); } else if (npc.mentalTraits.includes("Materialistic") || npc.mentalTraits.includes("Vain")) { responses.push("*grins* Well, you DO have great taste. Keep them coming!"); } else { responses.push("*smiles* Hey, I enjoy getting them just as much as you enjoy giving. It's our thing."); responses.push("*touched* That's really sweet of you to say. I always look forward to what you'll bring next."); responses.push("*nods* I appreciate you saying that. And honestly? Your gifts always show how well you know me."); } } else if (topic === "noticedChange") { var evoData = v.npcEvolution && v.npcEvolution[npc.name]; var pendingTrait = evoData ? evoData.pending : null; var lastHist = evoData && evoData.history && evoData.history.length > 0 ? evoData.history[evoData.history.length - 1] : null; var evoSource = lastHist ? lastHist.source : "natural"; if (pendingTrait) { if (evoSource === "impression") { if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Bold")) { responses.push("*nods thoughtfully* Yeah, I've noticed it myself. I feel more " + pendingTrait + " lately. Honestly? I think being around you helped make that happen."); responses.push("*grins* You picked up on that, huh? I've been feeling more " + pendingTrait + ". Pretty sure you're a big reason why."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Introverted")) { responses.push("*blushes* You... you noticed? I've been feeling more " + pendingTrait + " lately. I think... maybe being around you helped."); responses.push("*looks away shyly* Is it that obvious? I do feel different. More " + pendingTrait + ", I guess. You've had a real effect on me."); } else { responses.push("*smiles warmly* You know, I think you played a part in this. Being around you... I've been feeling more " + pendingTrait + "."); responses.push("*reflects* Yeah, something has changed. I feel more " + pendingTrait + " now. I think being around you is a big reason why."); } } else if (evoSource === "job") { var jobLabel = npc.jobs && npc.jobs.length > 0 ? npc.jobs[0] : "my job"; responses.push("*thinks* I guess working as a " + jobLabel + " has been shaping me. I feel more " + pendingTrait + " these days."); responses.push("*nods* Yeah, I can feel it. Working as a " + jobLabel + " changes you, you know? I've been getting more " + pendingTrait + "."); } else { if (npc.mentalTraits.includes("Thoughtful") || npc.mentalTraits.includes("Analytical")) { responses.push("*pauses thoughtfully* I've been doing some soul-searching. I feel more " + pendingTrait + " than before. Growth, I suppose."); responses.push("*reflects* You're perceptive. I've been evolving, I think. Feeling more " + pendingTrait + " lately."); } else { responses.push("*smiles* I guess I've just been growing. I feel more " + pendingTrait + " these days. Life changes you, right?"); responses.push("*nods* Yeah, something about me is different. I feel more " + pendingTrait + " now. Just part of growing, I guess."); } } v.npcEvolution[npc.name].pending = null; } else { responses.push("*tilts head* Different? Hmm, maybe. I can't really put my finger on it."); responses.push("*shrugs* I don't know... maybe I have changed. Hard telling from the inside, you know?"); } } /* --- NPC SOCIAL TOPICS (Phase 7) --- */ else if (topic === "askAboutNPC") { var targetName = v.socialTarget || "them"; var opinionText = setup.npcSocial.getOpinionText(npc, targetName); responses.push(opinionText); /* Mark bond as discovered */ var bondKey = setup.getNpcRelationshipKey(npc.name, targetName); if (!v.discoveredNpcBonds) v.discoveredNpcBonds = {}; v.discoveredNpcBonds[bondKey] = true; } else if (topic === "positiveGossip") { var targetName = v.socialTarget || "them"; var gossipResult = setup.npcSocial.applyGossip(npc.name, targetName, true, relLevel); if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Warm")) { responses.push("Oh really? That's wonderful! I always try and see the best in people. " + gossipResult.text); } else if (npc.mentalTraits.includes("Cynical") || npc.mentalTraits.includes("Suspicious")) { responses.push("Hmm, is that so? I'll believe it when I see it. " + gossipResult.text); } else { responses.push("Good for them. It's always nice hearing positive things about people. " + gossipResult.text); } } else if (topic === "negativeGossip") { var targetName = v.socialTarget || "them"; var gossipResult = setup.npcSocial.applyGossip(npc.name, targetName, false, relLevel); if (gossipResult.caught) { responses.push("*narrows eyes* Wait... that doesn't sound right. Are you sure about that? I think I'm gonna ask " + targetName + " about this myself. " + gossipResult.text); } else if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Empathetic")) { responses.push("Oh... that's disappointing. I always thought " + targetName + " was better than that. " + gossipResult.text); } else if (npc.mentalTraits.includes("Gossipy") || npc.mentalTraits.includes("Cynical")) { responses.push("Ha! I KNEW it. I always had a feeling about " + targetName + ". " + gossipResult.text); } else { responses.push("Hmm, that's... concerning. I'll keep that in mind. " + gossipResult.text); } } else if (topic === "introduceNPCs") { var targetName = v.socialTarget || "someone"; /* Create acquaintance bond */ setup.npcSocial.addNpcToNpcPoints(npc.name, targetName, 25); var bondKey = setup.getNpcRelationshipKey(npc.name, targetName); if (!v.discoveredNpcBonds) v.discoveredNpcBonds = {}; v.discoveredNpcBonds[bondKey] = true; if (npc.mentalTraits.includes("Social") || npc.mentalTraits.includes("Outgoing")) { responses.push("Oh yeah? I'm always down for meeting new people! Set it up — I'll bring the energy."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Introverted")) { responses.push("Oh... I mean, I guess? Meeting new people is kind of nerve-wracking, but if you think we'd get along..."); } else { responses.push("Sure, why not? I'm open for meeting someone new. Thanks for thinking of me."); } } else if (topic === "takeSides") { var targetName = v.socialTarget || "them"; /* Player gains favor, the NPC-NPC relationship worsens */ setup.npcSocial.addNpcToNpcPoints(npc.name, targetName, -10); var bondKey = setup.getNpcRelationshipKey(npc.name, targetName); if (!v.discoveredNpcBonds) v.discoveredNpcBonds = {}; v.discoveredNpcBonds[bondKey] = true; if (npc.mentalTraits.includes("Loyal") || npc.mentalTraits.includes("Grateful")) { responses.push("You have no idea how much that means. Seriously. It's good knowing someone has my back against " + targetName + "."); } else if (npc.mentalTraits.includes("Proud") || npc.mentalTraits.includes("Dominant")) { responses.push("Damn right. Glad someone finally sees it my way. " + targetName + " had it coming."); } else { responses.push("Thanks for backing me up. It means a lot knowing I'm not the only one who feels this way about " + targetName + "."); } } else if (topic === "mendRelationship") { var targetName = v.socialTarget || "them"; var rel = setup.getNpcToNpcRelationship(npc.name, targetName); var hostility = rel ? Math.abs(rel.points) : 0; var bondKey = setup.getNpcRelationshipKey(npc.name, targetName); if (!v.discoveredNpcBonds) v.discoveredNpcBonds = {}; v.discoveredNpcBonds[bondKey] = true; if (hostility > 75) { /* Too hostile — refuses */ if (npc.mentalTraits.includes("Stubborn") || npc.mentalTraits.includes("Proud")) { responses.push("No way. After everything " + targetName + " did? Absolutely not. Some things can't be fixed."); } else { responses.push("I appreciate you trying, but... there's too much damage with " + targetName + ". Maybe someday, but not now."); } } else { /* Willing — adds points */ setup.npcSocial.addNpcToNpcPoints(npc.name, targetName, 15); if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Forgiving")) { responses.push("You know what? Maybe you're right. I should give " + targetName + " another chance. Life's too short for grudges."); } else if (npc.mentalTraits.includes("Diplomatic")) { responses.push("Hmm. I suppose there could be room for... a fresh start. I'll think about reaching out."); } else { responses.push("*sighs* Maybe. I'll consider giving " + targetName + " another shot. But they better not pull the same stuff again."); } } } else if (topic === "romanticNudge") { var targetName = v.socialTarget || "them"; var bondKey = setup.getNpcRelationshipKey(npc.name, targetName); if (!v.discoveredNpcBonds) v.discoveredNpcBonds = {}; v.discoveredNpcBonds[bondKey] = true; /* Check compatibility */ var targetNpc = null; for (var rIdx = 0; rIdx < v.npcs.length; rIdx++) { if (v.npcs[rIdx].name === targetName) { targetNpc = v.npcs[rIdx]; break; } } var compat = targetNpc ? setup.npcSocial.getCompatibility(npc, targetNpc) : 0; if (compat > 20) { /* Interested — set romantic drift flag */ setup.npcSocial.addNpcToNpcPoints(npc.name, targetName, 10); if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Insecure")) { responses.push("*blushes deeply* W-what?! " + targetName + "? I mean... maybe I've thought about it... once or twice... don't tell anyone!"); } else if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Confident")) { responses.push("*grins* Oh, you noticed? Maybe I have been looking at " + targetName + " a little differently lately. Good eye."); } else { responses.push("*pauses* Huh... " + targetName + "? I hadn't really thought about it, but... now that you mention it, they are pretty attractive."); } } else { /* Not compatible — dismisses */ if (npc.mentalTraits.includes("Direct") || npc.mentalTraits.includes("Blunt")) { responses.push("*laughs* " + targetName + "? No way. We're not a match at all. Nice try though."); } else { responses.push("*shakes head* I don't think " + targetName + " and I are like that. We're just... not really compatible, you know?"); } } } /* ====== ROMANCE TOPIC RESPONSES ====== */ else if (topic === "confessFeelings") { /* Response handled by setup.romance.confess() in the passage — this is the NPC's verbal reaction */ var romData = v.npcRomance ? v.npcRomance[npc.name] : null; var confessSuccess = romData && romData.level; if (confessSuccess) { if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Introverted")) { responses.push("*face turns bright red* I... I've been hoping you'd say that. I didn't know how... I feel the same way."); } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Bold")) { responses.push("*smiles knowingly* Took you long enough. I was wondering when you'd finally say something. Yes. Absolutely yes."); } else if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { responses.push("*pulls you closer* Oh, I've been waiting for this... You have no idea how much I wanted this."); } else if (npc.mentalTraits.includes("Romantic") || npc.mentalTraits.includes("Kind")) { responses.push("*eyes light up* Really? You mean it? Because I've been feeling the same way for a while now. This makes me so happy."); } else { responses.push("*looks surprised, then smiles* Wow. I... yeah. I feel something between us too. Let's see where this goes."); } } else { if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Empathetic")) { responses.push("*looks away gently* I'm so sorry... I care about you, I really do. Just... I don't feel that way. I hope we can still be close."); } else if (npc.mentalTraits.includes("Direct") || npc.mentalTraits.includes("Blunt")) { responses.push("*shakes head* I appreciate you being honest, but I don't feel that way about you. Better you know now."); } else { responses.push("*pauses uncomfortably* That's... really sweet of you. But I don't think I see us like that. I'm sorry."); } } } else if (topic === "holdHands") { var sPers = setup.romance.getSexualPersonality(npc); if (sPers === "nervous" || npc.mentalTraits.includes("Shy")) { responses.push("*blushes as your fingers intertwine* Your hand feels so warm... *squeezes gently* I like this."); } else if (sPers === "tender" || npc.mentalTraits.includes("Romantic")) { responses.push("*laces fingers with yours, bringing your hand up, pressing a soft kiss against your knuckles* Perfect."); } else if (sPers === "playful" || npc.mentalTraits.includes("Flirty")) { responses.push("*grabs your hand, swinging it between you* Look at us being all cute. I love it."); } else if (sPers === "dominant") { responses.push("*takes your hand firmly, pulling you a step closer* Come here. I want you right beside me."); } else { responses.push("*takes your hand with a warm smile* Mmm, nice. Simple, but nice. I like being close like this."); } } else if (topic === "kissNPC") { var sPers = setup.romance.getSexualPersonality(npc); if (sPers === "dominant") { responses.push("*grabs you by the collar, pulling you in, kissing you hard* Been wanting that all day."); } else if (sPers === "submissive") { responses.push("*melts against you, lips parting softly* Mmm... *whispers* Don't stop..."); } else if (sPers === "tender") { responses.push("*cups your face gently, kissing you slow and sweet, savoring the moment* You taste like everything I've been missing."); } else if (sPers === "playful") { responses.push("*kisses you quickly then pulls back with a grin* Mmm, one more? *leans in again* Okay, maybe three more."); } else if (sPers === "nervous") { responses.push("*leans in hesitantly, then presses lips against yours — soft, tentative, trembling slightly* ...was that okay?"); } else if (sPers === "physical") { responses.push("*wraps arms around your waist, kissing you deeply, pressing your bodies together* God, I needed that."); } else if (sPers === "experimental") { responses.push("*kisses you, then traces your lower lip with a fingertip* Hmm, let me try that differently... *kisses you again, slower this time*"); } else { responses.push("*meets your lips with confidence, one hand sliding behind your neck* Now that's a proper kiss."); } } else if (topic === "romanticDate") { var sPers = setup.romance.getSexualPersonality(npc); if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Introverted")) { responses.push("*brightens up* Really? I'd love that. Maybe somewhere quiet where we can just... be together? That sounds perfect."); } else if (npc.mentalTraits.includes("Adventurous") || npc.mentalTraits.includes("Energetic")) { responses.push("*grins excitedly* Yes! Let's do something fun — maybe explore somewhere new, try something neither of us has done before!"); } else if (npc.mentalTraits.includes("Romantic")) { responses.push("*clasps hands together* A real date? With you? I already know it'll be wonderful. I don't care where we go, as long as we're together."); } else if (npc.mentalTraits.includes("Flirty") || npc.mentalTraits.includes("Seductive")) { responses.push("*leans in with a sly smile* A date? I like the sound of that. I promise I'll make it worth your while..."); } else { responses.push("*smiles warmly* That sounds great, actually. It'll be nice spending some real time together, just the two of us."); } } else if (topic === "askExclusive") { var sPers = setup.romance.getSexualPersonality(npc); if (npc.mentalTraits.includes("Romantic") || npc.mentalTraits.includes("Loyal")) { responses.push("*eyes glisten* You want us being exclusive? I've been hoping you'd ask. Yes. A thousand times yes. I only want you."); } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Bold")) { responses.push("*nods firmly* Good. Because I was getting ready for that conversation myself. You're mine, I'm yours. Deal?"); } else if (npc.mentalTraits.includes("Shy")) { responses.push("*covers mouth with both hands, eyes wide* E-exclusive? Like... officially together? *nods rapidly* Yes! I want that. I really want that."); } else if (npc.mentalTraits.includes("Cautious") || npc.mentalTraits.includes("Analytical")) { responses.push("*takes a breath* I've been thinking about this too. We work well together. Yes — let's make it official. I'm ready for that."); } else { responses.push("*smiles, taking your hand* Exclusive? Yeah... I'd really like that. It feels right with you."); } } else if (topic === "makeOutNPC") { var sPers = setup.romance.getSexualPersonality(npc); if (sPers === "dominant") { responses.push("*pushes you against the wall, hands gripping your hips* You started this... *kisses your neck roughly* Now deal with the consequences."); } else if (sPers === "submissive") { responses.push("*gasps softly as your hands wander* Whatever you want... *tilts head back, exposing neck* I'm yours..."); } else if (sPers === "tender") { responses.push("*pulls you close, kissing deeply, hands moving through your hair* I love how you feel... every single part of you..."); } else if (sPers === "playful") { responses.push("*giggles between kisses, tugging at your shirt* Mmm, getting handsy are we? *bites your lip teasingly* I like where this goes..."); } else if (sPers === "nervous") { responses.push("*breathing quickens as things intensify* Oh... *clutches your shirt* Oh god... wow... don't stop, okay? Please don't stop."); } else if (sPers === "physical") { responses.push("*grabs you tight, deepening the kiss aggressively* More. *runs hands over your body hungrily* I want more of you."); } else if (sPers === "experimental") { responses.push("*kisses along your jaw, finding sensitive spots* Here? *nips gently* What about here...? *smirks* I wanna learn every inch of you."); } else { responses.push("*kisses you deeply, pulling you against their body* Mmm, you're a great kisser. *runs hands down your sides* We should do this more often."); } } else if (topic === "initiateIntimacy") { var sPers = setup.romance.getSexualPersonality(npc); if (sPers === "dominant") { responses.push("*eyes darken with desire* Private? *grabs your wrist, starts walking* I thought you'd never ask. Move."); } else if (sPers === "submissive") { responses.push("*breath catches, cheeks flushing* Yes... *voice barely a whisper* Take me wherever you want. I'm all yours."); } else if (sPers === "tender") { responses.push("*takes both your hands, looking into your eyes* Are you sure? *soft smile* Because I want this. I want you. All of you."); } else if (sPers === "playful") { responses.push("*grins wickedly* Oh? Somewhere private? *runs a finger down your chest* Whatever could you have in mind...? Lead the way."); } else if (sPers === "nervous") { responses.push("*heart visibly pounding* I... *swallows hard* Yes. I'm nervous but I want this. I want you. Just... be gentle with me?"); } else if (sPers === "physical") { responses.push("*eyes light up with hunger* Finally. *pulls you by the belt* I've been thinking about this all day. Let's go. Now."); } else if (sPers === "experimental") { responses.push("*raises an eyebrow with interest* Somewhere private... I have a few ideas about what we could try. *takes your hand* Come on."); } else { responses.push("*meets your gaze steadily* I want that too. *slips hand into yours* Let's find somewhere just for us."); } } else if (topic === "pillowTalk") { var sPers = setup.romance.getSexualPersonality(npc); var discoveredPrefs = v.npcRomance && v.npcRomance[npc.name] ? v.npcRomance[npc.name].discoveredPrefs : []; if (sPers === "dominant") { responses.push("*stretches languidly* Wanna know what I like? I like being in control. Giving you orders. Watching you listen. *smirks* That drives me wild."); if (discoveredPrefs.indexOf("dominant") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("dominant"); } } else if (sPers === "submissive") { responses.push("*curls up against you* I love when you take charge... when you hold me down... I can just... let go. It makes me feel safe, actually."); if (discoveredPrefs.indexOf("submissive") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("submissive"); } } else if (sPers === "tender") { responses.push("*traces circles on your skin* For me it's all about the connection. The eye contact, the whispered words... the feeling that it's just us in the whole world."); if (discoveredPrefs.indexOf("tender") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("tender"); } } else if (sPers === "playful") { responses.push("*props up on elbow, grinning* I like it when we're laughing. When it's fun, teasing, neither of us taking it too seriously. *winks* The best part? The buildup."); if (discoveredPrefs.indexOf("playful") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("playful"); } } else if (sPers === "nervous") { responses.push("*hides face in your shoulder* God, this feels embarrassing but... I like being reassured. Knowing you want me. Being told I'm doing good. It helps me relax."); if (discoveredPrefs.indexOf("nervous") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("nervous"); } } else if (sPers === "physical") { responses.push("*rolls shoulders* I need intensity. The physical stuff — feeling every muscle, pushing limits, going hard. Slow and gentle puts me asleep."); if (discoveredPrefs.indexOf("physical") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("physical"); } } else if (sPers === "experimental") { responses.push("*eyes gleam* I like trying new things. Different positions, different places, different... dynamics. Variety keeps it exciting, you know?"); if (discoveredPrefs.indexOf("experimental") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("experimental"); } } else { responses.push("*looks at you thoughtfully* Honestly? I like when we're both really into it. When neither of us holds back. That mutual desire... that's the best part."); if (discoveredPrefs.indexOf("assertive") === -1 && v.npcRomance && v.npcRomance[npc.name]) { v.npcRomance[npc.name].discoveredPrefs.push("assertive"); } } } else if (topic === "deeperBond") { if (npc.mentalTraits.includes("Romantic") || npc.mentalTraits.includes("Kind")) { responses.push("*tears welling up* You mean it? I've never felt this way about anyone before. You're my person. My everything. I love you."); } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Bold")) { responses.push("*pulls you close, voice steady but thick with emotion* I'm never great with feelings, but... you're it for me. Nobody else even comes close."); } else if (npc.mentalTraits.includes("Shy")) { responses.push("*voice trembling* I... I love you. I've never said that before while meaning it like this. You make me brave enough."); } else if (npc.mentalTraits.includes("Playful") || npc.mentalTraits.includes("Humorous")) { responses.push("*tries joking but can't hide genuine emotion* You know, I was gonna say something funny, but... I just love you. Like, really love you. There. I said it."); } else { responses.push("*takes a deep breath* I want more with you too. What we have... it's special. I'm ready for whatever comes next, as long as it's with you."); } } else if (topic === "endThings") { if (npc.mentalTraits.includes("Kind") || npc.mentalTraits.includes("Empathetic")) { responses.push("*looks devastated but nods slowly* I... I understand. If that's what you need. I just... I hope you know how much you've meant."); } else if (npc.mentalTraits.includes("Aggressive") || npc.mentalTraits.includes("Dominant")) { responses.push("*jaw clenches* Fine. If that's what you want. *voice breaks slightly* Don't expect me pretending this doesn't hurt."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Sensitive")) { responses.push("*eyes fill with tears* No... please... *takes a shaky breath* I knew this was too good. I always knew. *turns away*"); } else if (npc.mentalTraits.includes("Confident")) { responses.push("*takes a moment, then straightens up* Okay. I'm never gonna beg. But you should know — what we had was real. I won't forget it."); } else { responses.push("*long silence* ...I see. *voice quiet* I wish things were different. But if this is what you want... I'll respect that."); } } else if (topic === "inviteHomeFriend") { if (npc.mentalTraits.includes("Outgoing") || npc.mentalTraits.includes("Social Butterfly")) { responses.push("*brightens up* Yeah! I'd love that! Let's go, I'm so down for this."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Introverted")) { responses.push("*small smile* Your place? That sounds nice, actually. Quieter than here."); } else if (npc.mentalTraits.includes("Lazy") || npc.mentalTraits.includes("Nonchalant")) { responses.push("*shrugs* Sure, why not? Lead the way."); } else { responses.push("*smiles* Sure, that sounds fun! Lead the way."); responses.push("Your place? Yeah, I'd like that. Let's go!"); } } else if (topic === "inviteHomeRomantic") { var sPerH = setup.romance.getSexualPersonality(npc); if (sPerH === "dominant") { responses.push("*eyes darken with interest* Your place? Perfect. Let's go. Now."); } else if (sPerH === "submissive") { responses.push("*blushes deeply* Y-yes... I'd like that. Bring me there."); } else if (sPerH === "tender") { responses.push("*takes your hand gently* I'd love nothing more than that. Let's go be alone."); } else if (sPerH === "nervous") { responses.push("*fidgets, but smiles* Your place? That's... yes. I feel safe there. With you."); } else if (sPerH === "playful") { responses.push("*grins mischievously* Your place? Oh, I like where this is going..."); } else if (sPerH === "experimental") { responses.push("*eyes light up* Your place? I've been wanting... let's just go."); } else if (sPerH === "physical") { responses.push("*pulls you close* Don't gotta tell me twice. Let's move."); } else { responses.push("*confident smile* Your place it is. I like the sound of that."); } } else if (topic === "whatsNew") { /* Dynamic response from getWhatsNewResponse */ var whatsNewResp = setup.getWhatsNewResponse(npc); if (whatsNewResp) { responses.push(whatsNewResp); } } /* Default fallback */ if (responses.length === 0) { if (npc.mentalTraits.includes("Thoughtful") || npc.mentalTraits.includes("Analytical")) { responses.push("Hmm, interesting question. I'll have to think about that for a while."); } else if (npc.mentalTraits.includes("Nonchalant")) { responses.push("Sure, whatever."); } else { responses.push("Hmm, interesting. I'll have to think about that."); } } var chosenResponse = setup.pickWithoutRepeat(responses, npc.name, "responses"); var memMod = setup.getMemoryResponseModifier ? setup.getMemoryResponseModifier(npc.name, topic, relLevel) : null; if (memMod) { chosenResponse = (memMod.prefix || "") + chosenResponse + (memMod.suffix || ""); } /* Proactive social reference (15% chance, skip for social and romance topics) */ var socialTopics = ["askAboutNPC", "positiveGossip", "negativeGossip", "introduceNPCs", "takeSides", "mendRelationship", "romanticNudge"]; var romanceTopics = ["confessFeelings", "holdHands", "kissNPC", "romanticDate", "askExclusive", "makeOutNPC", "initiateIntimacy", "pillowTalk", "deeperBond", "inviteHomeRomantic", "endThings"]; var homeTopics = ["inviteHomeFriend", "inviteHomeRomantic"]; if (socialTopics.indexOf(topic) === -1 && romanceTopics.indexOf(topic) === -1 && setup.npcSocial && setup.npcSocial.getProactiveSocialReference) { chosenResponse = chosenResponse + setup.npcSocial.getProactiveSocialReference(npc.name); } /* Apply speech flavor as the final wrapper */ var speechFlavor = setup.getSpeechFlavor(npc); return speechFlavor.prefix + setup.getMoodTonedResponse(chosenResponse, npc) + speechFlavor.suffix; }>> /* ====================================================================== */ /* ROISIN POSSESSION RECOGNITION */ /* While the player is bound to the artifact, NPCs sometimes reflect that */ /* "Roisin" is acting a little off, or react warmly to her by name. */ /* Revna McKraken (her closest friend) gets specific recognition lines. */ /* ====================================================================== */ <<set setup.roisinNPCRecognition = { /* Per-NPC recognition lines. Pulled with high probability when the */ /* named NPC is present. */ perNPC: { "Revna McKraken": [ "*tilts head* You alright, Roise? You're being weird with the words today.", "*narrows eyes* Christ, Roise, where's your head at? You sound off.", "*half-smiles* What's got into you. You're being soft with me. I do not hate it.", "*pokes your shoulder* Roise. Hello. Did you forget how you talk?" ], "Marcus Carter": [ "*smiles* Officer Sullivan. You're in a mood today, eh?", "Hey Roisin, you sound different. Good different." ], "Elena Romero": [ "*looks you over* Roisin. Hi. Did you do something? You feel different.", "*grins* Look at you, Roise. Walking around like you own the place. More than usual, I mean." ] }, /* Generic recognition lines used when a non-special NPC notices something */ /* off. Used on a low chance roll. */ generic: [ "*half-laughs* Roisin, you're being weird. Good weird. Whatever.", "*pauses* You sound like someone else half the time, Sullivan. Cute.", "*tilts head* Roisin, you're acting a little off today. You alright?", "*looks twice* Officer Sullivan. You're in a mood." ] }>> /* Wrap setup.getNPCResponse so possession sometimes prepends recognition. */ <<set setup.roisinOriginalGetNPCResponse = setup.getNPCResponse>> <<set setup.getNPCResponse = function(npc, topic, relLevel) { var v = State.variables; var base = setup.roisinOriginalGetNPCResponse(npc, topic, relLevel); if (!v.possessionActive) return base; if (!setup.roisinNPCRecognition) return base; /* Per-NPC line: 35% chance per response */ var perNPC = setup.roisinNPCRecognition.perNPC[npc.name]; if (perNPC && perNPC.length && Math.random() < 0.35) { var line = perNPC[Math.floor(Math.random() * perNPC.length)]; return line + " " + base; } /* Generic recognition for other NPCs: 12% chance */ if (Math.random() < 0.12 && setup.roisinNPCRecognition.generic.length) { var gline = setup.roisinNPCRecognition.generic[Math.floor(Math.random() * setup.roisinNPCRecognition.generic.length)]; return gline + " " + base; } return base; }>> <<set setup.calculateTalkRelationshipChange = function(npc, topic, relLevel) { var change = 0; }>> /* Function to add relationship bonus from trading */ <<set setup.addTradeRelationshipBonus = function(npc, playerPackage, npcPackage) { var v = State.variables; var prefs = setup.getNPCPreferences(npc); if (!prefs) { return 0; } var pointsGain = 0; /* Check if player gave desired traits (+5 points per desired item) */ if (prefs.desires) { if (prefs.desires.skills && playerPackage.skills) { playerPackage.skills.forEach(function(skill) { if (prefs.desires.skills.includes(skill)) { pointsGain += 5; } }); } if (prefs.desires.mental && playerPackage.mental) { playerPackage.mental.forEach(function(trait) { if (prefs.desires.mental.includes(trait)) { pointsGain += 5; } }); } if (prefs.desires.physical && playerPackage.physical) { playerPackage.physical.forEach(function(trait) { if (prefs.desires.physical.includes(trait)) { pointsGain += 5; } }); } if (prefs.desires.bodyParts && playerPackage.bodyParts) { playerPackage.bodyParts.forEach(function(part) { if (prefs.desires.bodyParts.includes(part.name)) { pointsGain += 5; } }); } } /* Check if player took reluctant traits (-1 point per reluctant item) */ if (prefs.reluctantToTrade && npcPackage) { if (prefs.reluctantToTrade.skills && npcPackage.skills) { npcPackage.skills.forEach(function(skill) { if (prefs.reluctantToTrade.skills.includes(skill)) { pointsGain -= 1; } }); } if (prefs.reluctantToTrade.mental && npcPackage.mental) { npcPackage.mental.forEach(function(trait) { if (prefs.reluctantToTrade.mental.includes(trait)) { pointsGain -= 1; } }); } if (prefs.reluctantToTrade.physical && npcPackage.physical) { npcPackage.physical.forEach(function(trait) { if (prefs.reluctantToTrade.physical.includes(trait)) { pointsGain -= 1; } }); } if (prefs.reluctantToTrade.bodyParts && npcPackage.bodyParts) { npcPackage.bodyParts.forEach(function(part) { if (prefs.reluctantToTrade.bodyParts.includes(part.name)) { pointsGain -= 1; } }); } } return pointsGain; }>> <<set setup.calculateTalkRelationshipChange = function(npc, topic, relLevel) { var change = 0; if (topic === "compliment") { /* Compliments - modified by personality */ if (npc.mentalTraits.includes("Insecure") || npc.mentalTraits.includes("Shy")) { change = relLevel >= 3 ? 3 : 2; /* Extra impact on insecure people (Friend+) */ } else if (npc.mentalTraits.includes("Arrogant") || npc.mentalTraits.includes("Vain")) { change = 1; /* They expect compliments */ } else { change = relLevel >= 3 ? 2 : 1; /* Friend+ */ } } else if (topic === "insult") { /* Insults - personality determines severity */ if (npc.mentalTraits.includes("Sensitive") || npc.mentalTraits.includes("Insecure")) { change = relLevel === 1 ? -5 : (relLevel === 2 ? -4 : -2); /* Stranger, Acquaintance, Friend+ */ } else if (npc.mentalTraits.includes("Confident") || npc.mentalTraits.includes("Arrogant")) { change = relLevel === 1 ? -2 : (relLevel === 2 ? -1 : -1); /* Less impact if confident */ } else if (npc.mentalTraits.includes("Aggressive") || npc.mentalTraits.includes("Short Tempered")) { change = -4; /* They don't forgive easily */ } else { change = relLevel === 1 ? -3 : (relLevel === 2 ? -2 : -1); } } else if (topic === "opinion") { /* Asking opinion - modified by personality */ if (npc.mentalTraits.includes("Arrogant") || npc.mentalTraits.includes("Vain")) { change = relLevel === 1 ? 2 : 1; /* They LOVE talking about themselves at Stranger level */ } else if (npc.mentalTraits.includes("Shy")) { change = relLevel === 1 ? 0 : 1; /* Uncomfortable at Stranger level */ } else { change = relLevel === 1 ? 1 : 0; /* Stranger gives +1, higher levels give 0 */ } } else if (topic === "trading") { /* Trading interest - modified by personality */ if (npc.mentalTraits.includes("Greedy") || npc.mentalTraits.includes("Shrewd")) { change = 1; /* They like business talk */ } else if (npc.mentalTraits.includes("Generous")) { change = relLevel === 1 ? 1 : 0; /* Stranger gives +1 */ } else { change = relLevel === 1 ? 1 : 0; /* Stranger gives +1 */ } } else if (topic === "smalltalk") { /* Small talk - personality heavily influences */ if (npc.mentalTraits.includes("Talkative") || npc.mentalTraits.includes("Friendly")) { change = 1; /* They enjoy it */ } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Impatient")) { change = -1; /* They hate it */ } else { change = 0; /* Neutral */ } } else if (topic === "job") { /* Job talk doesn't change relationship */ change = 0; } else { /* Default fallback for unknown topics */ change = 0; } return change; }>> /* Function to add relationship bonus from trading */ <<set setup.addTradeRelationshipBonus = function(npc, playerPackage, npcPackage) { var v = State.variables; var prefs = setup.getNPCPreferences(npc); if (!prefs) { return 0; } var pointsGain = 0; /* Check if player gave desired traits (+5 points per desired item) */ if (prefs.desires) { if (prefs.desires.skills && playerPackage.skills) { playerPackage.skills.forEach(function(skill) { if (prefs.desires.skills.includes(skill)) { pointsGain += 5; } }); } if (prefs.desires.mental && playerPackage.mental) { playerPackage.mental.forEach(function(trait) { if (prefs.desires.mental.includes(trait)) { pointsGain += 5; } }); } if (prefs.desires.physical && playerPackage.physical) { playerPackage.physical.forEach(function(trait) { if (prefs.desires.physical.includes(trait)) { pointsGain += 5; } }); } if (prefs.desires.bodyParts && playerPackage.bodyParts) { playerPackage.bodyParts.forEach(function(part) { if (prefs.desires.bodyParts.includes(part.name)) { pointsGain += 5; } }); } } /* Check if player took reluctant traits (-1 point per reluctant item) */ if (prefs.reluctantToTrade && npcPackage) { if (prefs.reluctantToTrade.skills && npcPackage.skills) { npcPackage.skills.forEach(function(skill) { if (prefs.reluctantToTrade.skills.includes(skill)) { pointsGain -= 1; } }); } if (prefs.reluctantToTrade.mental && npcPackage.mental) { npcPackage.mental.forEach(function(trait) { if (prefs.reluctantToTrade.mental.includes(trait)) { pointsGain -= 1; } }); } if (prefs.reluctantToTrade.physical && npcPackage.physical) { npcPackage.physical.forEach(function(trait) { if (prefs.reluctantToTrade.physical.includes(trait)) { pointsGain -= 1; } }); } if (prefs.reluctantToTrade.bodyParts && npcPackage.bodyParts) { npcPackage.bodyParts.forEach(function(part) { if (prefs.reluctantToTrade.bodyParts.includes(part.name)) { pointsGain -= 1; } }); } } return pointsGain; }>>
/* ---------------------------------- */ /* --- JOB WORK BONUS/PENALTY SYSTEM --- */ /* ---------------------------------- */ <<set setup.jobWorkConfig = { "Fitness Shop Clerk": { statRequirement: {stat: "strength", value: 25}, possibleGains: ["Fit", "Confident", "Patient", "Sales", "Retail", "Chill"], bonuses: { small: ["Fit", "Flexible", "Broad-shouldered", "Sturdy", "Tall", "Optimistic", "Patient", "Sales", "Werewolf", "Cerberus"], medium: ["Attractive", "Athletic Build", "Extroverted", "Heavy Lifting", "Athletics", "Yoga"], big: ["Muscular", "Friendly", "Outgoing", "Energetic", "Chill"] }, negativeRemovable: ["Ugly", "Overweight", "Underweight", "Weak", "Soft"], negativeReplacements: { "Overweight": "Fit", "Underweight": "Fit", "Weak": "Strong" }, traitUpgrades: { "Strong": "Muscular" }, negativePermanent: ["Messy Hair"] }, "Adult Store Clerk": { statRequirement: {stat: "charisma", value: 20}, possibleGains: ["Patient", "Sales", "Retail", "Chill"], bonuses: { small: ["Optimistic", "Patient", "Outgoing", "Energetic", "Accounting"], medium: ["Attractive", "Creative", "Huge Chest", "Curvy", "Voluptuous", "Huge Butt", "Giant Butt"], big: ["Friendly", "Sexually Skilled", "Sales", "Giant Chest", "Chill"] }, negativeRemovable: ["Ugly"], negativeReplacements: {}, traitUpgrades: {}, negativePermanent: ["Messy Hair"] }, "Ecentric Shop Worker": { statRequirement: {stat: "charisma", value: 20}, possibleGains: ["Patient", "Sales", "Sarcastic", "Artistic", "Retail", "Chill", "Humorous"], bonuses: { small: ["Dominant", "Creative", "Patient", "Accounting", "Deep Thinker", "Sarcastic", "Humorous", "Black Hair"], medium: ["Attractive", "Optimistic", "Honest", "Pierced", "Artistic", "Relaxed"], big: ["Introverted", "Pessimistic", "Sales", "Monotone Expression", "Retail", "Chill"] }, negativeRemovable: ["Ugly"], negativeReplacements: {}, traitUpgrades: { "Relaxed": "Chill" }, negativePermanent: ["Messy Hair"] }, "Dock Worker": { statRequirement: {stat: "strength", value: 15}, possibleGains: ["Patient", "Forklift Certified", "Relaxed", "Humorous"], bonuses: { small: ["Friendly", "Outgoing", "Energetic", "Relaxed"], medium: ["Attractive", "Optimistic", "Patient", "Honest", "Chill", "Humorous"], big: ["Hardworking", "Muscular", "Forklift Certified"] }, negativeRemovable: ["Ugly", "Impatient"], negativeReplacements: { "Impatient": "Patient" }, traitUpgrades: { "Relaxed": "Chill" }, negativePermanent: [] }, "Tech Store Clerk": { statRequirement: {stat: "intelligence", value: 20}, possibleGains: ["Confident", "Patient", "Intelligent", "Analytical", "Persuasion", "Sales", "Tech-Savvy", "Troubleshooting"], bonuses: { small: ["Outgoing", "Introverted", "Deep Thinker"], medium: ["Attractive", "Optimistic", "Creative", "Patient", "Persuasion", "Sales", "Accounting", "Retail"], big: ["Friendly", "Logical", "Intelligent", "Analytical", "Tech-Savvy", "Troubleshooting"] }, negativeRemovable: ["Ugly"], negativeReplacements: {}, traitUpgrades: {}, negativePermanent: ["Messy Hair"] }, "Beauty Salon Stylist": { statRequirement: {stat: "dexterity", value: 30}, possibleGains: ["Confident", "Optimistic", "Patient", "Outgoing", "Makeup", "Hair Styling", "Cleaning"], bonuses: { small: ["Hardworking", "Creative", "Energetic", "Cleaning", "Retail"], medium: ["Attractive", "Optimistic", "Makeup"], big: ["Extroverted", "Friendly", "Patient", "Outgoing", "Hair Styling"] }, negativeRemovable: ["Ugly"], negativeReplacements: {}, traitUpgrades: {}, negativePermanent: ["Messy Hair"] }, "Construction Worker": { statRequirement: {stat: "strength", value: 20}, possibleGains: ["Fit", "Patient", "Hardworking", "Heavy Lifting"], bonuses: { small: ["Fit", "Broad-shouldered", "Tall", "Patient", "Energetic", "Hardworking"], medium: ["Athletic Build", "Strong", "Sturdy", "Heavy Lifting"], big: ["Muscular", "Forklift Certified"] }, negativeRemovable: ["Weak", "Soft", "Underweight"], negativeReplacements: { "Weak": "Strong", "Underweight": "Fit" }, traitUpgrades: { "Strong": "Muscular", "Fit": "Athletic Build" }, negativePermanent: [] }, "Bus Driver": { statRequirement: {stat: "dexterity", value: 20}, possibleGains: ["Patient", "Calm", "Kind", "Confident", "Flirty", "Driving", "Navigation", "Customer Service", "Mechanical Repair", "Observant"], bonuses: { small: ["Patient", "Calm", "Kind", "Navigation", "Confident", "Mechanical Repair"], medium: ["Customer Service", "Observant", "Charming", "Attractive"], big: ["Driving", "Flirty", "Seductive"] }, negativeRemovable: ["Impatient", "Reckless"], negativeReplacements: { "Impatient": "Patient" }, traitUpgrades: { "Patient": "Calm" }, negativePermanent: ["Clumsy"] }, "Donuts Deliverer": { statRequirement: {stat: "dexterity", value: 15}, possibleGains: ["Quick", "Energetic", "Driving", "Customer Service", "Hardworking", "Fit"], bonuses: { small: ["Quick", "Energetic", "Customer Service"], medium: ["Hardworking", "Navigation"], big: ["Driving"] }, negativeRemovable: ["Lazy", "Slow"], negativeReplacements: { "Lazy": "Hardworking", "Slow": "Quick" }, traitUpgrades: { "Quick": "Energetic" }, negativePermanent: ["Clumsy"] }, "Cocktail Waitress": { statRequirement: {stat: "charisma", value: 25}, possibleGains: ["Charming", "Graceful", "Serving", "Customer Service", "Flirty", "Persuasion", "Quick"], bonuses: { small: ["Charming", "Flirty", "High Heels Proficient"], medium: ["Customer Service", "Attractive"], big: ["Serving"] }, negativeRemovable: ["Clumsy", "Shy"], negativeReplacements: { "Shy": "Charming" }, traitUpgrades: { "Charming": "Flirty" }, negativePermanent: ["Impatient"] }, "Fitness Trainer": { statRequirement: {stat: "strength", value: 40}, possibleGains: ["Athletic Build", "Fit", "Energetic", "Patient", "Coaching", "Hardworking", "Strong", "Muscular", "Kind", "Dominant", "Confident", "Humorous", "Competitive", "Flirty", "Aggressive", "Athletics", "Combat"], bonuses: { small: ["Athletic Build", "Energetic", "Patient", "Kind", "Humorous", "Competitive"], medium: ["Strong", "Fit", "Confident", "Dominant", "Athletics"], big: ["Muscular", "Coaching", "Flirty", "Aggressive", "Combat"] }, negativeRemovable: ["Lazy", "Weak"], negativeReplacements: { "Lazy": "Hardworking", "Weak": "Strong" }, traitUpgrades: { "Fit": "Athletic Build", "Strong": "Muscular" }, negativePermanent: ["Clumsy"] }, "Street Performer": { statRequirement: {stat: "charisma", value: 20}, possibleGains: ["Performer", "Creative", "Entertainer", "Outgoing", "Confident", "Showmanship"], bonuses: { small: ["Charismatic", "Creative", "Entertaining"], medium: ["Outgoing", "Confident"], big: ["Performer"] }, negativeRemovable: ["Shy", "Boring"], negativeReplacements: { "Shy": "Outgoing" }, traitUpgrades: { "Outgoing": "Confident" }, negativePermanent: ["Stage Fright"] }, "Musician": { statRequirement: {stat: "charisma", value: 25}, possibleGains: ["Musical", "Performer", "Creative", "Confident", "Showmanship", "Charming"], bonuses: { small: ["Charming", "Creative"], medium: ["Performer", "Confident"], big: ["Musical"] }, negativeRemovable: ["Shy", "Tone Deaf"], negativeReplacements: { "Shy": "Confident" }, traitUpgrades: { "Creative": "Artistic" }, negativePermanent: ["Stage Fright"] }, "Dancing Instructor": { statRequirement: {stat: "dexterity", value: 40}, possibleGains: ["Graceful", "Flexible", "Dancing", "Patient", "Artistic", "Confident", "Charming"], bonuses: { small: ["Patient", "Charming"], medium: ["Flexible", "Artistic"], big: ["Graceful", "Dancing"] }, negativeRemovable: ["Clumsy", "Stiff"], negativeReplacements: { "Clumsy": "Graceful" }, traitUpgrades: { "Flexible": "Graceful" }, negativePermanent: ["Two Left Feet"] }, "Social Media Influencer": { statRequirement: {stat: "charisma", value: 20}, possibleGains: ["Social Media", "Photography", "Creative", "Trendy", "Fashionable", "Charming"], bonuses: { small: ["Charming", "Trendy"], medium: ["Photography", "Creative"], big: ["Social Media"] }, negativeRemovable: ["Shy", "Technophobe"], negativeReplacements: { "Shy": "Outgoing" }, traitUpgrades: { "Trendy": "Fashionable" }, negativePermanent: ["Camera Shy"] }, "Black Market Dealer": { statRequirement: {stat: "charisma", value: 25}, possibleGains: ["Streetwise", "Persuasion", "Analytical", "Sly", "Shrewd", "Risk-Taker"], bonuses: { small: ["Persuasion", "Analytical", "Sly"], medium: [], big: ["Streetwise"] }, negativeRemovable: ["Naive", "Timid"], negativeReplacements: { "Naive": "Streetwise" }, traitUpgrades: { "Sly": "Shrewd" }, negativePermanent: ["Cowardly"] }, "Negotiator": { statRequirement: {stat: "charisma", value: 30}, possibleGains: ["Persuasion", "Analytical", "Diplomatic", "Confident", "Patient", "Observant", "Shrewd"], bonuses: { small: ["Confident", "Patient"], medium: ["Analytical", "Diplomatic"], big: ["Persuasion"] }, negativeRemovable: ["Timid", "Impatient"], negativeReplacements: { "Timid": "Confident" }, traitUpgrades: { "Patient": "Diplomatic" }, negativePermanent: ["Dishonest"] }, "Model": { statRequirement: {stat: "charisma", value: 35}, possibleGains: ["Modeling", "Fashionable", "Graceful", "Photogenic", "Confident", "Poised", "Striking"], bonuses: { small: ["Confident", "Poised"], medium: ["Fashionable", "Graceful", "Photogenic", "Striking"], big: ["Modeling"] }, negativeRemovable: ["Shy", "Clumsy"], negativeReplacements: { "Shy": "Confident" }, traitUpgrades: { "Poised": "Graceful" }, negativePermanent: ["Unphotogenic"] }, "Porn Star": { statRequirement: {stat: "charisma", value: 30}, possibleGains: ["Sexually Skilled", "Exhibitionist", "Confident", "Seductive", "Acting", "Charming"], bonuses: { small: ["Acting", "Modeling", "Seductive", "Exhibitionist"], medium: ["Charming", "Confident"], big: ["Sexually Skilled"] }, negativeRemovable: ["Shy", "Prudish"], negativeReplacements: { "Shy": "Confident", "Prudish": "Exhibitionist" }, traitUpgrades: { "Charming": "Seductive" }, negativePermanent: ["Frigid"] }, "Prostitute": { statRequirement: {stat: "charisma", value: 15}, possibleGains: ["Sexually Skilled", "Seductive", "Streetwise", "Confident", "Observant", "Persuasion"], bonuses: { small: ["Charming", "Flirty", "Outgoing", "Attractive", "Persuasion"], medium: ["Seductive", "Sexually Skilled", "Streetwise", "Confident"], big: ["Insatiable", "Exhibitionist"] }, negativeRemovable: ["Shy", "Prudish", "Naive"], negativeReplacements: { "Shy": "Confident", "Prudish": "Exhibitionist", "Naive": "Streetwise" }, traitUpgrades: { "Charming": "Seductive", "Flirty": "Insatiable" }, negativePermanent: ["Frigid"] } }>> /* Helper function to check if player has any trait/skill */ <<set setup.playerHasTrait = function(traitName) { var v = State.variables; /* Check body parts for special cases */ if (traitName === "Black Hair") { return v.hairColor === "Black"; } if (traitName === "Messy Hair") { return v.hairLength === "Messy Hair"; } /* Check chest/butt sizes */ var sizeTraits = ["Huge Chest", "Giant Chest", "Huge Butt", "Giant Butt"]; if (sizeTraits.includes(traitName)) { var bodyPart = traitName.includes("Chest") ? "chest" : "butt"; var size = traitName.split(" ")[0].toLowerCase(); /* "huge" or "giant" */ return v[bodyPart] && v[bodyPart].toLowerCase() === size; } return v.physicalTraits.includes(traitName) || v.mentalTraits.includes(traitName) || v.skills.includes(traitName); }>> /* Calculate pay multiplier based on stat deficit */ <<set setup.getJobPayMultiplier = function(jobName) { var v = State.variables; var config = setup.jobWorkConfig[jobName]; if (!config || !config.statRequirement) { return 1.0; /* No penalty if job not in system */ } var requiredStat = config.statRequirement.stat; var requiredValue = config.statRequirement.value; var playerStat = setup.getTotalStat(requiredStat); /* Use total stat with bonuses */ /* If player meets or exceeds requirement, full pay (100%) */ if (playerStat >= requiredValue) { return 1.0; } /* Calculate how far below the requirement the player is */ /* Formula: (playerStat / requiredValue) gives us the percentage */ /* This naturally scales: */ /* - If you have 6/15 strength = 40% pay (60% penalty) */ /* - If you have 5/70 charisma = 7.14% pay (92.86% penalty) */ /* - If you have 0 stats = 0% pay (100% penalty) */ var multiplier = playerStat / requiredValue; /* Ensure minimum is 0 (can't go negative) */ if (multiplier < 0) multiplier = 0; return multiplier; }>> /* Calculate bonus pay from traits */ <<set setup.getJobBonusMultiplier = function(jobName) { var config = setup.jobWorkConfig[jobName]; if (!config) return 0; var bonusPercent = 0; /* Check small bonuses (2% each) */ for (var i = 0; i < config.bonuses.small.length; i++) { if (setup.playerHasTrait(config.bonuses.small[i])) { bonusPercent += 2; } } /* Check medium bonuses (5% each) */ for (var i = 0; i < config.bonuses.medium.length; i++) { if (setup.playerHasTrait(config.bonuses.medium[i])) { bonusPercent += 5; } } /* Check big bonuses (15% each) */ for (var i = 0; i < config.bonuses.big.length; i++) { if (setup.playerHasTrait(config.bonuses.big[i])) { bonusPercent += 15; } } return bonusPercent / 100; /* Convert to multiplier */ }>> /* Calculate penalty from negative traits */ <<set setup.getJobNegativePenalty = function(jobName) { var config = setup.jobWorkConfig[jobName]; if (!config) return 0; var penaltyPercent = 0; /* Check removable negatives (10% penalty each) */ for (var i = 0; i < config.negativeRemovable.length; i++) { if (setup.playerHasTrait(config.negativeRemovable[i])) { penaltyPercent += 10; } } /* Check permanent negatives (5% penalty each) */ for (var i = 0; i < config.negativePermanent.length; i++) { if (setup.playerHasTrait(config.negativePermanent[i])) { penaltyPercent += 5; } } return penaltyPercent / 100; /* Convert to multiplier */ }>> /* Process trait gains/losses/upgrades after work */ <<set setup.processJobTraitChanges = function(jobName) { var v = State.variables; var config = setup.jobWorkConfig[jobName]; if (!config) return []; var changes = []; /* 5% chance to gain a new trait from possibleGains */ if (Math.random() < 0.05) { var availableGains = config.possibleGains.filter(function(trait) { return !setup.playerHasTrait(trait); }); if (availableGains.length > 0) { var newTrait = availableGains[Math.floor(Math.random() * availableGains.length)]; /* Determine where to add it using canonical trait lookups */ if (setup.availablePhysicalTraits && setup.availablePhysicalTraits[newTrait]) { v.physicalTraits.push(newTrait); } else if (setup.availableMentalTraits && setup.availableMentalTraits[newTrait]) { v.mentalTraits.push(newTrait); } else if (setup.availableVoiceTraits && setup.availableVoiceTraits[newTrait]) { v.voiceTraits.push(newTrait); } else if (setup.skillBonuses && setup.skillBonuses[newTrait]) { v.skills.push(newTrait); } else if (setup.traitBonuses && setup.traitBonuses[newTrait]) { v.mentalTraits.push(newTrait); } else { v.skills.push(newTrait); } changes.push({type: "gain", trait: newTrait}); } } /* 1% chance to upgrade existing traits */ if (Math.random() < 0.01) { var eligibleUpgrades = []; for (var oldTrait in config.traitUpgrades) { if (setup.playerHasTrait(oldTrait) && !setup.playerHasTrait(config.traitUpgrades[oldTrait])) { eligibleUpgrades.push(oldTrait); } } if (eligibleUpgrades.length > 0) { var oldTrait = eligibleUpgrades[Math.floor(Math.random() * eligibleUpgrades.length)]; var newTrait = config.traitUpgrades[oldTrait]; /* Remove old trait */ v.physicalTraits = v.physicalTraits.filter(function(t) { return t !== oldTrait; }); v.mentalTraits = v.mentalTraits.filter(function(t) { return t !== oldTrait; }); v.skills = v.skills.filter(function(t) { return t !== oldTrait; }); /* Add new trait using canonical lookups */ if (setup.availablePhysicalTraits && setup.availablePhysicalTraits[newTrait]) { v.physicalTraits.push(newTrait); } else if (setup.availableMentalTraits && setup.availableMentalTraits[newTrait]) { v.mentalTraits.push(newTrait); } else if (setup.availableVoiceTraits && setup.availableVoiceTraits[newTrait]) { v.voiceTraits.push(newTrait); } else if (setup.skillBonuses && setup.skillBonuses[newTrait]) { v.skills.push(newTrait); } else if (setup.traitBonuses && setup.traitBonuses[newTrait]) { v.mentalTraits.push(newTrait); } else { v.skills.push(newTrait); } changes.push({type: "upgrade", oldTrait: oldTrait, newTrait: newTrait}); } } /* 5% chance to remove a negative trait */ if (Math.random() < 0.05) { var removableNegatives = config.negativeRemovable.filter(function(trait) { return setup.playerHasTrait(trait); }); if (removableNegatives.length > 0) { var traitToRemove = removableNegatives[Math.floor(Math.random() * removableNegatives.length)]; v.physicalTraits = v.physicalTraits.filter(function(t) { return t !== traitToRemove; }); v.mentalTraits = v.mentalTraits.filter(function(t) { return t !== traitToRemove; }); changes.push({type: "remove", trait: traitToRemove}); } } /* 1% chance to replace negative trait with positive */ if (Math.random() < 0.01) { for (var negativeTrait in config.negativeReplacements) { if (setup.playerHasTrait(negativeTrait)) { var positiveTrait = config.negativeReplacements[negativeTrait]; /* Remove negative */ v.physicalTraits = v.physicalTraits.filter(function(t) { return t !== negativeTrait; }); v.mentalTraits = v.mentalTraits.filter(function(t) { return t !== negativeTrait; }); /* Add positive using canonical lookups */ if (setup.availablePhysicalTraits && setup.availablePhysicalTraits[positiveTrait]) { v.physicalTraits.push(positiveTrait); } else if (setup.availableMentalTraits && setup.availableMentalTraits[positiveTrait]) { v.mentalTraits.push(positiveTrait); } else if (setup.availableVoiceTraits && setup.availableVoiceTraits[positiveTrait]) { v.voiceTraits.push(positiveTrait); } else if (setup.skillBonuses && setup.skillBonuses[positiveTrait]) { v.skills.push(positiveTrait); } else if (setup.traitBonuses && setup.traitBonuses[positiveTrait]) { v.mentalTraits.push(positiveTrait); } else { v.skills.push(positiveTrait); } changes.push({type: "replace", oldTrait: negativeTrait, newTrait: positiveTrait}); break; /* Only one replacement per work session */ } } } return changes; }>>
/* ================================== */ /* === LAMPREY TOMES BOOKSHOP === */ /* ================================== */ <<set setup.lampreyTraits = { common: { price: 500, chance: 0.90, traits: [ {trait: "Broad-shouldered", type: "physical"}, {trait: "Freckled", type: "physical"}, {trait: "Tattooed", type: "physical"}, {trait: "Risk Taker", type: "mental"}, {trait: "Overthinker", type: "mental"}, {trait: "Quiet", type: "mental"}, {trait: "Clingy", type: "mental"}, {trait: "Impulsive", type: "mental"}, {trait: "Disorganized", type: "mental"}, {trait: "Forgetful", type: "mental"}, {trait: "Cowardly", type: "mental"}, {trait: "Insecure", type: "mental"}, {trait: "Brave", type: "mental"}, {trait: "Witty", type: "mental"}, {trait: "Passive", type: "mental"}, {trait: "Stubborn", type: "mental"}, {trait: "Paranoid", type: "mental"}, {trait: "Bitchy", type: "mental"}, {trait: "Foolish", type: "mental"}, {trait: "Flat Chest", type: "physical"}, {trait: "Flat Butt", type: "physical"}, {trait: "Flat Masculine Chest", type: "physical"}, {trait: "Flat Masculine Butt", type: "physical"} ] }, uncommon: { price: 2000, chance: 0.20, traits: [ {trait: "Submissive", type: "mental"}, {trait: "Sturdy", type: "physical"}, {trait: "Artistic", type: "mental"}, {trait: "Small Chest", type: "physical"}, {trait: "Small Butt", type: "physical"}, {trait: "Combat Training", type: "skill"}, {trait: "Business", type: "skill"}, {trait: "Social Skills", type: "skill"}, {trait: "Perceptive", type: "mental"} ] }, rare: { price: 5000, chance: 0.05, traits: [ {trait: "Youthful", type: "physical"}, {trait: "Attractive", type: "physical"}, {trait: "Sly", type: "mental"}, {trait: "Curvy", type: "physical"}, {trait: "Voluptuous", type: "physical"}, {trait: "Large Chest", type: "physical"}, {trait: "Large Butt", type: "physical"}, {trait: "Medium Chest", type: "physical"}, {trait: "Medium Butt", type: "physical"}, {trait: "Lactating", type: "physical"} ] }, aethereal: { price: 10000, chance: 0.01, traits: [ {trait: "Giant Chest", type: "physical"}, {trait: "Giant Butt", type: "physical"}, {trait: "Huge Chest", type: "physical"}, {trait: "Huge Butt", type: "physical"}, {trait: "Goth", type: "mental"}, {trait: "Nerd", type: "mental"}, {trait: "Jock", type: "mental"}, {trait: "Prep", type: "mental"}, {trait: "Dominant", type: "mental"} ] }, legendary: { price: 50000, chance: 0.001, traits: [ {trait: "Were-Creature", type: "physical"}, {trait: "Lucky", type: "mental"}, {trait: "Unlucky", type: "mental"}, {trait: "Occult Expert", type: "skill"}, {trait: "Gigantic Chest", type: "physical"}, {trait: "Gigantic Butt", type: "physical"} ] } }>> /* ===== INVENTORY GENERATION ===== */ <<set setup.generateLampreyInventory = function() { var inventory = []; /* Guaranteed common tome */ var guaranteedCommon = setup.lampreyTraits.common.traits.random(); inventory.push({ trait: guaranteedCommon.trait, type: guaranteedCommon.type, rarity: 'common', price: setup.lampreyTraits.common.price }); /* Base number of additional tomes */ var additionalTomes = 3; /* ===== SKILL TREE: Daily Tome Bonus ===== */ var skillTreeTomeBonus = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { skillTreeTomeBonus = setup.skillTree.getEffect("dailyTomeBonus") || 0; } if (skillTreeTomeBonus > 0) { additionalTomes += skillTreeTomeBonus; } /* Revna's favor scales the legendary/aethereal/rare thresholds proportionally, so the combined rare-or-rarer band widens by exactly revnaRareBoost. The uncommon band is shifted up by the same boost so its width is preserved and the donor is the common tier. Relative ratios between rarer tiers stay. */ var revnaRareBoost = (typeof setup.getLampreyRevnaRareBoost === "function") ? setup.getLampreyRevnaRareBoost() : 0; var rareScale = (revnaRareBoost > 0 && setup.lampreyTraits.rare.chance > 0) ? 1 + revnaRareBoost / setup.lampreyTraits.rare.chance : 1; var legendaryThresh = setup.lampreyTraits.legendary.chance * rareScale; var aetherealThresh = setup.lampreyTraits.aethereal.chance * rareScale; var rareThresh = setup.lampreyTraits.rare.chance * rareScale; var uncommonThresh = setup.lampreyTraits.uncommon.chance + revnaRareBoost; for (var i = 0; i < additionalTomes; i++) { var selectedRarity = null; var roll = Math.random(); if (roll < legendaryThresh) { selectedRarity = 'legendary'; } else if (roll < aetherealThresh) { selectedRarity = 'aethereal'; } else if (roll < rareThresh) { selectedRarity = 'rare'; } else if (roll < uncommonThresh) { selectedRarity = 'uncommon'; } else { selectedRarity = 'common'; } var rarityData = setup.lampreyTraits[selectedRarity]; var traitData = rarityData.traits.random(); if (!inventory.some(function(item) { return item.trait === traitData.trait; })) { inventory.push({ trait: traitData.trait, type: traitData.type, rarity: selectedRarity, price: rarityData.price }); } else { i--; } } return inventory; }>> /* ===== INVENTORY REFRESH CHECK ===== */ <<set setup.shouldRefreshLampreyInventory = function() { var v = State.variables; var currentDay = v.dayNumber; var lastRefreshDay = v.lampreyLastRefreshDay || -1; var lastRefreshWasAfterNoon = v.lampreyLastRefreshAfterNoon || false; var currentHour = Math.floor(v.timeInMinutes / 60) % 24; var isAfterNoon = currentHour >= 12; /* Refresh if more than 1 day has passed (at least one noon has definitely occurred) */ if (currentDay > lastRefreshDay + 1) { return true; } /* Refresh if it's a new day and we're at or past noon */ if (currentDay > lastRefreshDay && isAfterNoon) { return true; } /* Refresh if it's the same day but last refresh was before noon and now it's noon or later */ if (currentDay === lastRefreshDay && !lastRefreshWasAfterNoon && isAfterNoon) { return true; } /* Also refresh if skill tree tome bonus changed since last generation */ var currentBonus = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { currentBonus = setup.skillTree.getEffect("dailyTomeBonus") || 0; } var lastBonus = v.lampreyLastTomeBonus; if (typeof lastBonus === "undefined" || currentBonus !== lastBonus) { return true; } /* Also refresh if Revna's relationship-based rare boost changed */ var currentRevnaBoost = (typeof setup.getLampreyRevnaRareBoost === "function") ? setup.getLampreyRevnaRareBoost() : 0; var lastRevnaBoost = v.lampreyLastRevnaBoost; if (typeof lastRevnaBoost === "undefined" || currentRevnaBoost !== lastRevnaBoost) { return true; } return false; }>> /* ===== RARITY HELPERS ===== */ <<set setup.getRarityColor = function(rarity) { var colors = { common: '#aaa', uncommon: '#51cf66', rare: '#339af0', aethereal: '#b19cd9', legendary: '#ffd700' }; return colors[rarity] || '#aaa'; }>> <<set setup.getRarityName = function(rarity) { var names = { common: 'Common', uncommon: 'Uncommon', rare: 'Rare', aethereal: 'Aethereal', legendary: 'Legendary' }; return names[rarity] || 'Unknown'; }>> /* ===== BODY PART TRAIT APPLICATION ===== */ <<set setup.applyLampreyBodyTrait = function(trait) { var v = State.variables; /* Handle chest size traits */ if (trait === "Gigantic Chest") { v.bodyParts.chest = "gigantic"; return true; } if (trait === "Giant Chest") { v.bodyParts.chest = "giant"; return true; } if (trait === "Huge Chest") { v.bodyParts.chest = "huge"; return true; } if (trait === "Large Chest") { v.bodyParts.chest = "large"; return true; } if (trait === "Medium Chest") { v.bodyParts.chest = "medium"; return true; } if (trait === "Small Chest") { v.bodyParts.chest = "small"; return true; } if (trait === "Flat Chest") { v.bodyParts.chest = "flat"; return true; } if (trait === "Flat Masculine Chest") { v.bodyParts.chest = "flat masculine"; return true; } /* Handle butt size traits */ if (trait === "Gigantic Butt") { v.bodyParts.butt = "gigantic"; return true; } if (trait === "Giant Butt") { v.bodyParts.butt = "giant"; return true; } if (trait === "Huge Butt") { v.bodyParts.butt = "huge"; return true; } if (trait === "Large Butt") { v.bodyParts.butt = "large"; return true; } if (trait === "Medium Butt") { v.bodyParts.butt = "medium"; return true; } if (trait === "Small Butt") { v.bodyParts.butt = "small"; return true; } if (trait === "Flat Butt") { v.bodyParts.butt = "flat"; return true; } if (trait === "Flat Masculine Butt") { v.bodyParts.butt = "flat masculine"; return true; } return false; }>> /* ===== CHECK IF PLAYER HAS TRAIT ===== */ <<set setup.hasLampreyTrait = function(trait) { var v = State.variables; /* Check chest size traits - only allow if it would change current value */ if (trait === "Gigantic Chest") { return v.bodyParts.chest === "gigantic"; } if (trait === "Giant Chest") { return v.bodyParts.chest === "giant"; } if (trait === "Huge Chest") { return v.bodyParts.chest === "huge"; } if (trait === "Large Chest") { return v.bodyParts.chest === "large"; } if (trait === "Medium Chest") { return v.bodyParts.chest === "medium"; } if (trait === "Small Chest") { return v.bodyParts.chest === "small"; } if (trait === "Flat Chest") { return v.bodyParts.chest === "flat"; } if (trait === "Flat Masculine Chest") { return v.bodyParts.chest === "flat masculine"; } /* Check butt size traits - only allow if it would change current value */ if (trait === "Gigantic Butt") { return v.bodyParts.butt === "gigantic"; } if (trait === "Giant Butt") { return v.bodyParts.butt === "giant"; } if (trait === "Huge Butt") { return v.bodyParts.butt === "huge"; } if (trait === "Large Butt") { return v.bodyParts.butt === "large"; } if (trait === "Medium Butt") { return v.bodyParts.butt === "medium"; } if (trait === "Small Butt") { return v.bodyParts.butt === "small"; } if (trait === "Flat Butt") { return v.bodyParts.butt === "flat"; } if (trait === "Flat Masculine Butt") { return v.bodyParts.butt === "flat masculine"; } /* Check physical traits array */ if (v.physicalTraits && v.physicalTraits.includes(trait)) { return true; } /* Check mental traits array */ if (v.mentalTraits && v.mentalTraits.includes(trait)) { return true; } /* Check skills array */ if (v.skills && v.skills.includes(trait)) { return true; } /* Check voice traits array */ if (v.voiceTraits && v.voiceTraits.includes(trait)) { return true; } return false; }>> /* ===== ADD TRAIT TO PLAYER ===== */ <<set setup.addLampreyTrait = function(trait, type) { var v = State.variables; /* Check if trait is blocked by current transformation */ if (setup.isTraitBlockedByTransformation) { if (setup.isTraitBlockedByTransformation(trait, "physical") || setup.isTraitBlockedByTransformation(trait, "mental")) { return; /* Trait is blocked by transformation, don't add */ } } /* Check if it's a body part modification trait */ if (setup.applyLampreyBodyTrait(trait)) { return; /* Body part was modified, no need to add to trait arrays */ } /* Handle conflicts for regular traits */ var allTraits = v.physicalTraits.concat(v.mentalTraits).concat(v.skills); if (v.voiceTraits) allTraits = allTraits.concat(v.voiceTraits); var conflict = setup.getConflictingTrait(trait, allTraits); if (conflict) { /* Remove conflicting trait */ v.physicalTraits.delete(conflict); v.mentalTraits.delete(conflict); v.skills.delete(conflict); if (v.voiceTraits) v.voiceTraits.delete(conflict); } /* Add the new trait */ if (type === "physical") { v.physicalTraits.push(trait); } else if (type === "mental") { v.mentalTraits.push(trait); } else if (type === "skill") { v.skills.push(trait); } else if (type === "voice") { if (!v.voiceTraits) v.voiceTraits = []; v.voiceTraits.push(trait); } }>> /* ===== TOME NAME MAPPINGS ===== */ <<set setup.traitTomeNames = { /* Physical Traits */ "Broad-shouldered": "Tome of Titan's Frame", "Freckled": "Chronicle of Sun Kisses", "Tattooed": "Book of Living Ink", "Sturdy": "Codex of Endurance", "Youthful": "Manuscript of Eternal Youth", "Attractive": "Grimoire of Allure", "Curvy": "Scroll of Flowing Form", "Voluptuous": "Testament of Abundance", "Gigantic Chest": "Primordial Tome of Divine Endowment", "Gigantic Butt": "Ancient Chronicle of Legendary Curves", "Giant Chest": "Tome of Magnificent Proportions", "Giant Butt": "Chronicle of Grand Curves", "Huge Chest": "Chronicle of Bountiful Curves", "Huge Butt": "Testament of Voluptuous Depths", "Large Chest": "Grimoire of Generous Form", "Large Butt": "Tome of Ample Proportions", "Medium Chest": "Scroll of Balanced Figure", "Medium Butt": "Manuscript of Balanced Curves", "Small Chest": "Book of Modest Proportions", "Small Butt": "Scroll of Petite Form", "Flat Chest": "Manual of Sleek Lines", "Flat Butt": "Book of Athletic Lines", "Flat Masculine Chest": "Codex of Chiseled Pecs", "Flat Masculine Butt": "Guide to Firm Glutes", "Were-Creature": "Forbidden Bestiary", "Lactating": "Tome of Flowing Bounty", /* Voice Traits */ "Deep Voice": "Book of Resonant Depths", "Emotionless Tone": "Manual of Stoic Speech", "Grim Tone": "Diary of Dark Words", "Articulate Speech": "Lexicon of Eloquence", /* Mental Traits */ "Risk Taker": "Journal of Bold Ventures", "Overthinker": "Compendium of Endless Thoughts", "Quiet": "Whisper Manuscript", "Clingy": "Book of Attachment", "Impulsive": "Scroll of Rash Actions", "Disorganized": "Chaotic Chronicles", "Forgetful": "Fading Memoir", "Cowardly": "Tome of Fearful Hearts", "Insecure": "Journal of Self-Doubt", "Brave": "Codex of Courage", "Witty": "Book of Quick Minds", "Passive": "Manual of Peaceful Ways", "Stubborn": "Testament of Unyielding Will", "Paranoid": "Scroll of Eternal Vigilance", "Bitchy": "Grimoire of Sharp Tongues", "Foolish": "Chronicle of Poor Judgment", "Submissive": "Book of Obedience", "Artistic": "Canvas of Creation", "Sly": "Tome of Cunning Shadows", "Perceptive": "All-Seeing Manuscript", "Goth": "Grimoire of Darkness", "Nerd": "Encyclopedia of Knowledge", "Jock": "Manual of Athletic Prowess", "Prep": "Guide to Social Grace", "Dominant": "Tome of Command", "Lucky": "Scroll of Fortune's Favor", "Unlucky": "Scroll of Misfortune's Shadow", /* Skills */ "Occult Expert": "Necronomicon Fragment", "Cog": "Ancient Tome of Mechanical Resonance", "Combat Training": "Codex of Martial Forms", "Business": "Ledger of Commerce", "Social Skills": "Manual of Pleasant Company" }>> <<set setup.getTraitTomeName = function(trait) { return setup.traitTomeNames[trait] || "Mysterious Tome of " + trait; }>> /* ===== PRICING AND DISCOUNTS ===== */ <<set setup.getLampreyDiscount = function() { var rel = State.variables.relationships && State.variables.relationships["Revna McKraken"]; var pts = (rel && typeof rel.points === "number") ? rel.points : 0; var lvl = setup.calculateRelationshipLevel(pts); var discounts = { 0: 0, /* Stranger - no discount */ 1: 0.03, /* Acquaintance - 3% discount */ 2: 0.07, /* Friend - 7% discount */ 3: 0.12, /* Close Friend - 12% discount */ 4: 0.20, /* Best Friend - 20% discount */ 5: 0.20 /* Confidant - capped at Best Friend */ }; return discounts[lvl] || 0; }>> /* Revna's rapport widens the rare-tome roll band on the daily shelf. */ /* Levels follow setup.calculateRelationshipLevel (Acquaintance=1 ...). */ <<set setup.getLampreyRevnaRareBoost = function() { var rel = State.variables.relationships && State.variables.relationships["Revna McKraken"]; if (!rel) return 0; var lvl = setup.calculateRelationshipLevel(rel.points || 0); if (lvl >= 4) return 0.05; /* Best Friend or higher */ if (lvl === 3) return 0.0375; /* Close Friend */ if (lvl === 2) return 0.025; /* Friend */ if (lvl === 1) return 0.0125; /* Acquaintance */ return 0; }>> <<set setup.calculateLampreyPrice = function(basePrice) { var v = State.variables; /* ===== PHARAOH: All tomes cost $1 ===== */ if (v.physicalTraits && v.physicalTraits.includes("Pharaoh")) { return 1; } /* ===== LIVING DOLL SPECIAL DISCOUNT ===== */ /* Living Dolls get 60% off all tomes by default */ var livingDollDiscount = 0; if (v.physicalTraits && (v.physicalTraits.includes("Living Doll") || v.physicalTraits.includes("Automaton"))) { livingDollDiscount = 0.60; } /* Get relationship discount */ var relationshipDiscount = setup.getLampreyDiscount(); /* ===== SKILL TREE: Tome Discount ===== */ var skillTreeDiscount = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { skillTreeDiscount = setup.skillTree.getEffect("tomeDiscount") || 0; } /* Convert percentage to decimal (e.g., 5 -> 0.05) */ var skillTreeDiscountDecimal = skillTreeDiscount / 100; /* Combine discounts (additive) - Living Doll discount is separate/base */ var totalDiscount = livingDollDiscount + relationshipDiscount + skillTreeDiscountDecimal; /* Cap total discount at 90% (Living Doll 60% + other bonuses can stack but not fully free) */ totalDiscount = Math.min(totalDiscount, 0.90); return Math.floor(basePrice * (1 - totalDiscount)); }>> /* Helper function to get just the skill tree discount for display */ <<set setup.getSkillTreeTomeDiscount = function() { var skillTreeDiscount = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { skillTreeDiscount = setup.skillTree.getEffect("tomeDiscount") || 0; } return skillTreeDiscount; /* Return as percentage (e.g., 5 for 5%) */ }>> /* Helper function to get skill tree tome bonus for display */ <<set setup.getSkillTreeTomeBonus = function() { var bonus = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { bonus = setup.skillTree.getEffect("dailyTomeBonus") || 0; } return bonus; }>>
<<nobr>> <<set $lastLocation = "StripClubWorkStripper">> <!-- Achievement for working at strip club --> <<run setup.achievements.unlock("work_stripclub")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Stripper")>> <<run $jobsWorked.push("Stripper")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <!-- Initialize strip club work system --> <<if !$stripClubLastWorkDay>> <<set $stripClubLastWorkDay = 0>> <<set $stagePerformancesToday = 0>> <<set $mingleSessionsToday = 0>> <<set $privateShowsToday = 0>> <<set $maxStagePerformancesPerDay = 3>> <<set $maxMingleSessionsPerDay = 3>> <<set $maxPrivateShowsPerDay = 3>> <</if>> <!-- Reset daily counters if new day --> <<if $stripClubLastWorkDay !== $dayNumber>> <<set $stagePerformancesToday = 0>> <<set $mingleSessionsToday = 0>> <<set $privateShowsToday = 0>> <<set $stripClubLastWorkDay = $dayNumber>> <</if>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9D00FF; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(157, 0, 255, 0.8), 0 0 40px rgba(255, 20, 147, 0.6);">💃 Stripper Shift</h1> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #9D00FF; box-shadow: 0 0 30px rgba(157, 0, 255, 0.4), inset 0 0 20px rgba(255, 20, 147, 0.2);"> <p style="color: #fff; font-size: 20px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The Electric Jelly Revue pulses with life. Bass throbs through the floor, lights sweep across eager faces in the crowd. The smell of perfume, alcohol, and excitement fills the air. </p> <p style="color: #D8BFD8; font-size: 18px; margin: 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> You're on the clock. Time to make some money. </p> </div> <!-- Daily Activity Tracker --> <div style="background: #1a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 30px; border: 3px solid #9D00FF; box-shadow: 0 0 20px rgba(157, 0, 255, 0.3);"> <h3 style="color: #9D00FF; margin: 0 0 15px 0; text-align: center; font-size: 20px;">Today's Activity</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <!-- Stage Performances --> <div style="background: #0a0a1a; padding: 15px; border-radius: 8px; border: 2px solid #9D00FF;"> <p style="color: #9D00FF; margin: 0 0 8px 0; font-weight: bold; font-size: 14px;">🎭 Stage Shows</p> <p style="color: #fff; margin: 0; font-size: 20px; font-weight: bold;"> <<print $stagePerformancesToday>> / <<print $maxStagePerformancesPerDay>> </p> <<if $stagePerformancesToday >= $maxStagePerformancesPerDay>> <p style="color: #ff6b6b; margin: 5px 0 0 0; font-size: 12px;">Exhausted</p> <<else>> <p style="color: #51cf66; margin: 5px 0 0 0; font-size: 12px;"><<print $maxStagePerformancesPerDay - $stagePerformancesToday>> remaining</p> <</if>> </div> <!-- Floor Mingling --> <div style="background: #0a0a1a; padding: 15px; border-radius: 8px; border: 2px solid #FFD700;"> <p style="color: #FFD700; margin: 0 0 8px 0; font-weight: bold; font-size: 14px;">💬 Floor Work</p> <p style="color: #fff; margin: 0; font-size: 20px; font-weight: bold;"> <<print $mingleSessionsToday>> / <<print $maxMingleSessionsPerDay>> </p> <<if $mingleSessionsToday >= $maxMingleSessionsPerDay>> <p style="color: #ff6b6b; margin: 5px 0 0 0; font-size: 12px;">Exhausted</p> <<else>> <p style="color: #51cf66; margin: 5px 0 0 0; font-size: 12px;"><<print $maxMingleSessionsPerDay - $mingleSessionsToday>> remaining</p> <</if>> </div> <!-- Private Shows --> <div style="background: #0a0a1a; padding: 15px; border-radius: 8px; border: 2px solid #FF1493;"> <p style="color: #FF1493; margin: 0 0 8px 0; font-weight: bold; font-size: 14px;">👤 Private Shows</p> <p style="color: #fff; margin: 0; font-size: 20px; font-weight: bold;"> <<print $privateShowsToday>> / <<print $maxPrivateShowsPerDay>> </p> <<if $privateShowsToday >= $maxPrivateShowsPerDay>> <p style="color: #ff6b6b; margin: 5px 0 0 0; font-size: 12px;">Exhausted</p> <<else>> <p style="color: #51cf66; margin: 5px 0 0 0; font-size: 12px;"><<print $maxPrivateShowsPerDay - $privateShowsToday>> remaining</p> <</if>> </div> </div> </div> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💋 Work Options</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-top: 20px; margin-bottom: 30px;"> <!-- Dance on Stage --> <div style="border: 3px solid #9D00FF; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); box-shadow: 0 0 20px rgba(157, 0, 255, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #9D00FF, transparent); opacity: 0.6;"></div> <h4 style="color: #9D00FF; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(157, 0, 255, 0.8);">🎭 Dance on Stage</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Take the main stage under the spotlight. Choose your performance style and give the crowd a show they'll remember. The bigger the performance, the bigger the tips. </p> <<if $stagePerformancesToday >= $maxStagePerformancesPerDay>> <div style='background: linear-gradient(135deg, #666 0%, #444 100%); color: #999; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; font-size: 16px; margin-top: 15px; border: 2px solid #555; cursor: not-allowed;'>Too Exhausted (<<print $stagePerformancesToday>>/<<print $maxStagePerformancesPerDay>>)</div> <<else>> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(157, 0, 255, 0.5); transition: all 0.3s;'>✨ Take the Stage (<<print $maxStagePerformancesPerDay - $stagePerformancesToday>> left)</div>">> <<goto "StripClubStagePerformance">> <</link>> <</if>> </div> <!-- Private Shows --> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 25px rgba(255, 20, 147, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h4 style="color: #FF1493; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);">👤 Private Shows</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Perform exclusive one-on-one shows in private rooms. More intimate, more intense, and much more lucrative. VIP customers pay top dollar for your personal attention. </p> <<if $privateShowsToday >= $maxPrivateShowsPerDay>> <div style='background: linear-gradient(135deg, #666 0%, #444 100%); color: #999; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; font-size: 16px; margin-top: 15px; border: 2px solid #555; cursor: not-allowed;'>Too Exhausted (<<print $privateShowsToday>>/<<print $maxPrivateShowsPerDay>>)</div> <<else>> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6); transition: all 0.3s;'>🔥 Check for Requests (<<print $maxPrivateShowsPerDay - $privateShowsToday>> left)</div>">> <<goto "StripClubPrivateShows">> <</link>> <</if>> </div> <!-- Mingle with Customers --> <div style="border: 3px solid #FFD700; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); box-shadow: 0 0 20px rgba(255, 215, 0, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FFD700, transparent); opacity: 0.6;"></div> <h4 style="color: #FFD700; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);">💬 Mingle with Customers</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Work the floor with charm and charisma. Flirt, tease, and chat with patrons. Let your personality shine and watch the tips roll in from admirers who can't resist you. </p> <<if $mingleSessionsToday >= $maxMingleSessionsPerDay>> <div style='background: linear-gradient(135deg, #666 0%, #444 100%); color: #999; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; font-size: 16px; margin-top: 15px; border: 2px solid #555; cursor: not-allowed;'>Too Exhausted (<<print $mingleSessionsToday>>/<<print $maxMingleSessionsPerDay>>)</div> <<else>> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(255, 215, 0, 0.5); transition: all 0.3s;'>🌟 Work the Floor (<<print $maxMingleSessionsPerDay - $mingleSessionsToday>> left)</div>">> <<goto "StripClubMingleCustomers">> <</link>> <</if>> </div> </div> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #444 100%); color: white; padding: 14px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #888;'>← End Shift</div>">> <<goto "StripClub">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<workShift>> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubStagePerformance">> <<set $stripperTopPerformed = false>><<set $stripperTopResult = null>> <<set $stripperFullPerformed = false>><<set $stripperFullResult = null>> <<set $stripperPolePerformed = false>><<set $stripperPoleResult = null>> <<set $stripperFreestylePerformed = false>><<set $stripperFreestyleResult = null>> <!-- Initialize stage performance counter --> <<if !$stagePerformancesToday>> <<set $stagePerformancesToday = 0>> <<set $maxStagePerformancesPerDay = 3>> <</if>> <<set _canPerform = $stagePerformancesToday < $maxStagePerformancesPerDay>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FF1493; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8), 0 0 40px rgba(157, 0, 255, 0.6);">🎭 Take The Stage</h1> <!-- Atmospheric Scene Setting --> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FF1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.4), inset 0 0 20px rgba(157, 0, 255, 0.2);"> <p style="color: #fff; font-size: 20px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The moment you step through the curtain, the bass pounds through your chest. Multicolored lights sweep across the stage in hypnotic patterns—purple, pink, electric blue. The pole gleams under the spotlight, beckoning. </p> <p style="color: #FFB6C1; font-size: 18px; margin: 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Eyes turn toward you from the crowd. Some hungry, some curious, all waiting. The music builds, heavy and sensual. Your skin tingles with anticipation. How will you seduce them tonight? </p> </div> <!-- Performance Counter --> <div style="background: #2a2a2a; border: 3px solid <<if _canPerform>>#4ade80<<else>>#ff6b6b<</if>>; padding: 20px; border-radius: 12px; margin-bottom: 25px; text-align: center; box-shadow: 0 0 20px <<if _canPerform>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <h3 style="color: <<if _canPerform>>#4ade80<<else>>#ff6b6b<</if>>; margin: 0 0 10px 0; text-shadow: 0 0 10px <<if _canPerform>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> Stage Performances Today: <<print $stagePerformancesToday>> / <<print $maxStagePerformancesPerDay>> </h3> <<if !_canPerform>> <p style="color: #ff6b6b; margin: 0; font-size: 14px;"> You've performed enough for today. The stage needs a rest, and so do you. </p> <</if>> </div> <<if _canPerform>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💋 Choose Your Performance</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-top: 20px; margin-bottom: 30px;"> <!-- Remove Top --> <div style="border: 3px solid #FF69B4; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); box-shadow: 0 0 20px rgba(255, 105, 180, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; transition: all 0.3s; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF69B4, transparent); opacity: 0.6;"></div> <h4 style="color: #FF69B4; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 105, 180, 0.8);">👚 Tease & Reveal</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Slowly peel away your top while grinding to the rhythm. Let them see glimpses of skin, building their desire with every teasing movement. Your hands trace your curves as fabric slides away... </p> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid rgba(255, 105, 180, 0.3);"> <p style="color: #FFB6C1; font-size: 13px; margin: 0 0 5px 0; font-style: italic;"> ⭐ Moderate tips • Charisma 40+ • Dexterity 35+ </p> <p style="color: #FFD700; font-size: 14px; margin: 0; font-weight: bold;"> 💰 Potential: $30-90 </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF69B4 0%, #FF1493 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 12px; box-shadow: 0 0 15px rgba(255, 105, 180, 0.5); transition: all 0.3s;'>💕 Tease Them</div>">> <<goto "StripClubPerformRemoveTop">> <</link>> </div> <!-- Strip Completely --> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 25px rgba(255, 20, 147, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; transition: all 0.3s; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h4 style="color: #FF1493; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);">🔥 Full Exposure</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Give them everything. Strip down piece by piece until you're completely bare, body glistening under the lights. Show them your most intimate curves while moving with uninhibited sensuality. No holding back. </p> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid rgba(255, 20, 147, 0.3);"> <p style="color: #FFB6C1; font-size: 13px; margin: 0 0 5px 0; font-style: italic;"> ⭐⭐⭐ Maximum tips • Charisma 60+ • Dexterity 50+ </p> <p style="color: #FFD700; font-size: 14px; margin: 0; font-weight: bold;"> 💰 Potential: $75-300 </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 12px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6); transition: all 0.3s;'>🔥 Strip Naked</div>">> <<goto "StripClubPerformStripFull">> <</link>> </div> <!-- Pole Dance --> <div style="border: 3px solid #9D00FF; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); box-shadow: 0 0 20px rgba(157, 0, 255, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; transition: all 0.3s; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #9D00FF, transparent); opacity: 0.6;"></div> <h4 style="color: #9D00FF; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(157, 0, 255, 0.8);">💫 Acrobatic Seduction</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Grip the chrome pole and let your body become art. Spin, climb, and arch your back in gravity-defying moves. Every muscle flexing, every curve on display as you twist and spiral with athletic grace. </p> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid rgba(157, 0, 255, 0.3);"> <p style="color: #D8BFD8; font-size: 13px; margin: 0 0 5px 0; font-style: italic;"> ⭐⭐ High tips • Dexterity 70+ • Strength 65+ </p> <p style="color: #FFD700; font-size: 14px; margin: 0; font-weight: bold;"> 💰 Potential: $50-250 </p> </div> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 12px; box-shadow: 0 0 15px rgba(157, 0, 255, 0.5); transition: all 0.3s;'>✨ Work The Pole</div>">> <<goto "StripClubPerformPole">> <</link>> </div> <!-- Freestyle --> <div style="border: 3px solid #FFD700; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); box-shadow: 0 0 20px rgba(255, 215, 0, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; transition: all 0.3s; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FFD700, transparent); opacity: 0.6;"></div> <h4 style="color: #FFD700; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);">✨ Improvised Desire</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 auto 0; line-height: 1.5;"> Let the music flow through you. No routine, just raw sensuality and instinct. Sway your hips, arch your back, lock eyes with the audience. Make them feel like you're dancing only for them, responding to their energy. </p> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid rgba(255, 215, 0, 0.3);"> <p style="color: #FFE4B5; font-size: 13px; margin: 0 0 5px 0; font-style: italic;"> ⭐⭐ Variable tips • Charisma 55+ • Dexterity 45+ </p> <p style="color: #FFD700; font-size: 14px; margin: 0; font-weight: bold;"> 💰 Potential: $40-200 </p> </div> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 12px; box-shadow: 0 0 15px rgba(255, 215, 0, 0.5); transition: all 0.3s;'>🌟 Let Loose</div>">> <<goto "StripClubPerformFreestyle">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 0 20px rgba(255, 107, 107, 0.3); text-align: center;"> <p style="color: #ff6b6b; font-size: 18px; margin: 0;"> You've performed on stage enough for today. Your body needs rest. </p> </div> <</if>> <!-- Pulsing light effect --> <style> @keyframes glow-pulse { 0%, 100% { box-shadow: 0 0 20px rgba(255, 20, 147, 0.3); } 50% { box-shadow: 0 0 35px rgba(255, 20, 147, 0.6); } } </style> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #444 100%); color: white; padding: 14px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #888;'>← Step Off Stage</div>">> <<goto "StripClubWorkStripper">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubPrivateShows">> <<set $privateShowPerformed = false>><<set $privateShowResult = null>><<set $privateShowType = null>> <!-- Initialize private show variables --> <<if !$privateShowsToday>> <<set $privateShowsToday = 0>> <<set $maxPrivateShowsPerDay = 3>> <</if>> <<set _canTakeShow = $privateShowsToday < $maxPrivateShowsPerDay>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FF1493; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8), 0 0 40px rgba(157, 0, 255, 0.6);">👤 Private Shows</h1> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FF1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.4), inset 0 0 20px rgba(157, 0, 255, 0.2);"> <p style="color: #fff; font-size: 20px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The VIP section is where the real money gets made. Behind velvet curtains and locked doors, wealthy clients pay premium prices for your exclusive attention. No crowd, no distractions—just you and them. </p> <p style="color: #FFB6C1; font-size: 18px; margin: 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> What they do with that time is up to you... and what you're willing to offer. </p> </div> <!-- Shows Performed Today Counter --> <div style="background: #2a2a2a; border: 3px solid <<if _canTakeShow>>#4ade80<<else>>#ff6b6b<</if>>; padding: 20px; border-radius: 12px; margin-bottom: 25px; text-align: center; box-shadow: 0 0 20px <<if _canTakeShow>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <h3 style="color: <<if _canTakeShow>>#4ade80<<else>>#ff6b6b<</if>>; margin: 0 0 10px 0; text-shadow: 0 0 10px <<if _canTakeShow>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> Private Shows Today: <<print $privateShowsToday>> / <<print $maxPrivateShowsPerDay>> </h3> <<if !_canTakeShow>> <p style="color: #ff6b6b; margin: 0; font-size: 14px;"> You've reached your daily limit. Your body needs rest. </p> <</if>> </div> <<if _canTakeShow>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">💎 Available Show Types</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px;"> <!-- Lap Dance - REDUCED --> <div style="border: 3px solid #FF69B4; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); box-shadow: 0 0 20px rgba(255, 105, 180, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF69B4, transparent); opacity: 0.6;"></div> <h4 style="color: #FF69B4; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 105, 180, 0.8);">💋 Lap Dance</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Grind on their lap, run your hands over your body, let them feel the heat radiating off you. Close contact, no touching (unless you allow it). </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Base Pay:</span> $50-150 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Requirements:</span> Charisma 35, Dexterity 30 </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Duration:</span> 15 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF69B4 0%, #FF1493 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(255, 105, 180, 0.5);'>💕 Accept Request</div>">> <<set $privateShowType = "lapdance">> <<goto "StripClubPrivateShowPerform">> <</link>> </div> <!-- Intimate Dance - REDUCED --> <div style="border: 3px solid #FFD700; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); box-shadow: 0 0 20px rgba(255, 215, 0, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FFD700, transparent); opacity: 0.6;"></div> <h4 style="color: #FFD700; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);">✨ Intimate Dance</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Dance close, bodies nearly touching. Eye contact, whispered words, sensual movements. More connection than performance. The lines blur between dancer and client. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Base Pay:</span> $60-175 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Requirements:</span> Charisma 35, Dexterity 35 </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Duration:</span> 20 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(255, 215, 0, 0.5);'>💛 Accept Request</div>">> <<set $privateShowType = "intimate">> <<goto "StripClubPrivateShowPerform">> <</link>> </div> <!-- Sensual Tease --> <div style="border: 3px solid #C71585; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 20px rgba(199, 21, 133, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #C71585, transparent); opacity: 0.6;"></div> <h4 style="color: #C71585; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(199, 21, 133, 0.8);">🌹 Sensual Tease</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> A slow, intimate striptease just for them. Remove each piece deliberately, touch yourself sensually, make them ache with want. Pure visual seduction. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Base Pay:</span> $100-250 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Requirements:</span> Charisma 55, Dexterity 50 </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Duration:</span> 20 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #C71585 0%, #8B008B 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(199, 21, 133, 0.5);'>🌹 Accept Request</div>">> <<set $privateShowType = "tease">> <<goto "StripClubPrivateShowPerform">> <</link>> </div> <!-- Pole Performance --> <div style="border: 3px solid #9D00FF; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); box-shadow: 0 0 20px rgba(157, 0, 255, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #9D00FF, transparent); opacity: 0.6;"></div> <h4 style="color: #9D00FF; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(157, 0, 255, 0.8);">💫 Private Pole Show</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Give them an exclusive acrobatic performance. Spins, inversions, floor work—show off your athletic prowess in an intimate setting with just one set of eyes watching. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Base Pay:</span> $125-300 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Requirements:</span> Dexterity 65, Strength 60 </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Duration:</span> 20 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(157, 0, 255, 0.5);'>✨ Accept Request</div>">> <<set $privateShowType = "pole">> <<goto "StripClubPrivateShowPerform">> <</link>> </div> <!-- Roleplay Fantasy --> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); box-shadow: 0 0 25px rgba(255, 20, 147, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h4 style="color: #FF1493; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);">🎭 Roleplay Fantasy</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Become their fantasy. Play a character, act out a scenario. This is equal parts performance art and seduction. Requires creativity and acting skills. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Base Pay:</span> $150-350 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Requirements:</span> Charisma 75, Intelligence 70 </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Duration:</span> 30 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6);'>🎭 Accept Request</div>">> <<set $privateShowType = "roleplay">> <<goto "StripClubPrivateShowPerform">> <</link>> </div> <!-- Full Service (Optional Sex) --> <div style="border: 3px solid #DC143C; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a0a 0%, #2a0a0a 100%); box-shadow: 0 0 25px rgba(220, 20, 60, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #DC143C, transparent); opacity: 0.6;"></div> <h4 style="color: #DC143C; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(220, 20, 60, 0.8);">🔥 Full Experience</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Everything they desire. Dance, touch, and more if you're willing. The rules are yours to set, but they're paying for complete satisfaction. This is where boundaries get negotiated. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Base Pay:</span> $200-500 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Requirements:</span> Charisma 90 </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Duration:</span> 45 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #DC143C 0%, #8B0000 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(220, 20, 60, 0.6);'>🔥 Accept Request</div>">> <<set $privateShowType = "fullservice">> <<goto "StripClubPrivateShowPerform">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 0 20px rgba(255, 107, 107, 0.3); text-align: center;"> <p style="color: #ff6b6b; font-size: 18px; margin: 0;"> You've completed your maximum number of private shows for today. Rest up and come back tomorrow. </p> </div> <</if>> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #444 100%); color: white; padding: 14px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #888;'>← Back to Shift</div>">> <<goto "StripClubWorkStripper">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubMingleCustomers">> <<set $minglePerformed = false>><<set $mingleResult = null>><<set $mingleCustomerType = null>> <!-- Initialize mingling variables - REDUCED TO 3 --> <<if !$mingleSessionsToday>> <<set $mingleSessionsToday = 0>> <<set $maxMingleSessionsPerDay = 3>> <</if>> <<set _canMingle = $mingleSessionsToday < $maxMingleSessionsPerDay>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(255, 215, 0, 0.8), 0 0 40px rgba(255, 165, 0, 0.6);">💬 Work the Floor</h1> <div style="padding: 30px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FFD700; box-shadow: 0 0 30px rgba(255, 215, 0, 0.4), inset 0 0 20px rgba(255, 165, 0, 0.2);"> <p style="color: #fff; font-size: 20px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The club floor buzzes with activity. Customers nurse their drinks, eyes roaming hungrily. This is where charm and conversation translate directly into cash. Make them laugh, make them feel special, and watch the tips accumulate. </p> <p style="color: #FFE4B5; font-size: 18px; margin: 0; line-height: 1.6; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Every smile, every touch, every whispered word is an opportunity. Work smart, work sexy. </p> </div> <!-- Sessions Counter --> <div style="background: #2a2a2a; border: 3px solid <<if _canMingle>>#4ade80<<else>>#ff6b6b<</if>>; padding: 20px; border-radius: 12px; margin-bottom: 25px; text-align: center; box-shadow: 0 0 20px <<if _canMingle>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <h3 style="color: <<if _canMingle>>#4ade80<<else>>#ff6b6b<</if>>; margin: 0 0 10px 0; text-shadow: 0 0 10px <<if _canMingle>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> Floor Sessions Today: <<print $mingleSessionsToday>> / <<print $maxMingleSessionsPerDay>> </h3> <<if !_canMingle>> <p style="color: #ff6b6b; margin: 0; font-size: 14px;"> You've worked the floor enough for today. Your charm needs recharging. </p> <</if>> </div> <<if _canMingle>> <h2 style="color: #FF69B4; text-align: center; font-size: 28px; margin-bottom: 25px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.6);">👥 Available Customers</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px;"> <!-- Shy Regular - REDUCED --> <div style="border: 3px solid #87CEEB; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #0a0a1a 0%, #0a1a2a 100%); box-shadow: 0 0 20px rgba(135, 206, 235, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #87CEEB, transparent); opacity: 0.6;"></div> <h4 style="color: #87CEEB; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(135, 206, 235, 0.8);">😊 Shy Regular</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> A nervous customer who's been here a few times but never really talked to anyone. Gentle conversation and reassurance. Easy to please, modest tips. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Potential Tips:</span> $13-38 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Best Approach:</span> Charisma 30+ </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Time:</span> 10 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #87CEEB 0%, #4682B4 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(135, 206, 235, 0.5);'>💙 Approach Them</div>">> <<set $mingleCustomerType = "shy">> <<goto "StripClubMingleInteraction">> <</link>> </div> <!-- Big Spender --> <div style="border: 3px solid #FFD700; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); box-shadow: 0 0 25px rgba(255, 215, 0, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FFD700, transparent); opacity: 0.6;"></div> <h4 style="color: #FFD700; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 215, 0, 0.8);">💎 Big Spender</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Well-dressed, confident, expensive watch. They know what they want and have money to burn. Flirt hard, be impressive, and you'll be rewarded generously. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Potential Tips:</span> $75-200 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Best Approach:</span> Charisma 50+, Attractive trait </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Time:</span> 15 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 215, 0, 0.6);'>✨ Approach Them</div>">> <<set $mingleCustomerType = "spender">> <<goto "StripClubMingleInteraction">> <</link>> </div> <!-- Bachelor Party - REDUCED --> <div style="border: 3px solid #FF6347; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a0a 0%, #2a0a0a 100%); box-shadow: 0 0 20px rgba(255, 99, 71, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF6347, transparent); opacity: 0.6;"></div> <h4 style="color: #FF6347; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 99, 71, 0.8);">🎉 Bachelor Party</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> Rowdy group celebrating. They're loud, drunk, and looking for a good time. Entertain the whole table, play along with their energy. Group tips can add up fast. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Potential Tips:</span> $25-75 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Best Approach:</span> Charisma 40+, High energy </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Time:</span> 20 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF6347 0%, #DC143C 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(255, 99, 71, 0.5);'>🎊 Approach Them</div>">> <<set $mingleCustomerType = "bachelor">> <<goto "StripClubMingleInteraction">> <</link>> </div> <!-- Lonely Businessman - REDUCED --> <div style="border: 3px solid #9370DB; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); box-shadow: 0 0 20px rgba(147, 112, 219, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #9370DB, transparent); opacity: 0.6;"></div> <h4 style="color: #9370DB; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(147, 112, 219, 0.8);">💼 Lonely Businessman</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> In town for business, stressed and isolated. They want connection more than sex. Listen, empathize, make them feel understood. Good conversation pays. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Potential Tips:</span> $30-88 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Best Approach:</span> Charisma 45+, Intelligence 35+ </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Time:</span> 15 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #9370DB 0%, #6A5ACD 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(147, 112, 219, 0.5);'>💜 Approach Them</div>">> <<set $mingleCustomerType = "businessman">> <<goto "StripClubMingleInteraction">> <</link>> </div> <!-- Couple --> <div style="border: 3px solid #FF69B4; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); box-shadow: 0 0 20px rgba(255, 105, 180, 0.3), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF69B4, transparent); opacity: 0.6;"></div> <h4 style="color: #FF69B4; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 105, 180, 0.8);">💕 Adventurous Couple</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> They're here together, looking to spice things up. Navigate carefully—flirt with both, make neither jealous. Threeway conversation dynamics. High risk, high reward. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Potential Tips:</span> $90-225 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Best Approach:</span> Charisma 65+, Seductive trait </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Time:</span> 20 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF69B4 0%, #FF1493 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 15px rgba(255, 105, 180, 0.5);'>💕 Approach Them</div>">> <<set $mingleCustomerType = "couple">> <<goto "StripClubMingleInteraction">> <</link>> </div> <!-- VIP High Roller --> <div style="border: 3px solid #FF1493; border-radius: 15px; padding: 20px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); box-shadow: 0 0 25px rgba(255, 20, 147, 0.4), 0 8px 16px rgba(0,0,0,0.6); display: flex; flex-direction: column; position: relative; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; right: 0; height: 4px; background: linear-gradient(90deg, transparent, #FF1493, transparent); opacity: 0.6;"></div> <h4 style="color: #FF1493; margin: 0 0 12px 0; font-size: 22px; text-shadow: 0 0 10px rgba(255, 20, 147, 0.8);">👑 VIP High Roller</h4> <p style="color: #ddd; font-size: 15px; margin: 0 0 15px 0; line-height: 1.5;"> The club's biggest whale. Demanding, particular, expects perfection. You need to be at your absolute best. Fail and you get nothing. Succeed and you'll make bank. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: auto;"> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #FFD700;">💰 Potential Tips:</span> $125-300 </p> <p style="color: #aaa; font-size: 13px; margin: 0 0 8px 0;"> <span style="color: #60a5fa;">📊 Best Approach:</span> Charisma 80+, Multiple traits </p> <p style="color: #aaa; font-size: 13px; margin: 0;"> <span style="color: #9D00FF;">⏱️ Time:</span> 25 minutes </p> </div> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; margin-top: 15px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6);'>👑 Approach Them</div>">> <<set $mingleCustomerType = "vip">> <<goto "StripClubMingleInteraction">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 0 20px rgba(255, 107, 107, 0.3); text-align: center;"> <p style="color: #ff6b6b; font-size: 18px; margin: 0;"> You've worked the floor enough for today. Give yourself a break. </p> </div> <</if>> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #444 100%); color: white; padding: 14px 35px; border-radius: 10px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #888;'>← Back to Shift</div>">> <<goto "StripClubWorkStripper">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Brothel">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #007FFF; text-align: center;">👑 Brothel Management</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/BrothelOffice.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #007FFF; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Management Office"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #007FFF 0%, #0059b3 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #007FFF;"> <p style="color: white; font-size: 18px; margin: 0;"> Your private office overlooks the main floor through one-way glass. Leather furniture, a polished mahogany desk, and walls lined with financial reports and security monitors. From here, you control every aspect of the Azure Angelfish Lounge. </p> </div> <h2 style="color: #007FFF;">Management Options</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- View Finances --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">💰 View Finances</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Review income, expenses, and overall profitability of your establishment.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Staff Management --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">👥 Staff Management</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Hire, fire, and manage your workers. Review their performance and assign schedules.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Upgrade Facilities --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">🏗️ Upgrade Facilities</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Improve rooms, add amenities, and expand your establishment to attract higher-paying clients.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Set Pricing --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">💵 Set Pricing</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Adjust service prices to maximize profit while maintaining clientele.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Performance Reviews --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">📊 Performance Reviews</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Analyze worker performance metrics, client satisfaction, and revenue per employee.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Marketing & Advertising --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">📢 Marketing</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Run advertising campaigns and promotions to attract new clients and boost reputation.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Security & Discretion --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">🔒 Security</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Manage security systems, background checks, and maintain client discretion protocols.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Special Services --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h4 style="color: #888; margin: 0 0 10px 0;">✨ Special Services</h4> <p style="color: #777; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Develop and manage premium, exclusive services for VIP clientele.</p> <div style='background: #555; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #007FFF 0%, #0059b3 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Brothel Floor</div>">> <<goto "Brothel">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Enforce 8-hour daily work limit --> <<if !$secretaryHoursWorkedToday>> <<set $secretaryHoursWorkedToday = 0>> <</if>> <<if $secretaryHoursWorkedToday >= 8>> <<goto "SecretaryWorkLimitReached">> <</if>> <!-- Initialize Sunfish counter if it doesn't exist --> <<if !$sunfishSightings>> <<set $sunfishSightings = 0>> <</if>> <!-- Get Mayor's Gender --> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<set _mayorGender = "unknown">> <<if _mayorNPCs.length > 0>> <<set _mayorGender = _mayorNPCs[0].bodyParts.gender>> <</if>> <!-- Calculate Attractiveness Score --> <<set _attractiveTraits = ["Attractive", "Curvy", "Voluptuous", "Charming", "Seductive", "Alluring", "Flirty", "Smooth Skin", "Youthful", "Graceful", "Fashionable", "Warm", "Charismatic Voice", "Smooth Voice"]>> <<set _masculineTraits = ["Muscular", "Broad-shouldered", "Strong", "Athletic Build", "Sturdy", "Jock", "Fit", "Lean"]>> <<set _feminineTraits = ["Curvy", "Voluptuous", "Soft", "Graceful", "Petite", "Youthful", "Smooth Skin"]>> <<set _attractivenessScore = 0>> <<set _masculinityScore = 0>> <<set _femininityScore = 0>> <<for _trait range _attractiveTraits>> <<if $physicalTraits.includes(_trait) || $mentalTraits.includes(_trait)>> <<set _attractivenessScore += 1>> <</if>> <</for>> <<for _trait range _masculineTraits>> <<if $physicalTraits.includes(_trait)>> <<set _masculinityScore += 1>> <</if>> <</for>> <<for _trait range _feminineTraits>> <<if $physicalTraits.includes(_trait)>> <<set _femininityScore += 1>> <</if>> <</for>> <!-- Check for sexual traits --> <<set _sexualTraits = ["Oral Expert", "Anal Expert", "Dirty Talker", "BDSM Enthusiast - Dom", "BDSM Enthusiast - Sub", "Exhibitionist", "Rough Sex Enthusiast", "Sensual Lover", "Roleplay Expert", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master"]>> <<set _hasSexualTraits = false>> <<set _sexualTraitCount = 0>> <<for _trait range _sexualTraits>> <<if $skills.includes(_trait)>> <<set _hasSexualTraits = true>> <<set _sexualTraitCount += 1>> <</if>> <</for>> <!-- Chest size bonus for female player with male mayor --> <<set _chestBonus = 0>> <<if $bodyParts.gender === "female" && _mayorGender === "male">> <<set _chestSizes = ["flat", "small", "medium", "large", "huge", "giant"]>> <<set _chestIndex = _chestSizes.indexOf($bodyParts.chest.toLowerCase())>> <<if _chestIndex >= 0>> <<set _chestBonus = _chestIndex * 5>> <</if>> <</if>> <!-- Calculate base erotic task chance --> <<set _eroticChance = 20>> <!-- Sexual traits increase erotic chance --> <<if _hasSexualTraits>> <<set _eroticChance += (_sexualTraitCount * 5)>> <</if>> <!-- Gender-based modifiers --> <<if $bodyParts.gender === "female" && _mayorGender === "male">> <<set _eroticChance += (_attractivenessScore * 5) + (_femininityScore * 5) + _chestBonus>> <<elseif $bodyParts.gender === "male" && _mayorGender === "female">> <<set _eroticChance += (_attractivenessScore * 5) + (_masculinityScore * 8)>> <<elseif $bodyParts.gender === _mayorGender>> <!-- Same gender - requires high attractiveness + specific traits --> <<if $bodyParts.gender === "male" && $mentalTraits.includes("Femboy")>> <<set _eroticChance = (_attractivenessScore >= 5) ? 40 : 0>> <<elseif $bodyParts.gender === "female" && $mentalTraits.includes("Tomboy")>> <<set _eroticChance = (_attractivenessScore >= 5) ? 40 : 0>> <<else>> <<set _eroticChance = 0>> <</if>> <!-- Add sexual trait bonus for same gender --> <<if _eroticChance > 0 && _hasSexualTraits>> <<set _eroticChance += (_sexualTraitCount * 5)>> <</if>> <</if>> <!-- Sunfish trait override --> <<if $skills.includes("Sunfish")>> <<set _eroticChance = 95>> <<else>> <!-- Cap at 85% for non-Sunfish players --> <<if _eroticChance > 85>> <<set _eroticChance = 85>> <</if>> <</if>> <!-- Determine task type --> <<set _taskRoll = random(1, 100)>> <<set _isEroticTask = _taskRoll <= _eroticChance>> <!-- Check for Sunfish trait event (1% chance) --> <<set _sunfishEvent = false>> <<if $skills.includes("Sunfish") && random(1, 100) === 1>> <<set _sunfishEvent = true>> <<set $sunfishSightings += 1>> <</if>> <!-- Check if going to The Alter --> <<if $sunfishSightings >= 10>> <<run setup.achievements.unlock("stalked_10_times")>> <<goto "TheAlter">> <</if>> <!-- Calculate erotic payment based on traits (75-250) --> <<set _traitPaymentScore = _attractivenessScore + _masculinityScore + _femininityScore + (_chestBonus / 5)>> <<set _eroticPay = Math.floor(75 + (_traitPaymentScore * 12))>> <<if _eroticPay > 250>> <<set _eroticPay = 250>> <</if>> <!-- Generate Task --> <<if !_isEroticTask>> <!-- NORMAL TASK --> <<set _normalTasks = [ {desc: "file paperwork and organize the mayor's schedule", pay: 30}, {desc: "answer phone calls and respond to emails", pay: 25}, {desc: "prepare meeting notes and agendas", pay: 35}, {desc: "coordinate with other city departments", pay: 40}, {desc: "review and proofread city documents", pay: 30}, {desc: "manage the mayor's calendar and appointments", pay: 35}, {desc: "order office supplies and maintain inventory", pay: 25}, {desc: "greet visitors and direct them appropriately", pay: 30} ]>> <<set _task = _normalTasks.random()>> <<set _taskType = "normal">> <<else>> <!-- EROTIC TASK --> <<if $bodyParts.gender === "female" && _mayorGender === "male">> <<set _eroticTasks = [ {desc: "sit on the mayor's lap during a 'private meeting'", pay: _eroticPay, passage: "SecretaryEroticLap", taskId: "lap"}, {desc: "massage the mayor's shoulders while he works", pay: _eroticPay, passage: "SecretaryEroticMassage", taskId: "massage"}, {desc: "wear a more 'professional' outfit the mayor has selected", pay: _eroticPay, passage: "SecretaryEroticOutfit", taskId: "outfit"}, {desc: "take dictation while sitting very close to the mayor", pay: _eroticPay, passage: "SecretaryEroticDictation", taskId: "dictation"}, {desc: "help the mayor 'relieve stress' under his desk", pay: _eroticPay, passage: "SecretaryEroticDesk", taskId: "desk"}, {desc: "model the new 'city uniform' for the mayor's approval", pay: _eroticPay, passage: "SecretaryEroticModel", taskId: "modeling"}, {desc: "give the mayor a 'special presentation' behind closed doors", pay: _eroticPay, passage: "SecretaryEroticPresentation", taskId: "presentation"} ]>> <<elseif $bodyParts.gender === "male" && _mayorGender === "female">> <<set _eroticTasks = [ {desc: "let the mayor admire your physique during a 'fitness consultation'", pay: _eroticPay, passage: "SecretaryEroticPhysique", taskId: "fitness"}, {desc: "assist the mayor with 'personal stress relief'", pay: _eroticPay, passage: "SecretaryEroticRelief", taskId: "relief"}, {desc: "provide the mayor with a private massage", pay: _eroticPay, passage: "SecretaryEroticMassageFemale", taskId: "massage2"}, {desc: "model swimwear for the mayor's 'aquatics initiative review'", pay: _eroticPay, passage: "SecretaryEroticSwimwear", taskId: "swimwear"}, {desc: "help the mayor with 'personal satisfaction' in her private office", pay: _eroticPay, passage: "SecretaryEroticSatisfaction", taskId: "satisfaction"}, {desc: "demonstrate your strength by lifting the mayor", pay: _eroticPay, passage: "SecretaryEroticLift", taskId: "strength"}, {desc: "provide 'intimate assistance' as requested", pay: _eroticPay, passage: "SecretaryEroticAssist", taskId: "assistance"} ]>> <<else>> <!-- Same gender tasks --> <<set _eroticTasks = [ {desc: "help the mayor with a 'private wardrobe consultation'", pay: _eroticPay, passage: "SecretaryEroticWardrobe", taskId: "wardrobe"}, {desc: "provide the mayor with 'personal companionship'", pay: _eroticPay, passage: "SecretaryEroticCompanion", taskId: "companionship"}, {desc: "give the mayor a private massage", pay: _eroticPay, passage: "SecretaryEroticMassageSame", taskId: "massage3"}, {desc: "model clothing for the mayor's review", pay: _eroticPay, passage: "SecretaryEroticModelSame", taskId: "fashion"}, {desc: "assist with the mayor's 'special needs'", pay: _eroticPay, passage: "SecretaryEroticNeeds", taskId: "needs"} ]>> <</if>> <<set _task = _eroticTasks.random()>> <<set _taskType = "erotic">> <!-- Apply sexual trait bonuses to payment --> <<set _paymentBonus = 0>> <!-- Check for trait-specific bonuses based on task type --> <<if _task.taskId === "lap" || _task.taskId === "dictation">> <<if $skills.includes("BDSM Enthusiast - Sub")>> <<set _paymentBonus += 30>> <</if>> <<if $skills.includes("Sensual Lover")>> <<set _paymentBonus += 25>> <</if>> <<elseif _task.taskId === "massage" || _task.taskId === "massage2" || _task.taskId === "massage3">> <<if $skills.includes("Sensual Lover")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "outfit" || _task.taskId === "modeling" || _task.taskId === "presentation" || _task.taskId === "fitness" || _task.taskId === "swimwear" || _task.taskId === "wardrobe" || _task.taskId === "fashion">> <<if $skills.includes("Exhibitionist")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "desk" || _task.taskId === "relief">> <<if $skills.includes("Oral Expert")>> <<set _paymentBonus += 45>> <</if>> <<if $skills.includes("BDSM Enthusiast - Sub")>> <<set _paymentBonus += 25>> <</if>> <<elseif _task.taskId === "satisfaction" || _task.taskId === "needs">> <<if $skills.includes("BDSM Enthusiast - Sub")>> <<set _paymentBonus += 30>> <</if>> <<if $skills.includes("Rough Sex Enthusiast")>> <<set _paymentBonus += 35>> <</if>> <<elseif _task.taskId === "strength">> <<if $skills.includes("Sexual Stamina Expert")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "assistance">> <<if $skills.includes("Rough Sex Enthusiast")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "companionship">> <<if $skills.includes("Sensual Lover")>> <<set _paymentBonus += 35>> <</if>> <</if>> <!-- Apply bonus to task payment --> <<set _task.pay += _paymentBonus>> <!-- Trophy Wife 2x cash bonus for secretary sexual acts --> <<if $physicalTraits.includes("Trophy Wife")>> <<set _task.pay = _task.pay * 2>> <</if>> <!-- Slut 2x cash bonus for secretary sexual acts --> <<if $physicalTraits.includes("Slut")>> <<set _task.pay = _task.pay * 2>> <</if>> <!-- Cap at 1400 (increased to accommodate Slut bonus) --> <<if _task.pay > 1400>> <<set _task.pay = 1400>> <</if>> <</if>> <!-- Store task info globally for sub-passages --> <<set $currentTask = _task>> <<set $currentTaskType = _taskType>> <!-- Check for forced acceptance (Bimbo/Submissive) --> <<set _canRefuse = true>> <<set _forceAcceptChance = 0>> <<if $mentalTraits.includes("Bimbo") && $mentalTraits.includes("Submissive")>> <<set _forceAcceptChance = 75>> <<elseif $mentalTraits.includes("Bimbo") || $mentalTraits.includes("Submissive")>> <<set _forceAcceptChance = 50>> <</if>> <<set _forcedAcceptance = false>> <<if _forceAcceptChance > 0 && random(1, 100) <= _forceAcceptChance>> <<set _forcedAcceptance = true>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">✨ Special Assignment</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> You enter the mayor's private office. The door closes behind you with a soft click. </p> </div> <!-- Sunfish Event --> <<if _sunfishEvent>> <div style="background: #1a3a4a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a9eff; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #4dabf7; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> For a brief moment, you catch a glimpse of something in your peripheral vision - a shadowy figure that appears to be made of several sunfish stacked in a trench coat. When you turn to look, there's nothing there. Just an empty corner of the office. </p> <p style="color: #74c0fc; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> (Strange sightings: $sunfishSightings/10) </p> </div> <</if>> <!-- Task Description --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if _taskType === 'erotic'>>#FFD700<<else>>#9b59b6<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: <<if _taskType === 'erotic'>>#FFD700<<else>>#9b59b6<</if>>; margin-top: 0;">The Mayor's Request</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid <<if _taskType === 'erotic'>>#FFD700<<else>>#666<</if>>;"> <p style="color: #ccc; font-size: 16px; margin: 0;"> The mayor asks you to <strong style="color: <<if _taskType === 'erotic'>>#FFD700<<else>>#9b59b6<</if>>;"><<print _task.desc>></strong>. </p> <<if _taskType === "erotic">> <p style="color: #ffc107; font-size: 14px; margin: 15px 0 0 0; font-style: italic;"> This definitely wasn't in your job description... </p> <</if>> </div> <div style="margin-top: 20px; padding: 15px; background: #1a1a1a; border-radius: 8px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 16px; margin: 0;"> Payment: <strong>$<<print _task.pay>></strong> </p> <<if _taskType === "erotic">> <p style="color: #ff6b6b; font-size: 14px; margin: 5px 0 0 0;"> Refusing will result in reduced pay ($<<print Math.floor(_task.pay * 0.3)>>) </p> <</if>> </div> </div> <!-- Decision Options --> <<if _forcedAcceptance && _taskType === "erotic">> <!-- Forced Acceptance --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ff6b6b; font-size: 16px; text-align: center; margin: 0 0 15px 0; font-style: italic;"> <<if $mentalTraits.includes("Bimbo") && $mentalTraits.includes("Submissive")>> Your submissive nature and scattered thoughts make it impossible to refuse. You find yourself nodding automatically. <<else>> Something about the request makes you unable to say no. Your body moves on its own. <</if>> </p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Comply</div>">> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Secretary")>> <<run $jobsWorked.push("Secretary")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<goto _task.passage>> <</link>> </div> <<else>> <!-- Normal Choice --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 30px;"> <!-- Accept --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0; text-align: center;">✓ Accept</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Do as the mayor requests </p> <<if _taskType === "erotic">> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept Task</div>">> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Secretary")>> <<run $jobsWorked.push("Secretary")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<goto _task.passage>> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept Task</div>">> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Secretary")>> <<run $jobsWorked.push("Secretary")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<set $money += _task.pay>> <<run window.advanceTime(60)>> <<set $acceptedEroticTask = false>> <<goto "SecretaryTaskResult">> <</link>> <</if>> </div> <!-- Refuse --> <<if _taskType === "erotic">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; text-align: center;">✗ Refuse</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Politely decline </p> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Refuse Task</div>">> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Secretary")>> <<run $jobsWorked.push("Secretary")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<set $money += Math.floor(_task.pay * 0.3)>> <<run window.advanceTime(60)>> <<set $acceptedEroticTask = false>> <<set $refusedTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #666; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Office</div>">> <<goto "TownHall">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Initialize Sunfish counter if it doesn't exist --> <<if !$sunfishSightings>> <<set $sunfishSightings = 0>> <</if>> <!-- Initialize daily mayor work hours if it doesn't exist --> <<if !$mayorHoursWorkedToday>> <<set $mayorHoursWorkedToday = 0>> <</if>> <!-- Initialize mayor salary if it doesn't exist --> <<if !$mayorWeeklySalaryAvailable>> <<set $mayorWeeklySalaryAvailable = 0>> <</if>> <!-- Check for midnight Sunday Alter event (BEFORE time advances) --> <<set _currentHour = Math.floor($timeInMinutes / 60) % 24>> <<if $dayOfWeek === "Sunday" && _currentHour === 0 && random(1, 100) <= 10>> <<goto "TheAlter">> <</if>> <!-- Check for Sunfish trait event (1% chance) --> <<set _sunfishEvent = false>> <<if $skills.includes("Sunfish") && random(1, 100) === 1>> <<set _sunfishEvent = true>> <<set $sunfishSightings += 1>> <</if>> <!-- Check if going to The Alter --> <<if $sunfishSightings >= 10>> <<run setup.achievements.unlock("stalked_10_times")>> <<goto "TheAlter">> <</if>> <!-- Only advance time and increment hours if coming from outside (not from task result) --> <<set _justWorked = false>> <<if !$comingFromTaskResult>> <<run window.advanceTime(60)>> <<set $mayorHoursWorkedToday += 1>> <<set _justWorked = true>> <</if>> <<set $comingFromTaskResult = false>> <!-- Check for Corrupt trait gain (5% chance when completing 4th hour) --> <<set _gainedCorrupt = false>> <<if _justWorked && $mayorHoursWorkedToday === 4>> <<if random(1, 100) <= 5>> <<if !$mentalTraits.includes("Corrupt")>> <<set $mentalTraits.push("Corrupt")>> <<set _gainedCorrupt = true>> <</if>> <</if>> <</if>> <!-- Generate fake work task --> <<set _fakeWorkTasks = [ "create a comprehensive report on the city's imaginary budget surplus", "organize files that are already perfectly organized", "schedule meetings that will never actually happen", "proofread documents that don't need proofreading", "draft memos about initiatives that don't exist", "compile statistics on non-existent city projects", "review proposals that have already been approved", "research topics that aren't relevant to anything", "prepare presentations for cancelled meetings", "file paperwork in triplicate for no reason" ]>> <<set _assignedTask = _fakeWorkTasks.random()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">👑 Mayoral Duties</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> You sit in your luxurious office, contemplating what meaningless busywork to assign today. The leather chair is comfortable. The view is excellent. The salary is generous. </p> </div> <!-- Corrupt Trait Gained Notification --> <<if _gainedCorrupt>> <div style="background: #3a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255,107,107,0.3);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; text-align: center;">⚠️ TRAIT GAINED ⚠️</h3> <p style="color: #ff8787; font-size: 16px; margin: 0; text-align: center; font-weight: bold;"> You've gained the "Corrupt" trait! </p> <p style="color: #ffc9c9; font-size: 14px; margin: 10px 0 0 0; text-align: center; font-style: italic;"> All this power and no oversight... it's starting to affect you. </p> </div> <</if>> <!-- Sunfish Event --> <<if _sunfishEvent>> <div style="background: #1a3a4a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a9eff; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #4dabf7; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> For a brief moment, you catch a glimpse of something in your peripheral vision - a shadowy figure that appears to be made of several sunfish stacked in a trench coat. When you turn to look, there's nothing there. Just an empty corner of your office. </p> <p style="color: #74c0fc; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> (Strange sightings: $sunfishSightings/10) </p> </div> <</if>> <!-- Weekly Salary Withdrawal --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _ceMult = (typeof setup.hasCrowdsEye === "function" && setup.hasCrowdsEye()) ? 2 : 1>> <<set _baseSalary = $mayorWeeklySalaryAvailable>> <<set _displaySalary = (_baseSalary > 0 ? 5000 * _ceMult : 0) + (_pearlActive && _baseSalary > 0 ? 500 : 0)>> <<set _pearlBonus = _pearlActive && _baseSalary > 0 ? 500 : 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if $mayorWeeklySalaryAvailable > 0>>#51cf66<<else>>#666<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: <<if $mayorWeeklySalaryAvailable > 0>>#51cf66<<else>>#888<</if>>; margin-top: 0;">💰 Weekly Salary</h2> <<if _pearlActive && $mayorWeeklySalaryAvailable > 0>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 12px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #7dd3fc; box-shadow: 0 0 15px rgba(125, 211, 252, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> 🐚 The Pearl of Abundance increases your salary by $500! 🐚 </p> </div> <</if>> <<if _ceMult > 1 && $mayorWeeklySalaryAvailable > 0>> <div style="background: linear-gradient(135deg, #9d4edd 0%, #6a00b3 100%); padding: 12px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #b388ff; box-shadow: 0 0 15px rgba(157, 78, 221, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> 👁️ The Crowd's Eye doubles your salary! 👁️ </p> </div> <</if>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid <<if $mayorWeeklySalaryAvailable > 0>>#51cf66<<else>>#666<</if>>;"> <p style="color: #ccc; font-size: 18px; text-align: center; margin: 0 0 10px 0;"> Available to Withdraw: <strong style="color: <<if $mayorWeeklySalaryAvailable > 0>>#51cf66<<else>>#888<</if>>;">$<<print _displaySalary>></strong> <<if _pearlActive && $mayorWeeklySalaryAvailable > 0>> <span style="color: #7dd3fc; font-size: 14px;">(+$500)</span> <</if>> </p> <<if $mayorWeeklySalaryAvailable > 0>> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Your weekly salary of $<<print 5000 * _ceMult>> + Pearl Bonus $500 is ready to collect. </p> <<else>> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Your weekly salary of $<<print 5000 * _ceMult>> is ready to collect. </p> <</if>> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Withdraw Salary</div>">> <<if _pearlActive>> <<set $money += $mayorWeeklySalaryAvailable * _ceMult + 500>> <<else>> <<set $money += $mayorWeeklySalaryAvailable * _ceMult>> <</if>> <<set $mayorWeeklySalaryAvailable = 0>> <<goto "MayorWork">> <</link>> <<else>> <p style="color: #888; font-size: 14px; text-align: center; margin: 0; font-style: italic;"> Your next salary will be available on Monday. </p> <</if>> </div> </div> <!-- Work Completed --> <<if _justWorked>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #FFD700; margin-top: 0;">Task Assigned</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid #FFD700; text-align: center;"> <p style="color: #ccc; font-size: 16px; margin: 0; line-height: 1.6;"> You assigned your secretary to <strong style="color: #FFD700;"><<print _assignedTask>></strong>. </p> <p style="color: #888; font-size: 14px; margin: 15px 0 0 0; font-style: italic;"> They don't question it. They just nod and get to work on the pointless task. </p> </div> </div> <</if>> <!-- Hours Worked Today --> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid <<if $mayorHoursWorkedToday >= 4>>#ff6b6b<<else>>#4dabf7<</if>>;"> <p style="color: <<if $mayorHoursWorkedToday >= 4>>#ff6b6b<<else>>#4dabf7<</if>>; font-size: 18px; text-align: center; margin: 0;"> Hours "Worked" Today: <strong>$mayorHoursWorkedToday/4</strong> </p> <<if $mayorHoursWorkedToday >= 4>> <p style="color: #ffc107; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> You've reached your daily quota of appearing busy. </p> <</if>> </div> <!-- Action Buttons --> <<if $mayorHoursWorkedToday < 4>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 30px;"> <!-- Continue Working --> <div style="border: 3px solid #FFD700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #FFD700; margin: 0 0 10px 0; text-align: center;">🔄 Assign More Busywork</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Keep up appearances </p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Delegate More Work</div>">> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("City Mayor")>> <<run $jobsWorked.push("City Mayor")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<goto "MayorWork">> <</link>> </div> <!-- End Shift --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #888; margin: 0 0 10px 0; text-align: center;">🚪 End Shift</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Leave for the day </p> <<link "<div style='background: linear-gradient(135deg, #666 0%, #555 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Leave Office</div>">> <<goto "TownHall">> <</link>> </div> </div> <<else>> <!-- Daily Limit Reached --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; text-align: center;">Daily Work Limit Reached</h3> <p style="color: #ccc; text-align: center; margin: 0;"> You've already "worked" your 4 hours today. Time to go home and relax. </p> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #666 0%, #555 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Office</div>">> <<goto "TownHall">> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Town Hall</div>">> <<goto "TownHall">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("TheAlter")>> <<run $visitedLocations.push("TheAlter")>> <<run setup.achievements.unlock("find_altar")>> <</if>> <!-- Sunfish Cuff: Sunday witness scene (one-time, fires only Sunday 6:00-11:59) --> <<run setup.sunfishCuff.ensureState()>> <<if !$cuffSundayWitnessSeen && $dayOfWeek === "Sunday" && $timeInMinutes >= 360 && $timeInMinutes < 720>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; margin-bottom: 25px; box-shadow: 0 0 22px rgba(201,169,255,0.22);"> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> You step in and freeze. Someone is already kneeling at the Altar, candles guttering low. Red hair. A long, focused back. The smell of brine and chalk. </p> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> <em>Roisin Sullivan.</em> Whatever this is, she does not know you are here. You slip behind a column and hold your breath. </p> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> She is whispering something rhythmic at the floor. Then she stands, brushes off her knees, and walks past your hiding place without a glance. </p> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> Where she knelt, the stone has an old indented circle worn into it. Five empty notches ring its rim. Whatever was meant to sit here has been gone for a long time. </p> <p style="color: #c9a9ff; font-size: 13px; font-style: italic; margin: 0;"> Quest discovered: The Sunfish Artifact </p> </div> <<run State.variables.cuffSundayWitnessSeen = true>> <</if>> <!-- Sunfish Cuff: assemble + bind option (only when all 5 pieces collected and not yet bound) --> <<if setup.sunfishCuff.hasAllPieces() && !$sunfishCuffBound>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; margin-bottom: 25px; box-shadow: 0 0 22px rgba(201,169,255,0.3);"> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> You set the five pieces in the cradle, one by one. The bare band first, ringed by the four notches it was always meant to hold. Then the Disc Amulet, then the Dorsal Spire, then the Lunar Crescent. Last: the Eye Stone, set into the center of the disc. </p> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> The pieces shudder once and lock together. The artifact is whole. It is also still cold and inert, like a key with no lock yet found. </p> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.7; margin: 0 0 12px 0;"> You unfold a strand of red hair from your pocket. You have been around her enough to take it. You curl it around the Eye Stone and breathe over it. </p> <p style="color: #c9a9ff; font-size: 13px; font-style: italic; margin: 0 0 16px 0;"> The Eye Stone fills with someone else's pulse. The artifact knows whose body it answers to now. </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px 22px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Take the Artifact</div>">> <<run setup.sunfishCuff.ensureState(); State.variables.sunfishCuffAssembled = true; State.variables.sunfishCuffBound = true; State.variables.cuffRoisinTraceCollected = true;>> <<goto "TheAlter">> <</link>> </div> </div> <</if>> <<set $sunfishSightings = 0>> <div style="background: #0a1a2a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4fd1c5; text-align: center; text-shadow: 0 0 20px #4fd1c5, 0 0 40px #4fd1c5;">🐟 The Altar</h1> <<if $comingFromSunfishTank>> <!-- Special intro for transforming back from sunfish --> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a5a 0%, #0a2a4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4fd1c5; box-shadow: 0 8px 16px rgba(79, 209, 197, 0.3), 0 0 30px rgba(79, 209, 197, 0.2);"> <p style="color: #a5d8ff; font-size: 18px; margin: 0 0 15px 0; text-align: center; line-height: 1.6;"> You swim through the blue-green passage, drawn by an irresistible pull. The tunnel opens into a circular chamber carved from ancient stone, walls covered in intricate carvings of mola mola - ocean sunfish rendered in exquisite detail. </p> <p style="color: #a5d8ff; font-size: 18px; margin: 0; text-align: center; line-height: 1.6;"> The moment you enter, your body begins to shift. Your fins elongate into arms and legs, your flat body reshapes itself into human form. The transformation is swift and painless, guided by the ancient power of this place. </p> </div> <div style="background: #152535; padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4caf50; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 20px rgba(76, 175, 80, 0.3);"> <p style="color: #4caf50; font-size: 18px; margin: 0; text-align: center; font-weight: bold; text-shadow: 0 0 10px #4caf50;"> You're human again. </p> </div> <<set $comingFromSunfishTank = false>> <<elseif $comingFromParkPond>> <!-- Special intro for diving through the park pond --> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a5a 0%, #0a2a4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4fd1c5; box-shadow: 0 8px 16px rgba(79, 209, 197, 0.3), 0 0 30px rgba(79, 209, 197, 0.2);"> <p style="color: #a5d8ff; font-size: 18px; margin: 0 0 15px 0; text-align: center; line-height: 1.6;"> You plunge into the glowing pond. The water is impossibly warm, and instead of the muddy bottom you expected, you find yourself pulled deeper and deeper through luminescent currents. Fish-shaped shadows dart around you, guiding your descent. </p> <p style="color: #a5d8ff; font-size: 18px; margin: 0; text-align: center; line-height: 1.6;"> The watery tunnel opens suddenly into a circular chamber carved from ancient stone. You emerge dry, as if the water simply decided not to cling to you. The walls are covered in intricate carvings of mola mola - ocean sunfish rendered in exquisite detail, their eyes seeming to follow your every movement. </p> </div> <<set $comingFromParkPond = false>> <<else>> <!-- Normal Altar intro --> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a5a 0%, #0a2a4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4fd1c5; box-shadow: 0 8px 16px rgba(79, 209, 197, 0.3), 0 0 30px rgba(79, 209, 197, 0.2);"> <p style="color: #a5d8ff; font-size: 18px; margin: 0; text-align: center; line-height: 1.6;"> Reality shifts. The office dissolves into impossible geometry. You stand in a circular chamber carved from ancient stone, walls covered in intricate carvings of mola mola - ocean sunfish rendered in exquisite detail. </p> </div> <</if>> <div style="background: linear-gradient(135deg, #152535 0%, #0a1a2a 100%); padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4fd1c5; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px rgba(79, 209, 197, 0.4), inset 0 0 30px rgba(79, 209, 197, 0.1);"> <p style="color: #74c0fc; font-size: 16px; margin: 0 0 20px 0; text-align: center; text-shadow: 0 0 10px rgba(116, 192, 252, 0.5);"> In the center of the chamber sits a massive jewel, pulsing with an otherworldly turquoise light. Sunfish symbols swirl across its surface like living things, glowing with ethereal energy. </p> <p style="color: #4fd1c5; font-size: 16px; margin: 0; text-align: center; font-style: italic; text-shadow: 0 0 15px #4fd1c5;"> The jewel whispers to you: it hungers for essence. Sacrifice your traits, and it will grant you something in return. What that something is... you cannot know until the bargain is sealed. </p> </div> <!-- Trait Sacrifice Interface --> <<if !$altarSelectedTraits>> <<set $altarSelectedTraits = []>> <</if>> <<if State.length < 2 || State.history[State.length - 2].title !== "TheAlter">> <<set $altarPoints = 0>> <</if>> <div style="background: linear-gradient(135deg, #1a2a3a 0%, #0f1a2a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(156, 39, 176, 0.3);"> <h2 style="color: #9c27b0; text-align: center; margin: 0 0 20px 0; text-shadow: 0 0 15px #9c27b0;">⚗️ Trait Sacrifice</h2> <!-- Calculate available traits --> <<set _availableTraits = []>> <<set _physicalTraits = $physicalTraits || []>> <<set _mentalTraits = $mentalTraits || []>> <<set _skills = $skills || []>> <!-- Build forbidden traits set: event traits + all lab transformations --> <<set _forbiddenSacrifice = new Set(["Sunfish", "Blessed", "Wild", "Chosen", "Honey", "Cog", "Mystic", "Heart", "Guardian", "Darkness", "Alcoholic", "Disturbed", "Mirrored", "Thirsty", "Blood", "Burnt", "Inferno", "Scaled", "Divine Sunfish", "Electrified", "Totally not a Vampire", "Fish", "Fishing", "Advanced Angler", "Master Angler", "Fishimon Master", "Futanari"])>> <<run setup.combinationOnlyTraits.forEach(function(t) { _forbiddenSacrifice.add(t); })>> <!-- Add physical traits (excluding forbidden) --> <<for _i = 0; _i < _physicalTraits.length; _i++>> <<set _trait = _physicalTraits[_i]>> <<if !_forbiddenSacrifice.has(_trait)>> <<set _availableTraits.push({name: _trait, type: "physical", value: setup.getTraitValue("physical", _trait)})>> <</if>> <</for>> <!-- Add mental traits (excluding forbidden) --> <<for _i = 0; _i < _mentalTraits.length; _i++>> <<set _trait = _mentalTraits[_i]>> <<if !_forbiddenSacrifice.has(_trait)>> <<set _availableTraits.push({name: _trait, type: "mental", value: setup.getTraitValue("mental", _trait)})>> <</if>> <</for>> <!-- Add skills (excluding forbidden) --> <<for _i = 0; _i < _skills.length; _i++>> <<set _trait = _skills[_i]>> <<if !_forbiddenSacrifice.has(_trait)>> <<set _availableTraits.push({name: _trait, type: "skill", value: setup.getTraitValue("skill", _trait)})>> <</if>> <</for>> <!-- Calculate current total --> <<set _currentTotal = $altarPoints || 0>> <<for _i = 0; _i < $altarSelectedTraits.length; _i++>> <<set _currentTotal += $altarSelectedTraits[_i].value>> <</for>> <!-- Display current selection --> <div style="background: #0a1a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #4fd1c5; box-shadow: 0 0 20px rgba(79, 209, 197, 0.2);"> <p style="color: #4fd1c5; margin: 0 0 10px 0; font-weight: bold; text-shadow: 0 0 10px rgba(79, 209, 197, 0.5);">Selected Traits for Sacrifice:</p> <<if $altarSelectedTraits.length === 0>> <p style="color: #888; margin: 0; font-style: italic;">None selected</p> <<else>> <<for _i = 0; _i < $altarSelectedTraits.length; _i++>> <<capture _i>> <<set _selected = $altarSelectedTraits[_i]>> <div style="background: #152535; padding: 8px; border-radius: 4px; margin-bottom: 5px; display: flex; justify-content: space-between; align-items: center; border: 1px solid rgba(79, 209, 197, 0.3);"> <span style="color: #a5d8ff;">_selected.name (_selected.value points)</span> <<link "<span style='color: #ff6b6b; cursor: pointer;'>✖ Remove</span>">> <<set $altarSelectedTraits.deleteAt(_i)>> <<goto "TheAlter">> <</link>> </div> <</capture>> <</for>> <</if>> <<if $altarPoints > 0>> <p style="color: #ff922b; margin: 10px 0 0 0; font-weight: bold; text-shadow: 0 0 10px rgba(255, 146, 43, 0.5);">Offered fish: $altarPoints points</p> <</if>> <<if _currentTotal > 0>> <p style="color: #4caf50; margin: 15px 0 0 0; font-weight: bold; font-size: 18px; text-shadow: 0 0 10px rgba(76, 175, 80, 0.5);">Total Value: _currentTotal points</p> <</if>> </div> <!-- Available Traits List --> <div style="background: #0a1a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #666; max-height: 400px; overflow-y: auto; box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.5);"> <p style="color: #888; margin: 0 0 10px 0; font-weight: bold;">Available Traits:</p> <<if _availableTraits.length === 0>> <p style="color: #666; margin: 0; font-style: italic;">No traits available to sacrifice</p> <<else>> <<for _i = 0; _i < _availableTraits.length; _i++>> <<set _trait = _availableTraits[_i]>> <<set _alreadySelected = false>> <<for _j = 0; _j < $altarSelectedTraits.length; _j++>> <<if $altarSelectedTraits[_j].name === _trait.name>> <<set _alreadySelected = true>> <</if>> <</for>> <<if !_alreadySelected>> <<capture _trait>> <div style="background: #152535; padding: 8px; border-radius: 4px; margin-bottom: 5px; display: flex; justify-content: space-between; align-items: center; border: 1px solid rgba(102, 102, 102, 0.3);"> <span style="color: #a5d8ff;">_trait.name (_trait.value points)</span> <<link "<span style='color: #4caf50; cursor: pointer;'>✚ Add</span>">> <<run $altarSelectedTraits.push(_trait)>> <<goto "TheAlter">> <</link>> </div> <</capture>> <</if>> <</for>> <</if>> </div> <!-- Sacrifice Button --> <<if _currentTotal >= 50>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9c27b0 0%, #7b1fa2 100%); color: white; padding: 15px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.3), 0 0 25px rgba(156, 39, 176, 0.5); text-shadow: 0 0 10px rgba(255, 255, 255, 0.5);'>🔥 Perform Sacrifice (_currentTotal points)</div>">> <<set $altarSacrificeValue = _currentTotal>> <<goto "AltarSacrifice">> <</link>> </div> <<elseif _currentTotal > 0>> <p style="color: #ff6b6b; text-align: center; font-style: italic; text-shadow: 0 0 10px rgba(255, 107, 107, 0.3);">The jewel requires at least 50 points to accept your sacrifice (currently: _currentTotal)</p> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Alter")>> <h2 style="color: #4fd1c5; text-shadow: 0 0 15px #4fd1c5;">🌙 Visitors to the Altar</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: linear-gradient(135deg, #1a2a3a 0%, #0f1a2a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4fd1c5; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(79, 209, 197, 0.3);"> <p style="color: #74c0fc; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic; text-shadow: 0 0 10px rgba(116, 192, 252, 0.5);"> You sense another presence in this otherworldly space... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #4fd1c5; border-radius: 10px; padding: 15px; background: #0a1a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(79, 209, 197, 0.2);"> <h3 style="color: #4fd1c5; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(79, 209, 197, 0.5);">_npc.name</h3> <p style="font-size: 14px; color: #74c0fc; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #a5d8ff; font-size: 14px; margin: 5px 0;"><strong style="color: #4caf50;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: linear-gradient(135deg, #4fd1c5 0%, #339af0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 15px rgba(79, 209, 197, 0.3);'>💬 Speak with _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: linear-gradient(135deg, #1a2a3a 0%, #0f1a2a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #74c0fc; margin: 0; font-style: italic; text-shadow: 0 0 10px rgba(116, 192, 252, 0.3);"> You are alone in this sacred space. The jewel pulses with patient hunger. </p> </div> <</if>> <!-- Fish Offering Section (requires Offering skill - skill_53) --> <<if $unlockedSkills && $unlockedSkills.includes("skill_53")>> <div style="background: linear-gradient(135deg, #1a2a3a 0%, #0f1a2a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff922b; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(255, 146, 43, 0.3);"> <h2 style="color: #ff922b; text-align: center; margin: 0 0 20px 0; text-shadow: 0 0 15px #ff922b;">🐟 Fish Offering</h2> <p style="color: #a5d8ff; font-size: 14px; text-align: center; margin: 0 0 15px 0;">Offer rare fish to the jewel. Their essence adds to your sacrifice total. Epic: 10 pts | Legendary: 30 pts | Mythical: 100 pts</p> <<set _fishInv = $fishInventory || []>> <<set _offerableFish = []>> <<for _fi = 0; _fi < _fishInv.length; _fi++>> <<if _fishInv[_fi].rarity === "epic" || _fishInv[_fi].rarity === "legendary" || _fishInv[_fi].rarity === "mythical">> <<set _offerableFish.push({idx: _fi, fish: _fishInv[_fi]})>> <</if>> <</for>> <<if _offerableFish.length === 0>> <p style="color: #888; text-align: center; font-style: italic;">You have no epic, legendary, or mythical fish to offer.</p> <<else>> <div style="display: grid; gap: 8px; max-height: 300px; overflow-y: auto; padding: 5px;"> <<for _fi = 0; _fi < _fishInv.length; _fi++>> <<if _fishInv[_fi].rarity === "mythical">> <<capture _fi>> <div style="background: #152535; padding: 10px; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 1px solid #ff6b6b; margin-bottom: 6px;"> <span style="color: #ff6b6b; font-weight: bold;"><<= _fishInv[_fi].name>> (mythical)</span> <<link "<span style='background: linear-gradient(135deg, #ff922b 0%, #e8590c 100%); color: white; padding: 5px 12px; border-radius: 4px; font-weight: bold; font-size: 13px; cursor: pointer;'>Sacrifice (+100 pts)</span>">><<run setup.sacrificeFishAtIndex(_fi)>><<goto "TheAlter">><</link>> </div> <</capture>> <<elseif _fishInv[_fi].rarity === "legendary">> <<capture _fi>> <div style="background: #152535; padding: 10px; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 1px solid #ffd700; margin-bottom: 6px;"> <span style="color: #ffd700; font-weight: bold;"><<= _fishInv[_fi].name>> (legendary)</span> <<link "<span style='background: linear-gradient(135deg, #ff922b 0%, #e8590c 100%); color: white; padding: 5px 12px; border-radius: 4px; font-weight: bold; font-size: 13px; cursor: pointer;'>Sacrifice (+30 pts)</span>">><<run setup.sacrificeFishAtIndex(_fi)>><<goto "TheAlter">><</link>> </div> <</capture>> <<elseif _fishInv[_fi].rarity === "epic">> <<capture _fi>> <div style="background: #152535; padding: 10px; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 1px solid #c084fc; margin-bottom: 6px;"> <span style="color: #c084fc; font-weight: bold;"><<= _fishInv[_fi].name>> (epic)</span> <<link "<span style='background: linear-gradient(135deg, #ff922b 0%, #e8590c 100%); color: white; padding: 5px 12px; border-radius: 4px; font-weight: bold; font-size: 13px; cursor: pointer;'>Sacrifice (+10 pts)</span>">><<run setup.sacrificeFishAtIndex(_fi)>><<goto "TheAlter">><</link>> </div> <</capture>> <</if>> <</for>> </div> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4fd1c5 0%, #339af0 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.3), 0 0 20px rgba(79, 209, 197, 0.4); text-shadow: 0 0 8px rgba(255, 255, 255, 0.5);'>Leave The Altar</div>">> <<set $altarSelectedTraits = []>> <<goto "SeabassPark">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "lap">> <!-- Increase relationship with mayor --> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💋 Private Meeting</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> The mayor gestures to his lap with a knowing smile. "Come here, we have important city business to discuss..." </p> </div> <!-- Player Image --> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Lap.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="On the Mayor's Lap"> </div> <</if>> <!-- Detailed Erotic Description --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You slide onto the mayor's lap, your <<print $bodyParts.butt>> settling against his thighs. His hands immediately claim your waist, fingers digging into your <<if $physicalTraits.includes("Soft")>>soft<<elseif $physicalTraits.includes("Fit")>>toned<</if>> flesh possessively. </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Let's review the budget," he murmurs, though you feel his hardness growing beneath you. One hand slides along your stocking-clad thigh, pushing your skirt higher, while the other traces up your ribs<<if $bodyParts.chest !== "flat">>. His palm cups your <<print $bodyParts.chest>> breast through your blouse, thumb circling your nipple until it stiffens<</if>>. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> He grinds you down against his erection as he pretends to read documents, his breath hot against your neck. His hand slips higher up your thigh, fingers finding the dampness between your legs through your panties. "Such a dedicated secretary," he groans, fingers slipping beneath your blouse. You feel him throb against your ass as his other hand teases your <<print $bodyParts.genitals>>, making you squirm on his lap. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Let's review the budget," he murmurs, though you feel his hardness growing beneath you. One hand slides along your thigh, pushing your skirt higher. His other hand traces up your ribs<<if $bodyParts.chest !== "flat">>, palm cupping your <<print $bodyParts.chest>> chest through your blouse<</if>>. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> He grinds you down against his erection as he pretends to read documents, his breath hot against your neck. His hand slips higher up your thigh, discovering your own growing arousal beneath your skirt. "Interesting," he chuckles darkly, fingers wrapping around your <<print $bodyParts.genitals>> through the fabric. "My secretary seems to be enjoying this meeting." You feel him throb against your ass as his hands explore freely, stroking you while you're expected to maintain professional composure. </p> <</if>> <<if $physicalTraits.includes("Curvy") || $physicalTraits.includes("Voluptuous") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Hucow")>> <p style="color: #ffc107; font-size: 16px; line-height: 1.8; margin: 0;"> Your curves drive him wild. He grabs handfuls of your body greedily, groaning about how perfect you feel on his lap. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> As you grind on his lap, the mayor's hand slides between your thighs and discovers both your wetness and your hardening cock pressed against his leg. He groans deeply, wrapping his fingers around your shaft while his thumb slips inside your pussy. "My perfect secretary," he growls, working both at once, "with the best of everything." He rocks you harder against him, stroking your cock while fingering you, relishing the way your dual anatomy lets him pleasure you twice over. </p> <</if>> </div> <!-- Payment --> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> for this 'meeting' </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "desk">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💼 Under the Desk</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I have a very important meeting in ten minutes. Help me relieve some stress first..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Desk.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Under His Desk"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> He gestures beneath his mahogany desk. You sink to your knees on the plush carpet, crawling into the confined space between his spread legs. His bulge strains against his expensive slacks, already hard with anticipation. </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Good girl," he purrs, stroking your <<print $appearance.hairColor.toLowerCase()>> hair. His belt buckle clinks as he frees himself. You're face-to-face with his throbbing cock, thick and demanding. "Show me what a dedicated secretary you are." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Your lips wrap around him as he groans, one hand gripping your hair to guide you. He rocks his hips, pushing deeper. Above, you hear him answer his phone—discussing city budgets while you service him beneath his desk. Between your own legs, your <<print $bodyParts.genitals>> grows wet from the degradation. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Good girl," he purrs, stroking your <<print $appearance.hairColor.toLowerCase()>> hair. His belt buckle clinks as he frees himself. You're face-to-face with his throbbing cock—but when his hand slides down to grope you, he discovers your own hardness straining against your skirt. "Well, well," he chuckles darkly. "What do we have here?" </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Your lips wrap around him as he groans, one hand gripping your hair while the other reaches under your skirt to stroke your <<print $bodyParts.genitals>>. He rocks his hips, pushing deeper. Above, you hear him answer his phone—discussing city budgets while you service him beneath his desk, your own arousal throbbing in his grip. "My special secretary," he mutters. </p> <</if>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> His grip tightens as his voice remains professionally calm. "Yes, councilman... the proposal looks excellent..." He thrusts harder, using your mouth roughly. When he finally finishes, groaning quietly, he keeps you down there for several more minutes—his way of showing who's really in control. </p> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> While you service him under the desk, his foot slides between your spread knees, pressing against the bulge tenting your skirt. He feels your cock straining and your pussy soaking through your panties simultaneously. "Both holes wet for me already?" he murmurs into the phone, pretending it's part of the conversation. His shoe grinds against you, making your cock throb while your pussy clenches, the dual stimulation nearly making you choke on him. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "modeling">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">👙 Uniform Modeling</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I'm considering new uniforms for city employees. Model these options for me..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Model.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Modeling Outfits"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The "uniforms" become progressively more revealing. First, a tight pencil skirt and blouse. Then a dress that hugs every curve. Finally, lingerie barely passing as "professional attire"—lace and silk that leaves nothing to the imagination. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Each time you emerge from behind the changing screen, the mayor circles you slowly. His eyes devour every inch of exposed skin. "Turn around. Bend over. Walk toward me." His commands grow bolder, his bulge more obvious. </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if $bodyParts.chest !== "flat">>In the sheer lace bra, your <<print $bodyParts.chest>> breasts are fully visible, nipples hard from his hungry stare. <</if>>The matching panties barely cover your ass, the damp spot at your crotch revealing your arousal. He approaches, running his hands over the fabric—and what lies beneath. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "Perfect fit," he growls, pulling you against him. His erection presses into your stomach as he gropes you thoroughly, hands roaming over your nearly-naked body. His fingers slip beneath the lace panties, finding your wet <<print $bodyParts.genitals>>. "I think we need more 'testing' to ensure quality..." </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if $bodyParts.chest !== "flat">>In the sheer lace bra, your <<print $bodyParts.chest>> chest is fully visible. <</if>>The matching panties struggle to contain your growing arousal, your <<print $bodyParts.genitals>> straining obviously against the delicate fabric. His eyes widen with interest. "Interesting," he murmurs, approaching slowly. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "Perfect fit," he growls, pulling you against him. His erection presses into your stomach as he gropes you thoroughly, hands roaming over your nearly-naked body. One hand wraps around your hardness through the lace. "My secretary has some extra... equipment. How delightful." His fingers slip beneath the lace, stroking your <<print $bodyParts.genitals>> directly. "I think we need more 'testing' to ensure quality..." </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> The sheer lace panties hide nothing—your cock strains against the delicate fabric while a dark wet stain spreads from your pussy. The mayor's breath catches as he takes in the full picture. "Both," he whispers reverently, one hand cupping your balls through the lace while his other slides two fingers inside your soaking cunt. "You are the finest model I have ever employed." He strokes and fingers you at the same time, watching you squirm in the lingerie. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "massage">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💆 Stress Relief Massage</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I'm so tense from all this paperwork. Be a dear and help me relax..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Massage.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Massaging the Mayor"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You stand behind his chair, your hands working into his shoulders. He groans appreciatively, leaning back into your touch. "Lower," he instructs, and you comply, working down his back. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> As you lean forward to reach, he tilts his head back<<if $bodyParts.chest !== "flat">>—right between your breasts. You feel his breath on your cleavage as he "accidentally" nuzzles against your <<print $bodyParts.chest>> chest<</if>>. His hands reach back, grabbing your hips and pulling you closer. </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "You have magic hands," he purrs, spinning his chair around suddenly. Now you're standing between his spread legs, his face level with your body. His hands slide up the backs of your thighs, under your skirt, gripping your ass. "But I think I need a more... thorough massage." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> He pulls you down onto his lap, guiding your hands to his chest while his roam over your body. What started as a shoulder rub becomes something much more intimate, his arousal pressing insistently against you. His fingers slip beneath your panties, exploring your <<print $bodyParts.genitals>> as you gasp. </p> <<elseif setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> His hands explore eagerly between your thighs, discovering the familiar territory he loves—your slick pussy and your hardening cock together. "My favorite part of these massages," he groans, wrapping one hand around your shaft while his other fingers push inside your wet heat. He works you from both sides, his own erection grinding against your ass as he milks pleasure from every inch of your dual anatomy. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "You have magic hands," he purrs, spinning his chair around suddenly. Now you're standing between his spread legs, his face level with your body. His hands slide up the backs of your thighs, under your skirt, gripping your ass. "But I think I need a more... thorough massage." His hand discovers your stiffening arousal through your underwear. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> He pulls you down onto his lap, guiding your hands to his chest while his roam over your body. What started as a shoulder rub becomes something much more intimate. "My secretary has their own tension to work out," he growls, hand slipping beneath your skirt to stroke your <<print $bodyParts.genitals>> directly, matching the rhythm of his own arousal grinding against you. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "satisfaction">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">😈 Personal Satisfaction</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Lock the door. I have very specific needs that require your immediate attention." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Satisfaction.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Satisfying the Mayor"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The door clicks locked. The mayor is already unbuttoning her blouse, eyes dark with need. "Strip. Everything." Her voice brooks no argument. You obey, clothes falling to the floor until you stand naked before her. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She circles you hungrily, one finger trailing over your skin. "Perfect." She pushes you back onto her desk, scattering papers. Climbing on top of you, she positions herself above your hardening <<print $bodyParts.genitals>>. "I'm going to use you properly now." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She sinks down on you with a moan, taking you to the hilt. Her hips move frantically, using your body for her pleasure. She's wild, desperate—nails scratching your chest<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, hands groping your <<print $bodyParts.chest>> breasts<</if>>, riding you hard and fast. "Yes... fuck... just like that..." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She comes multiple times before she's satisfied, milking every drop from you. Afterwards, she dismounts calmly, adjusting her clothes. "Same time tomorrow," she says casually, as if she didn't just fuck you raw on her desk. </p> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> She rides your cock while reaching behind to finger your dripping pussy, her eyes rolling back as she feels you clench around her fingers while throbbing inside her. "God, I love that you have both," she gasps. "I can fuck you and finger you at the same time. No one else gives me this." She comes screaming, your cock buried deep while three fingers plunge into your cunt. </p> <</if>> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She circles you hungrily, one finger trailing over your skin, sliding between your legs to discover your <<print $bodyParts.genitals>>. Her eyes light up. "Oh, even better." She pushes you back onto her desk, scattering papers. Positioning herself between your spread legs, she grins wickedly. "I'm going to use you properly now." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Her mouth and fingers work you frantically, using your body for her pleasure. She's wild, desperate—nails digging into your thighs<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, one hand reaching up to grope your <<print $bodyParts.chest>> breasts<</if>>, tongue and fingers working you hard and fast. "Yes... taste so good... just like that..." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She makes you come multiple times before she's satisfied, wringing every orgasm from you. Afterwards, she stands calmly, adjusting her clothes and wiping her mouth. "Same time tomorrow," she says casually, as if she didn't just devour you on her desk. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "presentation">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">🎭 Private Presentation</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> The door locks with a decisive click. "Give me a show. Just for me..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Presentation.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Private Performance"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The mayor settles into his leather chair, already palming his growing erection through his slacks. "Strip. Slowly." His voice is thick with lust. Music plays softly from hidden speakers—your cue to perform. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You sway to the rhythm, unbuttoning your blouse with deliberate slowness. Each revealed inch of skin makes him grip the armrests tighter. The blouse falls. Your bra follows.<<if $bodyParts.chest !== "flat">> Your <<print $bodyParts.chest>> breasts bounce free, and he groans.<</if>> </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The skirt slides down your hips. You stand before him in just your panties and heels, gyrating, touching yourself as he watches hungrily. His cock is fully out now, his hand working it as he devours you with his eyes. The wet spot on your panties grows as you perform. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "Come here," he commands when you're completely naked. You straddle his lap, feeling his hardness between your thighs, pressing against your wet <<print $bodyParts.genitals>>. His hands grab your <<print $bodyParts.butt>> ass roughly, grinding you against him. "Such a perfect little performer. Now finish the show properly..." </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The skirt slides down your hips. You stand before him in just your panties and heels—but your own arousal is obvious, your <<print $bodyParts.genitals>> tenting the fabric. His eyes widen with surprise then darken with lust. "Well, well," he growls. His cock is fully out now, his hand working it as you continue to dance, your own hardness on display. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "Come here," he commands when you're completely naked, both of you fully exposed and hard. You straddle his lap, feeling his cock pressing against your ass while yours stands between you. His hands grab your <<print $bodyParts.butt>> ass roughly, grinding you against him, one hand wrapping around your <<print $bodyParts.genitals>>. "Such a perfect little performer. My special secretary. Now finish the show properly..." </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> As you strip for him, the big reveal draws a sharp intake of breath. Your cock hangs heavy between your thighs, already stiffening, while your pussy glistens with arousal. "The full package," he growls, stroking himself faster. He pulls you onto his lap facing outward so he can watch your cock bounce while he grinds against your wet cunt from behind. "Best performer in the city. Show me everything." </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "swimwear">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">🏊 Aquatics Review</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I'm reviewing the city pool initiative. Model these swimsuits for me..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Swimwear.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Modeling Swimwear"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The "swimsuits" are impossibly small—tight speedos that leave absolutely nothing to the imagination. You emerge from the bathroom, barely covered<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>—the speedo revealing not just your bulge but also your <<print $bodyParts.chest>> chest<</if>>, and the mayor's eyes go wide with hunger. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Turn around. Slowly." She circles you like a predator, drinking in every angle. The speedos cling to your body, outlining everything. <<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>Your <<print $bodyParts.chest>> chest is fully on display, and she licks her lips. <</if>><<if $physicalTraits.includes("Muscular") || $physicalTraits.includes("Athletic Build")>>Your muscles flex as you move, and she bites her lip.<</if>> </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Her hands reach out, tracing over the fabric—and your body beneath. "Very impressive," she purrs, palming your <<print $bodyParts.genitals>> through the thin material. You start to harden, the speedo doing nothing to hide your arousal. She strokes you through the fabric, watching you grow. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "I think we need to test... durability." She yanks the speedo down, freeing your erection. "On the desk. Now." She's on you before you can think, riding you hard while praising your "excellent fit for city standards." </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The "swimsuits" are impossibly small—a tiny bikini bottom that barely covers anything. You emerge from the bathroom, barely covered<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>—wearing just the bikini bottom, your <<print $bodyParts.chest>> chest completely exposed<</if>>, and the mayor's eyes go wide with hunger. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Turn around. Slowly." She circles you like a predator, drinking in every angle. The bikini bottom clings to your body, the fabric already damp. <<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>Your <<print $bodyParts.chest>> breasts are fully on display, and she licks her lips. <</if>><<if $physicalTraits.includes("Muscular") || $physicalTraits.includes("Athletic Build")>>Your muscles flex as you move, and she bites her lip.<</if>> </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Her hands reach out, tracing over the fabric—and your body beneath. "Very impressive," she purrs, fingers sliding beneath the bikini to find your wet <<print $bodyParts.genitals>>. You gasp as she touches you, the thin material providing no protection. She strokes you, making you wetter. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "I think we need to test... durability." She yanks the bikini aside, fingers pushing inside you. "On the desk. Now." She has you spread out before her, working you with hands and tongue while praising your "excellent fit for city standards." </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> The tiny swimsuit can barely contain you—your cock pushes obscenely against the fabric while the back rides between your dripping pussy lips. She traces the outline of your shaft through the material, then slips her hand around to feel your wetness. "Two for one," she purrs, yanking the suit aside to expose both. She wraps her lips around your cock while her fingers pump inside your cunt, moaning at the way your body offers her every pleasure at once. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "massage2">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💆 Private Massage</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I'm so tense. Those strong hands of yours... I need them on me." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Massage.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Massaging the Mayor"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The mayor lies face-down on her office couch, her blouse already unbuttoned and pulled aside. Your <<if $physicalTraits.includes("Strong")>>powerful<<elseif $physicalTraits.includes("Muscular")>>strong<</if>> hands work into her shoulders, kneading the tension from her muscles. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Lower," she moans. You work down her spine, and she reaches back to unhook her bra completely. "Don't be shy." Your hands slide over her bare back, feeling her skin warm beneath your touch. She arches into your massage, sighing with pleasure. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "The backs of my thighs too," she instructs, hiking up her skirt. Your hands move lower, massaging her legs. She spreads them slightly, giving you access. "Higher..." Your fingers brush against her panties, and you feel how wet she is. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She rolls over suddenly, bare-chested and flushed<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>. Her eyes widen as she sees your shirt has come off too, revealing your <<print $bodyParts.chest>> chest. "Interesting," she purrs, reaching up to touch you<</if>>. "I think the front needs attention now." She pulls you down on top of her, hands fumbling with your belt, discovering your hardening <<print $bodyParts.genitals>>. "Use those hands for something even better..." </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She rolls over suddenly, bare-chested and flushed<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>. Her eyes widen as she sees your shirt has come off too, revealing your <<print $bodyParts.chest>> chest. "Interesting," she purrs, reaching up to touch you<</if>>. "I think the front needs attention now." She pulls you down on top of her, hands fumbling with your pants. When she discovers your <<print $bodyParts.genitals>>, her eyes light up with delight. "Oh, this is even better than I imagined," she moans, fingers already exploring. "Use those hands on me while I use mine on you..." </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> She rolls you onto her couch and pulls your pants down, discovering both your stiffening cock and your wet pussy in one hungry glance. "I knew you were special," she moans, straddling you so she can grind her soaking cunt against your shaft while reaching behind to finger your pussy. Her body shudders against you as she rides your cock and fucks your cunt at the same time, the massage long forgotten. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "outfit">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">👗 Professional Attire</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I've selected a more appropriate outfit for my secretary. Go change." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Outfit.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="New Outfit"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The "professional" outfit turns out to be a scandal—a skirt so short it barely covers your ass, and a blouse cut low enough to show<<if $bodyParts.chest !== "flat">> generous cleavage<<else>> your flat chest provocatively<</if>>. Sheer stockings with garters complete the ensemble. The underwear provided is a mere scrap of lace that leaves nothing to the imagination. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The "professional" outfit turns out to be a scandal—a skirt so short it barely covers your ass, and a blouse cut provocatively<<if $bodyParts.chest !== "flat">> to show off your <<print $bodyParts.chest>> chest<</if>>. Sheer stockings with garters complete the ensemble. The underwear provided is impossibly tight, doing nothing to hide your <<print $bodyParts.genitals>> and everything to accentuate the bulge. </p> <</if>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> When you emerge from the bathroom, the mayor's eyes darken with lust. "Perfect. Come here." He has you bend over to "pick up" dropped papers, stand on tiptoe to reach high shelves, sit with your legs crossed and uncrossed repeatedly. </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Every movement is designed to show off your body. He circles you like prey, adjusting the blouse lower, smoothing the skirt higher. His hands linger everywhere—your hips, your thighs<<if $bodyParts.chest !== "flat">>, cupping your breasts to "fix the fit"<</if>>. When you bend over, you know he can see your barely-covered <<print $bodyParts.genitals>> through the flimsy panties. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "You'll wear this every day," he commands, pulling you against him. You feel his hardness pressing into your barely-covered ass. "My perfect little secretary." His hands slide under the skirt, fingers finding your wetness, exploring freely. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Every movement is designed to show off your body. He circles you like prey, adjusting the blouse, smoothing the skirt higher. His hands linger everywhere—your hips, your thighs<<if $bodyParts.chest !== "flat">>, groping your chest<</if>>. The tight underwear makes your arousal obvious, your <<print $bodyParts.genitals>> clearly outlined for his viewing pleasure. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "You'll wear this every day," he commands, pulling you against him. You feel his hardness pressing into your barely-covered ass, while yours presses against his thigh. "My perfect little secretary." His hands slide under the skirt, one gripping your ass while the other wraps around your <<print $bodyParts.genitals>>, stroking through the thin fabric. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> The scandalous outfit makes your dual anatomy impossible to hide. The tight skirt outlines your cock while the flimsy lace panties ride between your wet pussy lips. He hikes the skirt up, eyes feasting on the sight of both. "This outfit was made for you," he growls, one hand pumping your cock while his other slides two fingers inside your pussy. "Wear this every day. I want easy access to both." </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "fitness">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💪 Fitness Consultation</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Take off your shirt. I want to see your... physical conditioning." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Physique.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Showing Your Body"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You strip off your shirt, standing bare-chested before the mayor. Her eyes rake over your <<if $physicalTraits.includes("Muscular")>>sculpted muscles<<elseif $physicalTraits.includes("Fit")>>toned physique<<else>>body<</if>>, tongue darting out to wet her lips. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Come closer," sshe purrs. Her hands explore your chest<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, fingers tracing over your <<print $bodyParts.chest>> chest with particular interest. "How unexpected," she murmurs, cupping them<<else>>, tracing your pecs<</if>>, trailing down your abs. She circles you slowly, admiring every angle. Her fingers dig into your <<if $physicalTraits.includes("Strong")>>solid<</if>> muscles appreciatively. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She presses against your back, hands sliding around your waist, lower and lower. "Very impressive," she breathes in your ear. Her palms cup the bulge in your pants, squeezing your hardening <<print $bodyParts.genitals>>. "I want to see all of you. Everything." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> Soon you're completely naked as she examines you thoroughly, hands everywhere—gripping your ass, stroking your cock until you're rock hard<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, playing with your chest<</if>>. "Perfect specimen," she moans, pushing you back onto her desk. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She presses against your back, hands sliding around your waist, lower and lower. "Very impressive," she breathes in your ear. Her palms slide to your crotch, then pause with surprise. "Well now," she purrs with delight, fingers exploring the unexpected anatomy beneath your pants. "What a delightful surprise. I want to see all of you. Everything." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> Soon you're completely naked as she examines you thoroughly, hands everywhere—gripping your ass, fingers teasing your wet <<print $bodyParts.genitals>><<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, playing with your chest<</if>>. "Perfect specimen," she moans, spreading your legs wider. "Such a rare treat." She pushes you back onto her desk, hands already between your thighs. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> When you strip completely, she sees everything—your cock hanging thick between your thighs and your glistening pussy just behind it. Her jaw drops. "Now that is a physique," she breathes, dropping to her knees. She takes your cock in her mouth while sliding two fingers into your pussy from below, her other hand gripping your ass. She worships your dual anatomy like a masterpiece, sucking and fingering until your legs shake. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "strength">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💪 Strength Demonstration</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Show me how strong you really are. Lift me up..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Lift.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Lifting the Mayor"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You wrap your <<if $physicalTraits.includes("Muscular")>>powerful<<elseif $physicalTraits.includes("Strong")>>strong<</if>> arms around her waist and lift her effortlessly. She gasps, wrapping her legs around you instinctively. "Oh my..." Her face is level with yours now, breathing heavily. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Higher," she demands. You hoist her up, her legs tightening around your torso. She's grinding against you now, her skirt hiked up, feeling your strength<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>. Her hands find your <<print $bodyParts.chest>> chest through your shirt, squeezing<</if>>. "So strong..." She's getting wet, you can feel it through your shirt. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She kisses you hard, tongue invading your mouth. Her hands fumble with your belt while you hold her up. "Don't put me down," she orders breathlessly. You brace her against the wall, supporting her weight easily. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She frees your <<print $bodyParts.genitals>> and guides you inside her, moaning as you fill her. You fuck her standing up, using your strength to bounce her on your shaft. She clings to you, screaming her pleasure, loving how you manhandle her with such ease. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She kisses you hard, tongue invading your mouth. Her hands fumble with your pants while you hold her up. "Don't put me down," she orders breathlessly. When she discovers your <<print $bodyParts.genitals>>, she groans. "Oh fuck yes. Against the wall. Now." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> You brace her against the wall, supporting her weight easily while she works her hand between your legs, fingers pushing inside your wet heat. You grind against her hand, using your strength to control the pace. She clings to you, moaning her pleasure, loving how strong you are, how you can hold her up while she fingers you. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> You hold her pinned against the wall with your strength, her legs wrapped tight around your waist. She reaches between your bodies and finds your cock, rock-hard and dripping, while your pussy grinds wet against her thigh. "Fuck me with it," she begs, guiding your shaft inside her while her fingers reach behind to push into your soaking cunt. You thrust into her while being fucked from behind by her fingers, the dual sensation making you slam her harder against the wall. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "dictation">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">📝 Taking Dictation</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Sit close. I need you to take these notes personally..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Female_Dictation.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Taking Dictation"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You pull your chair next to his, notepad ready. But he pulls you even closer—so close your thigh presses against his, your shoulder touching his arm. His cologne fills your senses as he leans in, lips nearly brushing your ear. </p> <<if _hasVagina>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Regarding the city infrastructure project..." he begins, but his hand finds your knee, sliding slowly up your thigh. His whispers tickle your neck, making you shiver. The "dictation" becomes increasingly nonsensical as his hand ventures higher, fingers teasing the hem of your skirt before slipping beneath it to find your dampening panties. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if $bodyParts.chest !== "flat">>His other arm wraps around your back, hand cupping your breast through your blouse. He squeezes in rhythm with his words, thumb circling your nipple. <</if>>You try to write but your pen trembles as he touches you, fingers rubbing against your <<print $bodyParts.genitals>> through the thin fabric, his breath hot and heavy in your ear. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "Are you getting all this?" he growls, pulling you onto his lap. The notepad falls forgotten as he grinds you against his obvious arousal, his fingers pushing your panties aside to stroke you directly. "I think you need to take better notes. Much more... hands-on study." </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Regarding the city infrastructure project..." he begins, but his hand finds your knee, sliding slowly up your thigh. His whispers tickle your neck, making you shiver. The "dictation" becomes increasingly nonsensical as his hand ventures higher, fingers teasing the hem of your skirt before discovering your growing arousal straining against your underwear. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if $bodyParts.chest !== "flat">>His other arm wraps around your back, hand groping your <<print $bodyParts.chest>> chest. <</if>>You try to write but your pen trembles as he touches you, fingers wrapping around your <<print $bodyParts.genitals>> through the fabric, stroking in slow, deliberate movements, his breath hot and heavy in your ear. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "Are you getting all this?" he growls, pulling you onto his lap. The notepad falls forgotten as he grinds against your ass, his hand slipping beneath your underwear to stroke your hardness directly. "My secretary seems very... attentive today. I think you need to take better notes. Much more... hands-on study." </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> His hand slides under your skirt and discovers the full landscape—your cock already hard against your thigh, and your pussy soaking through your panties. He wraps his hand around your shaft while pressing his palm against your wet slit. "Take this down," he whispers, dictating gibberish while jerking you off and rubbing your clit simultaneously. Your pen scrawls nonsense as pleasure builds from both sources, his expert hands knowing exactly how to work everything you have. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "relief">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">😌 Stress Relief</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I need to unwind. Help me relax... properly." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Relief.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Providing Relief"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The mayor reclines on her office couch, hiking up her skirt. "Come here," she commands, spreading her legs. You kneel between her thighs, her scent filling your nose as she guides your head where she wants it. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Your tongue finds her wet heat, and she gasps, fingers tangling in your hair. "Yes... just like that..." She grinds against your face, using your mouth for her pleasure. Her thighs clamp around your head as you work. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She comes hard, crying out without caring who might hear. But she's not done. "Stand up. Take off your pants." When you're exposed, your <<print $bodyParts.genitals>> hard and ready, she pulls you down onto the couch with surprising strength. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She rides you aggressively, nails raking down your chest<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, groping your <<print $bodyParts.chest>> chest roughly<</if>>, taking her pleasure from your body. "Good boy," she purrs, moving faster. "Such a dedicated secretary..." You're just a toy for her relief. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> She comes hard, crying out without caring who might hear. But she's not done. "Stand up. Take off your pants." When you comply, she sees your wet <<print $bodyParts.genitals>> and grins wickedly. "Oh, this is even better," sshe purrs. She pulls you down onto the couch with surprising strength. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She positions herself between your legs, fingers and tongue working your <<print $bodyParts.genitals>> with skill. Her nails rake down your thighs<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>, one hand reaching up to grope your <<print $bodyParts.chest>> chest roughly<</if>>. "Good boy," she purrs against your sensitive flesh. "Such a dedicated secretary... with such a delicious surprise." She takes her pleasure from your body, making you come again and again until you're trembling. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> After you eat her out, she strips you and discovers your full anatomy. "God, you really do have it all," she moans, pushing you onto the couch. She mounts your cock reverse-cowgirl style, riding you while reaching behind to finger your dripping pussy. The dual stimulation has you screaming as she uses your body for her stress relief, coming hard around your shaft while your cunt clenches around her fingers. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "assistance">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">🔥 Intimate Assistance</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I need you. Right now. Don't make me wait..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Jobs/MayorSecretary/Male_Assist.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Assisting the Mayor"> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The mayor is already half-undressed when you enter, her need obvious. She practically attacks you, tearing at your clothes with desperate hands. "I've been thinking about you all morning," she pants, yanking your shirt off<<if $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">>. Her eyes widen when she sees your <<print $bodyParts.chest>> chest. "Perfect," she gasps, hands immediately cupping them<</if>>. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Your pants hit the floor and she's on her knees immediately, taking your <<print $bodyParts.genitals>> in her mouth. She sucks you hungrily, moaning around your length. Her hand works what doesn't fit, stroking and sucking until you're rock hard. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Bend me over the desk," she commands, standing. You comply, pushing her forward. She arches her back, presenting herself. "Fuck me hard. I need it rough." You grab her hips and thrust into her wet heat. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> You pound into her relentlessly, the desk shaking with each thrust. She screams your name, not caring who might hear. "Harder! Yes!" Her walls clench around you as she comes, but you keep going—giving her exactly what she demanded. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Your pants hit the floor and she gasps when she sees your <<print $bodyParts.genitals>>. "Even better," she groans, pushing you back onto her desk. She spreads your legs wide, positioning herself between them. Her mouth descends on you hungrily, tongue and lips working you with desperate need. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "So wet for me," she moans against you. Her fingers push inside while her tongue works your most sensitive spots. She's relentless, making you writhe and buck against her face. "I need to taste you come." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> She works you frantically, the desk creaking beneath you with each movement. You scream her name, not caring who might hear. "Yes! Don't stop!" Your body clenches around her fingers as you come, but she keeps going—giving you exactly what you both need, making you come again and again. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> She gasps when your pants come off, revealing both your throbbing cock and your dripping pussy. "You brought everything today," she purrs, shoving you onto the desk. She sinks down on your cock, riding you hard, while her hand snakes behind to plunge fingers into your cunt. The desk shakes as she fucks you from both ends, your cock buried in her while your pussy is stuffed with her fingers, the double penetration making you both scream. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "wardrobe">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">👔 Wardrobe Consultation</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Help me choose an outfit. I value your... close opinion." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <<if $bodyParts.gender === "male">> <img src="Images/Jobs/MayorSecretary/MaleMale_Wardrobe.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Wardrobe Consultation"> <<else>> <img src="Images/Jobs/MayorSecretary/FemaleFemale_Wardrobe.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Wardrobe Consultation"> <</if>> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You follow the mayor into the private changing room adjacent to the office. It's intimate—just the two of you in close quarters. The mayor strips without hesitation, completely comfortable being naked in front of you. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "What do you think of this one?" Each outfit requires your hands-on assessment—smoothing fabric, adjusting fits, standing close enough to smell the mayor's cologne. The touches linger, become more deliberate. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Your turn. I need to see how you look." The mayor insists you try on clothing too, hands roaming as they "help" you change. Fingers trail over your skin, adjusting collars, smoothing wrinkles, finding excuses to touch. When your pants come off, the mayor's eyes linger on your <<print $bodyParts.genitals>>. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> Soon you're pressed against the mirror, the mayor's body flush against yours, both of you hard and wanting. "I think we need to... test the durability," the mayor breathes, hand wrapping around both your cocks, stroking together. The consultation becomes something much more intimate. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Your turn. I need to see how you look." The mayor insists you try on clothing too, hands roaming as they "help" you change. Fingers trail over your skin, adjusting fabric, smoothing wrinkles, finding excuses to touch. When your pants come off, the mayor's eyes widen with surprise and delight at your <<print $bodyParts.genitals>>. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> Soon you're pressed against the mirror, the mayor's body flush against yours. "What a delightful surprise," the mayor breathes, fingers already sliding between your legs, exploring your wetness. "I think we need to... test compatibility." The consultation becomes something much more intimate as the mayor's fingers work inside you. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> In the cramped changing room, pressed against the mirror, the mayor discovers both your cock and your pussy when your pants come off. "Now I know exactly what to dress you in," the mayor murmurs, one hand wrapping around your shaft while the other cups your wet cunt. You watch your own reflection—flushed, moaning, both sets of genitals being worked expertly as the mayor strokes and fingers you against the glass. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "massage3">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💆 Private Massage Session</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I'm incredibly tense. Your hands... I need them on me." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <<if $bodyParts.gender === "male">> <img src="Images/Jobs/MayorSecretary/MaleMale_Massage.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Massage Session"> <<else>> <img src="Images/Jobs/MayorSecretary/FemaleFemale_Massage.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Massage Session"> <</if>> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The mayor lies on the office couch, already shirtless. "Start with my shoulders." Your hands work into tense muscles, kneading and pressing. The mayor groans appreciatively, body relaxing under your touch. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Lower... yes, there." You work down the spine, and the mayor shifts, making room for you to reach better. Your position is intimate now—straddling the mayor's hips to get better leverage. You feel body heat through your clothes. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "The front needs attention too," the mayor says, rolling over beneath you. Now you're straddling a half-naked mayor who's looking up at you with obvious desire. "Don't stop..." Hands reach up, pulling you down. You can feel both of you hardening, cocks pressing together through fabric. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> The massage becomes something else entirely. Lips meet in a heated kiss. Remaining clothes are torn away. Two bodies grinding together on the couch, hands everywhere, both your <<print $bodyParts.genitals>> hard and leaking, seeking pleasure rather than relaxation. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "The front needs attention too," the mayor says, rolling over beneath you. Now you're straddling a half-naked mayor who's looking up at you with obvious desire. "Don't stop..." Hands reach up, pulling you down, then sliding between your legs to discover your <<print $bodyParts.genitals>>. Eyes widen with surprise and hunger. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> The massage becomes something else entirely. Lips meet in a heated kiss. Remaining clothes are torn away. The mayor flips you onto your back, settling between your legs, mouth descending to taste your wetness while fingers work inside you, seeking pleasure rather than relaxation. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> As clothes come off on the couch, the mayor discovers your cock and pussy together. "Perfect," the mayor breathes, positioning you on all fours. A hand reaches beneath to stroke your hanging cock while the mayor's tongue pushes into your pussy from behind. You moan into the cushions as both are worked simultaneously, the massage oil making everything slick and sensitive, pleasure radiating from your cock and your cunt in equal measure. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "companionship">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">💕 Personal Companionship</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "I need more than just a secretary today. Keep me company. Close company." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <<if $bodyParts.gender === "male">> <img src="Images/Jobs/MayorSecretary/MaleMale_Companion.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Companionship"> <<else>> <img src="Images/Jobs/MayorSecretary/FemaleFemale_Companion.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Companionship"> <</if>> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The mayor pulls you down onto the leather couch, uncomfortably close. An arm drapes around your shoulders, fingers playing with your <<print $appearance.hairColor.toLowerCase()>> hair. "You're more than just an employee to me," the mayor murmurs. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The touching becomes bolder—a hand on your thigh, sliding higher. The mayor leans in, breath hot against your neck. "I've wanted this for so long..." Lips brush your skin, testing your reaction. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> When you don't pull away, the mayor becomes more aggressive. You're pulled into a deep kiss, tongue invading your mouth. Hands roam over your body, claiming, exploring. "You're so <<if $physicalTraits.includes("Attractive")>>beautiful<<else>>perfect<</if>>," the mayor groans, hand finding your hardening <<print $bodyParts.genitals>>. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> Clothes are stripped away piece by piece. The mayor's mouth trails down your body, hands everywhere at once. What started as companionship becomes raw need—two bodies moving together, cocks grinding, hands stroking, taking pleasure from each other without pretense. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> When you don't pull away, the mayor becomes more aggressive. You're pulled into a deep kiss, tongue invading your mouth. Hands roam over your body, claiming, exploring. When fingers slip between your legs and discover your <<print $bodyParts.genitals>>, the mayor gasps with delight. "Oh, this is perfect," the mayor breathes. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> Clothes are stripped away piece by piece. The mayor's mouth trails down your body, settling between your spread legs. What started as companionship becomes raw need—tongue and fingers working you expertly, taking pleasure from making you moan and writhe without pretense. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> On the couch together, the mayor's hand slides into your lap and finds everything waiting. Fingers curl around your hardening cock while a thumb traces circles on your wet clit. "You're so unique," the mayor whispers between kisses, slowly stroking your shaft while slipping two fingers into your pussy. "I could spend all day exploring you." The intimate companionship becomes raw worship of your dual anatomy. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "fashion">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">👗 Fashion Review</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Model these outfits for me. I want to see how they look on someone... attractive." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <<if $bodyParts.gender === "male">> <img src="Images/Jobs/MayorSecretary/MaleMale_Model.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Modeling"> <<else>> <img src="Images/Jobs/MayorSecretary/FemaleFemale_Model.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Modeling"> <</if>> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The outfits grow progressively more revealing. What starts as formal wear devolves into barely-there clothing that shows far too much skin. You change in the private bathroom, emerging each time to the mayor's hungry stare. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> "Turn around. Slowly." The mayor circles you, eyes devouring every inch. Hands reach out, adjusting fabric—or so the excuse goes. Really, it's just an opportunity to touch your body, to feel your <<if $physicalTraits.includes("Fit")>>toned<<elseif $physicalTraits.includes("Soft")>>soft<</if>> skin. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> By the final "outfit"—lingerie that barely counts as clothing—the mayor's arousal is obvious, matching your own. "Perfect fit," the mayor breathes, pulling you close. Hands slide over the thin fabric, both your cocks straining visibly against the delicate material. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "I think we need a more thorough examination." The lingerie is stripped away, and you're pressed against the wall. The mayor's mouth is on yours, hands groping, wrapping around both your hardnesses, stroking together while grinding against you. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> By the final "outfit"—lingerie that barely counts as clothing—the mayor's arousal is obvious. "Perfect fit," the mayor breathes, pulling you close. Hands slide over the thin fabric, then beneath it, discovering your wet <<print $bodyParts.genitals>> with obvious delight. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> "I think we need a more thorough examination." The lingerie is stripped away, and you're pressed against the wall. The mayor's mouth is on yours, hands groping, fingers pushing inside your heat while lips travel down your body to taste you directly. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> When the lingerie comes off, the mayor stares at your cock and pussy revealed together beneath the lace. "You look even better naked," the mayor growls, dropping to their knees. A mouth closes around your cock while fingers slide into your wet cunt, sucking and fingering you simultaneously. You arch against the wall, both sets of genitals being serviced at once as the mayor moans around your shaft, fingers pumping deep inside your pussy. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $currentEroticTask = "needs">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <<run setup.addRelationshipPoints(_mayorName, 1)>> <</if>> <!-- Check player genitals --> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center;">🔒 Special Needs</h1> <div style="padding: 20px; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #FFD700;"> <p style="color: white; font-size: 18px; margin: 0;"> "Lock the door. What I'm about to ask requires complete discretion..." </p> </div> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <<if $bodyParts.gender === "male">> <img src="Images/Jobs/MayorSecretary/MaleMale_Needs.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Special Needs"> <<else>> <img src="Images/Jobs/MayorSecretary/FemaleFemale_Needs.webp" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Special Needs"> <</if>> </div> <</if>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> The door clicks locked. The mayor's eyes are dark with need, voice thick with desire. "I've been thinking about this all week." Hands grab you roughly, pulling you close. "About you. About us." </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You're kissed hard, desperately. The mayor's hands are everywhere—tearing at your clothes, groping, claiming. "I need you naked. Now." There's no pretense anymore, no excuses. Just raw want. </p> <<if _hasPenis>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Soon you're both stripped bare, bodies pressed together. The mayor pushes you down—onto the desk, the couch, the floor—it doesn't matter. What matters is skin on skin, mouths tasting, hands wrapping around both your hard cocks, stroking together in desperate rhythm. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> The mayor takes you roughly, no holding back. Grinding, stroking, sucking—taking pleasure from every part of your body. It's intense, primal—two people giving in completely to forbidden desire. "Yes... god, yes..." The mayor's voice echoes in the office as pleasure consumes you both. </p> <<else>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Soon you're both stripped bare, bodies pressed together. When the mayor's hands slide between your legs and discover your <<print $bodyParts.genitals>>, the gasp is one of pure hunger. "Even better than I imagined," the mayor groans, pushing you down—onto the desk, the couch, the floor—it doesn't matter. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> The mayor devours you roughly, no holding back. Mouth, fingers, tongue—taking pleasure from every part of your body, making you writhe and scream. It's intense, primal—two people giving in completely to forbidden desire. "Yes... god, yes... so perfect..." The mayor's voice echoes in the office as pleasure consumes you both, making you come again and again. </p> <</if>> <<if setup.getFutaVariant()>> <p style="color: #e84393; font-size: 16px; line-height: 1.8; margin: 15px 0 0 0; font-style: italic;"> When your clothes hit the floor, the mayor sees your cock and pussy and loses all restraint. "Everything. I want everything." You're thrown down and devoured—mouth on your cock, fingers buried in your cunt, then switching, tongue lapping at your pussy while a hand pumps your shaft. The mayor takes you every way possible, using both your holes, making you come from your cock and your pussy alternately until neither of you can move, spent and satisfied on the office floor. </p> <</if>> </div> <<set $money += $currentTask.pay>> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0;"> You earned <strong>$<<print $currentTask.pay>></strong> </p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Work</div>">> <<set $acceptedEroticTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- SAVE CASH/BANK AT THE VERY START TO PREVENT DOUBLE ADDITIONS --> <<set _savedMoney = $money>> <<set _savedBankBalance = $bankAccount ? $bankAccount.balance : 0>> <!-- Initialize flags if they don't exist --> <<if !$acceptedEroticTask>> <<set $acceptedEroticTask = false>> <</if>> <<if !$refusedTask>> <<set $refusedTask = false>> <</if>> <!-- Ensure currentTask exists --> <<if !$currentTask>> <<set $currentTask = {pay: 30, desc: "complete miscellaneous office work"}>> <</if>> <!-- Initialize secretary hours tracking --> <<if !$secretaryHoursWorkedToday>> <<set $secretaryHoursWorkedToday = 0>> <</if>> <!-- Increment hours worked and advance time by 1 hour --> <<set $secretaryHoursWorkedToday += 1>> <<advancetime 60>> <!-- Initialize sexual skills if player has the trait but system isn't initialized --> <<if ($skills.includes("Sexually Skilled") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju")) && !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Relationship Point Gain System --> <<set _relationshipGained = false>> <<set _baseRelationshipPoints = 0>> <<set _finalRelationshipPoints = 0>> <<set _mayorName = "">> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<if _mayorNPCs && _mayorNPCs.length > 0>> <<set _mayorName = _mayorNPCs[0].name>> <!-- Calculate BASE relationship points based on task type --> <<if $acceptedEroticTask>> <<set _baseRelationshipPoints = 5>> <!-- Erotic task: 5 base points --> <<elseif !$refusedTask>> <<set _baseRelationshipPoints = 1>> <!-- Regular task: 1 base points --> <<else>> <<set _baseRelationshipPoints = -5>> <!-- Refused task: -1 points --> <</if>> <<set _finalRelationshipPoints = _baseRelationshipPoints>> <!-- Add the relationship points --> <<if _finalRelationshipPoints !== 0>> <<run setup.addRelationshipPoints(_mayorName, _finalRelationshipPoints)>> <<set _relationshipGained = true>> <</if>> <</if>> <!-- Sexual activity recovery: erotic tasks satisfy Slut/Raiju sexual needs and clear exhaustion (they recover via sex), and reset Cheshire Cat needs. --> <<if $acceptedEroticTask>> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <</if>> <!-- Sexual Skill XP Gain System --> <<set _sexualXPGains = []>> <<if ($skills.includes("Sexually Skilled") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus")) || $physicalTraits.includes("Slut") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Raiju")) && $acceptedEroticTask && $currentEroticTask>> <<set _hasVagina = $bodyParts.genitals.includes("vagina")>> <<set _hasPenis = $bodyParts.genitals.includes("penis")>> <<set _hasBreasts = false>> <!-- Check for small or bigger chest --> <<set _chestSizes = ["small", "medium", "large", "huge", "gigantic"]>> <<for _size range _chestSizes>> <<if $bodyParts.chest.includes(_size)>> <<set _hasBreasts = true>> <<break>> <</if>> <</for>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <!-- Apply XP based on which erotic task was completed --> <<if $currentEroticTask === "lap">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "massage">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "outfit">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "dictation">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "desk">> <<run setup.addSexualSkillExp("oralGiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Giving)", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<elseif $currentEroticTask === "modeling">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "presentation">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<if _hasBreasts>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "fitness">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<set _hasNonFlatChest = $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">> <<if _hasNonFlatChest>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<if _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "relief">> <<run setup.addSexualSkillExp("oralGiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Giving)", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<if _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "massage2">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<set _hasNonFlatChest = $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">> <<if _hasNonFlatChest>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<if _hasPenis>> <<run setup.addSexualSkillExp("vaginal", _finalXP)>> <<run _sexualXPGains.push({skill: "Vaginal", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "swimwear">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<set _hasNonFlatChest = $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">> <<if _hasNonFlatChest>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<if _hasPenis>> <<run setup.addSexualSkillExp("vaginal", _finalXP)>> <<run _sexualXPGains.push({skill: "Vaginal", amount: _finalXP})>> <<elseif _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "satisfaction">> <<run setup.addSexualSkillExp("submission", _finalXP)>> <<run _sexualXPGains.push({skill: "Submission", amount: _finalXP})>> <<set _hasNonFlatChest = $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">> <<if _hasNonFlatChest>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<if _hasPenis>> <<run setup.addSexualSkillExp("vaginal", _finalXP)>> <<run _sexualXPGains.push({skill: "Vaginal", amount: _finalXP})>> <<elseif _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "strength">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("stamina", _finalXP)>> <<run _sexualXPGains.push({skill: "Stamina", amount: _finalXP})>> <<set _hasNonFlatChest = $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">> <<if _hasNonFlatChest>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<if _hasPenis>> <<run setup.addSexualSkillExp("vaginal", _finalXP)>> <<run _sexualXPGains.push({skill: "Vaginal", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "assistance">> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <<run setup.addSexualSkillExp("rough", _finalXP)>> <<run _sexualXPGains.push({skill: "Rough", amount: _finalXP})>> <<set _hasNonFlatChest = $bodyParts.chest !== "flat" && $bodyParts.chest !== "flat masculine">> <<if _hasNonFlatChest>> <<run setup.addSexualSkillExp("titWorship", _finalXP)>> <<run _sexualXPGains.push({skill: "Tit Worship", amount: _finalXP})>> <</if>> <<if _hasPenis>> <<run setup.addSexualSkillExp("vaginal", _finalXP)>> <<run _sexualXPGains.push({skill: "Vaginal", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "wardrobe">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<if _hasPenis>> <<run setup.addSexualSkillExp("handjobs", _finalXP)>> <<run _sexualXPGains.push({skill: "Handjobs", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "companionship">> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualXPGains.push({skill: "Sensual", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<if _hasPenis>> <<run setup.addSexualSkillExp("handjobs", _finalXP)>> <<run _sexualXPGains.push({skill: "Handjobs", amount: _finalXP})>> <<elseif _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "massage3">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualXPGains.push({skill: "Sensual", amount: _finalXP})>> <<if _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "fashion">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualXPGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualXPGains.push({skill: "Teasing", amount: _finalXP})>> <<if _hasPenis>> <<run setup.addSexualSkillExp("handjobs", _finalXP)>> <<run _sexualXPGains.push({skill: "Handjobs", amount: _finalXP})>> <<elseif _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <<elseif $currentEroticTask === "needs">> <<run setup.addSexualSkillExp("rough", _finalXP)>> <<run _sexualXPGains.push({skill: "Rough", amount: _finalXP})>> <<if _hasPenis>> <<run setup.addSexualSkillExp("oralGiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Giving)", amount: _finalXP})>> <<elseif _hasVagina>> <<run setup.addSexualSkillExp("oralReceiving", _finalXP)>> <<run _sexualXPGains.push({skill: "Oral (Receiving)", amount: _finalXP})>> <</if>> <</if>> <</if>> <!-- Check if reached daily limit --> <<if $secretaryHoursWorkedToday >= 8>> <<set $showWorkLimitNext = true>> <</if>> <!-- Calculate base pay with Pearl of Abundance bonus --> <<set _basePay = $currentTask.pay>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_basePay * 0.5)>> <<set _basePay = _basePay + _pearlBonus>> <</if>> <!-- Check if player has bank account for direct deposit --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<set _totalDeposited = 0>> <!-- RESTORE CASH/BANK TO PREVENT DOUBLE ADDITIONS FROM ANY HELPER FUNCTIONS --> <<set $money = _savedMoney>> <<if $bankAccount>> <<set $bankAccount.balance = _savedBankBalance>> <</if>> <<if _hasBankAccount>> <!-- Calculate 5% direct deposit bonus --> <<set _creditBonus = Math.floor(_basePay * 0.05)>> <<set _totalDeposited = _basePay + _creditBonus>> <!-- Add directly to bank account --> <<set $bankAccount.balance += _totalDeposited>> <<else>> <!-- No bank account - pay base in cash --> <<set $money += _basePay>> <</if>> <!-- Lucky bonus money check (ALWAYS GOES TO CASH) --> <<set _bonusMoneyChance = 3>> <<if $mentalTraits.includes("Lucky") || $physicalTraits.includes("Cerberus") || $physicalTraits.includes("Cupid") || $physicalTraits.includes("Cheshire Cat")>> <<set _bonusMoneyChance = 10>> <<elseif $mentalTraits.includes("Unlucky") || $mentalTraits.includes("Bad Luck")>> <<set _bonusMoneyChance = 0>> <</if>> <<set _bonusMoney = 0>> <<if random(1, 100) <= _bonusMoneyChance>> <<set _bonusMoney = random(50, 150)>> <<set $money += _bonusMoney>> <!-- Bonus money ALWAYS goes to cash --> <</if>> <!-- Trait gain system --> <<set _traitGained = false>> <<set _gainedTraitName = "">> <<set _replacedTrait = "">> <<set _isSkill = false>> <<if random(1, 100) <= 3>> <<if $acceptedEroticTask>> <!-- Erotic task trait pool --> <<set _eroticTraitPool = { physical: ["Graceful", "Fashionable"], mental: ["Customer-Focused", "Soft-Spoken", "Hushed Intimate Voice", "Loyal", "High Stamina", "Flirty", "Seductive", "Alluring", "Perfectionist", "Perverted", "Hardworking", "Quick Learner"], skills: ["Sexually Skilled", "Modeling", "Makeup"] }>> <!-- Flatten into single array with type info --> <<set _availableTraits = []>> <<for _pt range _eroticTraitPool.physical>> <<run _availableTraits.push({name: _pt, type: "physical"})>> <</for>> <<for _mt range _eroticTraitPool.mental>> <<run _availableTraits.push({name: _mt, type: "mental"})>> <</for>> <<for _st range _eroticTraitPool.skills>> <<run _availableTraits.push({name: _st, type: "skill"})>> <</for>> <<set _chosenTrait = _availableTraits.random()>> <<elseif !$refusedTask>> <!-- Regular task trait pool --> <<set _regularTraitPool = { mental: ["Perceptive", "Detail-Oriented", "Punctual", "Friendly Tone", "Clear Pronunciation", "Diplomatic", "Organized", "Resourceful", "Focused", "Determined", "Considerate", "Polite", "Reassuring", "Direct", "Efficient", "Workaholic", "Warm", "Logical", "Patient", "Intelligent", "Quick Learner"], skills: ["Public Speaking", "Accounting", "Customer Service"] }>> <!-- Flatten into single array with type info --> <<set _availableTraits = []>> <<for _mt range _regularTraitPool.mental>> <<run _availableTraits.push({name: _mt, type: "mental"})>> <</for>> <<for _st range _regularTraitPool.skills>> <<run _availableTraits.push({name: _st, type: "skill"})>> <</for>> <<set _chosenTrait = _availableTraits.random()>> <</if>> <!-- Process trait gain if one was selected --> <<if _chosenTrait>> <<if _chosenTrait.type === "skill">> <!-- Check if player already has this skill --> <<if !$skills.includes(_chosenTrait.name)>> <<run $skills.push(_chosenTrait.name)>> <<set _traitGained = true>> <<set _gainedTraitName = _chosenTrait.name>> <<set _isSkill = true>> <!-- Initialize sexual skills if Sexually Skilled was just gained --> <<if _chosenTrait.name === "Sexually Skilled">> <<run setup.initializeSexualSkills()>> <</if>> <</if>> <<elseif _chosenTrait.type === "physical">> <!-- Check for conflicts in physical traits --> <<if !$physicalTraits.includes(_chosenTrait.name)>> <<set _conflict = setup.getConflictingTrait(_chosenTrait.name, $physicalTraits)>> <<if _conflict>> <<run $physicalTraits.delete(_conflict)>> <<set _replacedTrait = _conflict>> <</if>> <<run $physicalTraits.push(_chosenTrait.name)>> <<set _traitGained = true>> <<set _gainedTraitName = _chosenTrait.name>> <</if>> <<elseif _chosenTrait.type === "mental">> <!-- Check for conflicts in mental traits --> <<if !$mentalTraits.includes(_chosenTrait.name)>> <<set _conflict = setup.getConflictingTrait(_chosenTrait.name, $mentalTraits)>> <<if _conflict>> <<run $mentalTraits.delete(_conflict)>> <<set _replacedTrait = _conflict>> <</if>> <<run $mentalTraits.push(_chosenTrait.name)>> <<set _traitGained = true>> <<set _gainedTraitName = _chosenTrait.name>> <</if>> <</if>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">✓ Task Complete</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> <<if $acceptedEroticTask>> You've fulfilled the mayor's request. The office door unlocks with a soft click as the mayor dismisses you with a satisfied smile. <<elseif $refusedTask>> You politely but firmly declined the mayor's request. The mayor looks disappointed but waves you away dismissively, handing you a reduced payment. <<else>> You complete the task efficiently and professionally. The mayor nods in approval, satisfied with your work. <</if>> </p> </div> <!-- Relationship Change Display --> <<if _relationshipGained && _mayorName !== "">> <<if $relationships[_mayorName]>> <<if $refusedTask>> <div style="background: linear-gradient(135deg, #2a0a0a 0%, #1a0505 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 0 25px rgba(255, 107, 107, 0.4); text-align: center; animation: pulse-red 2s infinite;"> <p style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(255, 107, 107, 0.6);"> 💔 Relationship Damaged </p> <p style="color: #ff8787; font-size: 16px; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Your relationship with <<print _mayorName>> has suffered. </p> <p style="color: #ff6b6b; font-size: 20px; font-weight: bold; margin: 10px 0 0 0;"> <<print _finalRelationshipPoints>> Relationship Points </p> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> (Level <<print $relationships[_mayorName].level>>, <<print $relationships[_mayorName].points>> points) </p> </div> <style> @keyframes pulse-red { 0%, 100% { box-shadow: 0 0 25px rgba(255, 107, 107, 0.4); } 50% { box-shadow: 0 0 35px rgba(255, 107, 107, 0.7); } } </style> <<else>> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 0 25px rgba(81, 207, 102, 0.4); text-align: center; animation: pulse-green 2s infinite;"> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(81, 207, 102, 0.6);"> 💕 Connection Deepened </p> <p style="color: #4ade80; font-size: 16px; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Your relationship with <<print _mayorName>> has improved! <<if ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #e91e63;">(💖 8x Bonus!)</span> <</if>> </p> <p style="color: #51cf66; font-size: 20px; font-weight: bold; margin: 10px 0 0 0;"> +<<print _finalRelationshipPoints>> Relationship Points </p> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> (Level <<print $relationships[_mayorName].level>>, <<print $relationships[_mayorName].points>> points) </p> </div> <style> @keyframes pulse-green { 0%, 100% { box-shadow: 0 0 25px rgba(81, 207, 102, 0.4); } 50% { box-shadow: 0 0 35px rgba(81, 207, 102, 0.7); } } </style> <</if>> <</if>> <</if>> <!-- Aftermath based on task type --> <<if $acceptedEroticTask>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #FFD700; margin-top: 0; text-align: center;">💋 Intimate Service Rendered</h2> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> You straighten your clothes and catch your breath. The mayor is already back at work, as if nothing happened. But the knowing glances say otherwise. </p> </div> <<elseif $refusedTask>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin-top: 0; text-align: center;">✗ Request Declined</h2> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> The atmosphere is awkward. The mayor clearly expected compliance. Your refusal has been noted, and the reduced payment reflects their displeasure. </p> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #9b59b6; margin-top: 0; text-align: center;">✓ Professional Task Completed</h2> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> Another task done. The work is straightforward, if unremarkable. The mayor thanks you and returns to their paperwork. </p> </div> <</if>> <!-- Sexual XP Gained Event --> <<if _sexualXPGains.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h2 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if _sexSkillXPBonus > 0>> <span style="color: #CE93D8;">⭐ +<<print _sexSkillXPBonus>></span> <</if>> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-top: 15px;"> <<for _xp range _sexualXPGains>> <div style="background: #1a1a1a; padding: 10px; border-radius: 8px; border: 2px solid #ff69b4; text-align: center;"> <p style="color: #ff69b4; font-size: 14px; font-weight: bold; margin: 0;"><<print _xp.skill>></p> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 5px 0 0 0;">+<<print _xp.amount>> XP</p> </div> <</for>> </div> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 15px 0 0 0; font-style: italic;"> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> The Basking Charm amplifies every sensation, every lesson learned... <<else>> Your intimate experiences are refining your skills... <</if>> </p> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- Trait Gained Event --> <<if _traitGained>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 8px 16px rgba(81, 207, 102, 0.3); animation: glow 2s infinite;"> <h2 style="color: #51cf66; margin-top: 0; text-align: center;">✨ New <<if _isSkill>>Skill<<else>>Trait<</if>> Gained!</h2> <p style="color: #51cf66; font-size: 20px; text-align: center; margin: 0 0 10px 0; font-weight: bold;"> <<if _isSkill>>🎯<<elseif _chosenTrait.type === "physical">>💪<<else>>🧠<</if>> _gainedTraitName </p> <<if _replacedTrait !== "">> <p style="color: #ff6b6b; font-size: 14px; text-align: center; margin: 0 0 10px 0;"> (Replaced: _replacedTrait) </p> <</if>> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> <<if $acceptedEroticTask>> The intimate work is changing you in unexpected ways... <<else>> Your professional dedication is paying off! <</if>> </p> </div> <style> @keyframes glow { 0%, 100% { box-shadow: 0 8px 16px rgba(81, 207, 102, 0.3); } 50% { box-shadow: 0 8px 24px rgba(81, 207, 102, 0.6); } } </style> <</if>> <!-- Bonus Money Event (ALWAYS CASH) --> <<if _bonusMoney > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 8px 16px rgba(255, 215, 0, 0.3); animation: pulse 2s infinite;"> <h2 style="color: #FFD700; margin-top: 0; text-align: center;">💰 Unexpected Cash Bonus!</h2> <p style="color: #51cf66; font-size: 18px; text-align: center; margin: 0 0 10px 0; font-weight: bold;"> +$<<print _bonusMoney>> (Cash) </p> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> <<if $acceptedEroticTask>> "For going above and beyond," the mayor says with a wink, sliding extra cash across the desk. <<else>> "You've been doing excellent work lately," the mayor says, handing you extra cash with a smile. <</if>> </p> <<if $mentalTraits.includes("Lucky")>> <p style="color: #ffc107; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> Your luck really pays off sometimes! </p> <</if>> </div> <style> @keyframes pulse { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 215, 0, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 215, 0, 0.6); } } </style> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your base earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Credit Bonus Notification --> <<if _hasBankAccount && _creditBonus > 0>> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #667eea; box-shadow: 0 0 20px rgba(102, 126, 234, 0.4); animation: pulse-credit 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 💳 Direct Deposit Bonus: +<<print setup.formatMoney(_creditBonus)>> (5%)! 💳 </p> </div> <style> @keyframes pulse-credit { 0%, 100% { box-shadow: 0 0 20px rgba(102, 126, 234, 0.4); } 50% { box-shadow: 0 0 30px rgba(102, 126, 234, 0.7); } } </style> <</if>> <!-- Payment Summary --> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #51cf66;"> <h3 style="color: #51cf66; margin-top: 0; text-align: center;">💰 Payment Summary</h3> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #aaa; margin: 0 0 10px 0; text-align: center; font-size: 14px;">Base Task Pay:</p> <<if _pearlActive>> <p style="color: #51cf66; margin: 0; text-align: center; font-size: 20px; font-weight: bold;"> <<print setup.formatMoney(_basePay)>> <span style="color: #7dd3fc; font-size: 14px;">(+50% Pearl)</span> </p> <p style="color: #aaa; margin: 5px 0 0 0; text-align: center; font-size: 12px;"> Original: <<print setup.formatMoney($currentTask.pay)>> + Pearl: <span style="color: #7dd3fc;"><<print setup.formatMoney(_pearlBonus)>></span> </p> <<else>> <p style="color: #51cf66; margin: 0; text-align: center; font-size: 20px; font-weight: bold;"> <<print setup.formatMoney(_basePay)>> </p> <</if>> </div> <<if _hasBankAccount>> <!-- Show direct deposit breakdown --> <div style="background: #2a2a4a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #667eea;"> <p style="color: #667eea; margin: 0 0 10px 0; font-size: 16px; font-weight: bold; text-align: center;">💳 Direct Deposit to Bank</p> <<if _creditBonus > 0>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 10px;"> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 13px;">Base Deposit:</p> <p style="color: #51cf66; margin: 0; font-size: 18px; font-weight: bold;"><<print setup.formatMoney(_basePay)>></p> </div> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 13px;">Credit Bonus (5%):</p> <p style="color: #667eea; margin: 0; font-size: 18px; font-weight: bold;">+<<print setup.formatMoney(_creditBonus)>></p> </div> </div> <hr style="border: 0; border-top: 1px solid #667eea; margin: 10px 0;"> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Total Deposited:</p> <p style="color: #51cf66; margin: 0; font-size: 22px; font-weight: bold;"><<print setup.formatMoney(_totalDeposited)>></p> </div> <<else>> <div style="text-align: center; margin-top: 10px;"> <p style="color: #51cf66; margin: 0; font-size: 22px; font-weight: bold;"><<print setup.formatMoney(_basePay)>> deposited</p> </div> <</if>> </div> <<else>> <!-- Cash payment only --> <div style="background: #2a4a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #51cf66;"> <p style="color: #51cf66; margin: 0 0 10px 0; font-size: 16px; font-weight: bold; text-align: center;">💵 Paid in Cash</p> <div style="text-align: center; margin-top: 10px;"> <p style="color: #51cf66; margin: 0; font-size: 22px; font-weight: bold;"><<print setup.formatMoney(_basePay)>></p> </div> <p style="color: #ffc107; margin: 10px 0 0 0; font-size: 13px; text-align: center;"> 💡 Open a bank account to receive a 5% direct deposit bonus! </p> </div> <</if>> <<if _bonusMoney > 0>> <!-- Bonus money (always cash) --> <div style="background: #4a3a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #FFD700;"> <p style="color: #FFD700; margin: 0 0 10px 0; font-size: 16px; font-weight: bold; text-align: center;">💵 Lucky Bonus (Cash)</p> <div style="text-align: center;"> <p style="color: #FFD700; margin: 0; font-size: 20px; font-weight: bold;">+<<print setup.formatMoney(_bonusMoney)>></p> </div> </div> <</if>> <hr style="border: 0; border-top: 1px solid #666; margin: 15px 0;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Cash on Hand:</p> <p style="color: #51cf66; margin: 0; font-size: 20px; font-weight: bold;"><<print setup.formatMoney($money)>></p> </div> <<if _hasBankAccount>> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Bank Balance:</p> <p style="color: #667eea; margin: 0; font-size: 20px; font-weight: bold;"><<print setup.formatMoney($bankAccount.balance)>></p> </div> <</if>> </div> <<if _hasBankAccount>> <div style="text-align: center; margin-top: 10px; padding-top: 10px; border-top: 1px solid #666;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Total Funds:</p> <p style="color: #ffd43b; margin: 0; font-size: 24px; font-weight: bold;"><<print setup.formatMoney($money + $bankAccount.balance)>></p> </div> <</if>> <div style="text-align: center; margin-top: 15px;"> <p style="color: #4dabf7; font-size: 14px; margin: 0;"> Hours worked today: <strong>$secretaryHoursWorkedToday/8</strong> </p> </div> </div> <!-- Action Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 30px;"> <!-- Continue Working --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 10px 0; text-align: center;">🔄 Continue Working</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> See if the mayor has more tasks </p> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Keep Working</div>">> <<set $acceptedEroticTask = false>> <<set $refusedTask = false>> <<if $showWorkLimitNext>> <<set $showWorkLimitNext = false>> <<goto "SecretaryWorkLimitReached">> <<else>> <<goto "SecretarySpecialTasks">> <</if>> <</link>> </div> <!-- End Shift --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #888; margin: 0 0 10px 0; text-align: center;">🚪 End Shift</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Leave Town Hall for the day </p> <<link "<div style='background: linear-gradient(135deg, #666 0%, #555 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Leave</div>">> <<set $acceptedEroticTask = false>> <<set $refusedTask = false>> <<goto "TownHall">> <</link>> </div> </div> <!-- Quick Navigation --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Return to Secretary Work</div>">> <<set $acceptedEroticTask = false>> <<set $refusedTask = false>> <<goto "SecretaryWork">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; align-items: center; justify-content: center;"> <div style="max-width: 700px; width: 100%;"> <div style="background: #2a1a1a; padding: 30px; border-radius: 15px; border: 3px solid #ff6b6b; box-shadow: 0 8px 16px rgba(255, 107, 107, 0.4);"> <h1 style="color: #ff6b6b; text-align: center; margin: 0 0 20px 0;">⚠️ Content Warning</h1> <div style="background: #1a1a1a; padding: 25px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <strong style="color: #ff6b6b;">Warning:</strong> The Mayor's Secretary job contains explicit adult content. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> This job involves sexual scenarios that may include: </p> <ul style="color: #aaa; font-size: 15px; line-height: 1.6; margin: 0 0 15px 20px;"> <li>Explicit sexual content and descriptions</li> <li>Workplace power dynamics</li> <li>Sexual harassment themes</li> <li>Adult situations across various gender combinations</li> <li>Coercion (with certain character traits)</li> </ul> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> This content is intended for mature audiences only. You can refuse inappropriate requests from the mayor, though this may affect your payment. </p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px;"> <!-- Continue --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #1a2a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0; text-align: center;">✓ I Understand</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Continue to work </p> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Proceed</div>">> <<set $hasSeenSecretaryWarning = true>> <<goto "SecretaryWork">> <</link>> </div> <!-- Go Back --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #888; margin: 0 0 10px 0; text-align: center;">✗ Go Back</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Return to Town Hall </p> <<link "<div style='background: linear-gradient(135deg, #666 0%, #555 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Leave</div>">> <<goto "TownHall">> <</link>> </div> </div> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Initialize Sunfish counter if it doesn't exist --> <<if !$sunfishSightings>> <<set $sunfishSightings = 0>> <</if>> <!-- Get Mayor's Gender --> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<set _mayorGender = "unknown">> <<if _mayorNPCs.length > 0>> <<set _mayorGender = _mayorNPCs[0].bodyParts.gender>> <</if>> <!-- Calculate Attractiveness Score --> <<set _attractiveTraits = ["Attractive", "Curvy", "Voluptuous", "Charming", "Seductive", "Alluring", "Flirty", "Smooth Skin", "Youthful", "Graceful", "Fashionable", "Warm", "Charismatic Voice", "Smooth Voice"]>> <<set _masculineTraits = ["Muscular", "Broad-shouldered", "Strong", "Athletic Build", "Sturdy", "Jock", "Fit", "Lean"]>> <<set _feminineTraits = ["Curvy", "Voluptuous", "Soft", "Graceful", "Petite", "Youthful", "Smooth Skin"]>> <<set _attractivenessScore = 0>> <<set _masculinityScore = 0>> <<set _femininityScore = 0>> <<for _trait range _attractiveTraits>> <<if $physicalTraits.includes(_trait) || $mentalTraits.includes(_trait)>> <<set _attractivenessScore += 1>> <</if>> <</for>> <<for _trait range _masculineTraits>> <<if $physicalTraits.includes(_trait)>> <<set _masculinityScore += 1>> <</if>> <</for>> <<for _trait range _feminineTraits>> <<if $physicalTraits.includes(_trait)>> <<set _femininityScore += 1>> <</if>> <</for>> <!-- Check for sexual traits --> <<set _sexualTraits = ["Oral Expert", "Anal Expert", "Dirty Talker", "BDSM Enthusiast - Dom", "BDSM Enthusiast - Sub", "Exhibitionist", "Rough Sex Enthusiast", "Sensual Lover", "Roleplay Expert", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master"]>> <<set _hasSexualTraits = false>> <<set _sexualTraitCount = 0>> <<for _trait range _sexualTraits>> <<if $skills.includes(_trait)>> <<set _hasSexualTraits = true>> <<set _sexualTraitCount += 1>> <</if>> <</for>> <!-- Chest size bonus for female player with male mayor --> <<set _chestBonus = 0>> <<if $bodyParts.gender === "female" && _mayorGender === "male">> <<set _chestSizes = ["flat", "small", "medium", "large", "huge", "giant"]>> <<set _chestIndex = _chestSizes.indexOf($bodyParts.chest.toLowerCase())>> <<if _chestIndex >= 0>> <<set _chestBonus = _chestIndex * 5>> <</if>> <</if>> <!-- Calculate base erotic task chance --> <<set _eroticChance = 20>> <!-- Sexual traits increase erotic chance --> <<if _hasSexualTraits>> <<set _eroticChance += (_sexualTraitCount * 5)>> <</if>> <!-- Gender-based modifiers --> <<if $bodyParts.gender === "female" && _mayorGender === "male">> <<set _eroticChance += (_attractivenessScore * 5) + (_femininityScore * 5) + _chestBonus>> <<elseif $bodyParts.gender === "male" && _mayorGender === "female">> <<set _eroticChance += (_attractivenessScore * 5) + (_masculinityScore * 8)>> <<elseif $bodyParts.gender === _mayorGender>> <!-- Same gender - requires high attractiveness + specific traits --> <<if $bodyParts.gender === "male" && $mentalTraits.includes("Femboy")>> <<set _eroticChance = (_attractivenessScore >= 5) ? 40 : 0>> <<elseif $bodyParts.gender === "female" && $mentalTraits.includes("Tomboy")>> <<set _eroticChance = (_attractivenessScore >= 5) ? 40 : 0>> <<else>> <<set _eroticChance = 0>> <</if>> <!-- Add sexual trait bonus for same gender --> <<if _eroticChance > 0 && _hasSexualTraits>> <<set _eroticChance += (_sexualTraitCount * 5)>> <</if>> <</if>> <!-- Sunfish trait override --> <<if $skills.includes("Sunfish")>> <<set _eroticChance = 95>> <<else>> <!-- Cap at 85% for non-Sunfish players --> <<if _eroticChance > 85>> <<set _eroticChance = 85>> <</if>> <</if>> <!-- Determine task type --> <<set _taskRoll = random(1, 100)>> <<set _isEroticTask = _taskRoll <= _eroticChance>> <!-- Check for Sunfish trait event (1% chance) --> <<set _sunfishEvent = false>> <<if $skills.includes("Sunfish") && random(1, 100) === 1>> <<set _sunfishEvent = true>> <<set $sunfishSightings += 1>> <</if>> <!-- Check if going to The Alter --> <<if $sunfishSightings >= 10>> <<run setup.achievements.unlock("stalked_10_times")>> <<goto "TheAlter">> <</if>> <!-- Calculate erotic payment based on traits (75-250) --> <<set _traitPaymentScore = _attractivenessScore + _masculinityScore + _femininityScore + (_chestBonus / 5)>> <<set _eroticPay = Math.floor(75 + (_traitPaymentScore * 12))>> <<if _eroticPay > 250>> <<set _eroticPay = 250>> <</if>> <!-- Generate Task --> <<if !_isEroticTask>> <!-- NORMAL TASK --> <<set _normalTasks = [ {desc: "File paperwork and organize the mayor's schedule", pay: 30}, {desc: "answer phone calls and respond to emails", pay: 25}, {desc: "prepare meeting notes and agendas", pay: 35}, {desc: "coordinate with other city departments", pay: 40}, {desc: "review and proofread city documents", pay: 30}, {desc: "manage the mayor's calendar and appointments", pay: 35}, {desc: "order office supplies and maintain inventory", pay: 25}, {desc: "greet visitors and direct them appropriately", pay: 30} ]>> <<set _task = _normalTasks.random()>> <<set _taskType = "normal">> <<else>> <!-- EROTIC TASK --> <<if $bodyParts.gender === "female" && _mayorGender === "male">> <<set _eroticTasks = [ {desc: "sit on the mayor's lap during a 'private meeting'", pay: _eroticPay, passage: "SecretaryEroticLap", taskId: "lap"}, {desc: "massage the mayor's shoulders while he works", pay: _eroticPay, passage: "SecretaryEroticMassage", taskId: "massage"}, {desc: "wear a more 'professional' outfit the mayor has selected", pay: _eroticPay, passage: "SecretaryEroticOutfit", taskId: "outfit"}, {desc: "take dictation while sitting very close to the mayor", pay: _eroticPay, passage: "SecretaryEroticDictation", taskId: "dictation"}, {desc: "help the mayor 'relieve stress' under his desk", pay: _eroticPay, passage: "SecretaryEroticDesk", taskId: "desk"}, {desc: "model the new 'city uniform' for the mayor's approval", pay: _eroticPay, passage: "SecretaryEroticModel", taskId: "modeling"}, {desc: "give the mayor a 'special presentation' behind closed doors", pay: _eroticPay, passage: "SecretaryEroticPresentation", taskId: "presentation"} ]>> <<elseif $bodyParts.gender === "male" && _mayorGender === "female">> <<set _eroticTasks = [ {desc: "let the mayor admire your physique during a 'fitness consultation'", pay: _eroticPay, passage: "SecretaryEroticPhysique", taskId: "fitness"}, {desc: "assist the mayor with 'personal stress relief'", pay: _eroticPay, passage: "SecretaryEroticRelief", taskId: "relief"}, {desc: "provide the mayor with a private massage", pay: _eroticPay, passage: "SecretaryEroticMassageFemale", taskId: "massage2"}, {desc: "model swimwear for the mayor's 'aquatics initiative review'", pay: _eroticPay, passage: "SecretaryEroticSwimwear", taskId: "swimwear"}, {desc: "help the mayor with 'personal satisfaction' in her private office", pay: _eroticPay, passage: "SecretaryEroticSatisfaction", taskId: "satisfaction"}, {desc: "demonstrate your strength by lifting the mayor", pay: _eroticPay, passage: "SecretaryEroticLift", taskId: "strength"}, {desc: "provide 'intimate assistance' as requested", pay: _eroticPay, passage: "SecretaryEroticAssist", taskId: "assistance"} ]>> <<else>> <!-- Same gender tasks --> <<set _eroticTasks = [ {desc: "help the mayor with a 'private wardrobe consultation'", pay: _eroticPay, passage: "SecretaryEroticWardrobe", taskId: "wardrobe"}, {desc: "provide the mayor with 'personal companionship'", pay: _eroticPay, passage: "SecretaryEroticCompanion", taskId: "companionship"}, {desc: "give the mayor a private massage", pay: _eroticPay, passage: "SecretaryEroticMassageSame", taskId: "massage3"}, {desc: "model clothing for the mayor's review", pay: _eroticPay, passage: "SecretaryEroticModelSame", taskId: "fashion"}, {desc: "assist with the mayor's 'special needs'", pay: _eroticPay, passage: "SecretaryEroticNeeds", taskId: "needs"} ]>> <</if>> <<set _task = _eroticTasks.random()>> <<set _taskType = "erotic">> <!-- Apply sexual trait bonuses to payment --> <<set _paymentBonus = 0>> <!-- Check for trait-specific bonuses based on task type --> <<if _task.taskId === "lap" || _task.taskId === "dictation">> <<if $skills.includes("BDSM Enthusiast - Sub")>> <<set _paymentBonus += 30>> <</if>> <<if $skills.includes("Sensual Lover")>> <<set _paymentBonus += 25>> <</if>> <<elseif _task.taskId === "massage" || _task.taskId === "massage2" || _task.taskId === "massage3">> <<if $skills.includes("Sensual Lover")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "outfit" || _task.taskId === "modeling" || _task.taskId === "presentation" || _task.taskId === "fitness" || _task.taskId === "swimwear" || _task.taskId === "wardrobe" || _task.taskId === "fashion">> <<if $skills.includes("Exhibitionist")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "desk" || _task.taskId === "relief">> <<if $skills.includes("Oral Expert")>> <<set _paymentBonus += 45>> <</if>> <<if $skills.includes("BDSM Enthusiast - Sub")>> <<set _paymentBonus += 25>> <</if>> <<elseif _task.taskId === "satisfaction" || _task.taskId === "needs">> <<if $skills.includes("BDSM Enthusiast - Sub")>> <<set _paymentBonus += 30>> <</if>> <<if $skills.includes("Rough Sex Enthusiast")>> <<set _paymentBonus += 35>> <</if>> <<elseif _task.taskId === "strength">> <<if $skills.includes("Sexual Stamina Expert")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "assistance">> <<if $skills.includes("Rough Sex Enthusiast")>> <<set _paymentBonus += 40>> <</if>> <<elseif _task.taskId === "companionship">> <<if $skills.includes("Sensual Lover")>> <<set _paymentBonus += 35>> <</if>> <</if>> <!-- Apply bonus to task payment --> <<set _task.pay += _paymentBonus>> <!-- Trophy Wife 2x cash bonus for secretary sexual acts --> <<if $physicalTraits.includes("Trophy Wife")>> <<set _task.pay = _task.pay * 2>> <</if>> <!-- Slut 2x cash bonus for secretary sexual acts --> <<if $physicalTraits.includes("Slut")>> <<set _task.pay = _task.pay * 2>> <</if>> <!-- Cap at 1400 (increased to accommodate Slut bonus) --> <<if _task.pay > 1400>> <<set _task.pay = 1400>> <</if>> <</if>> <!-- Store task info globally for sub-passages --> <<set $currentTask = _task>> <<set $currentTaskType = _taskType>> <!-- Check for forced acceptance (Bimbo/Submissive) --> <<set _canRefuse = true>> <<set _forceAcceptChance = 0>> <<if $mentalTraits.includes("Bimbo") && $mentalTraits.includes("Submissive")>> <<set _forceAcceptChance = 75>> <<elseif $mentalTraits.includes("Bimbo") || $mentalTraits.includes("Submissive")>> <<set _forceAcceptChance = 50>> <</if>> <<set _forcedAcceptance = false>> <<if _forceAcceptChance > 0 && random(1, 100) <= _forceAcceptChance>> <<set _forcedAcceptance = true>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">✨ Special Assignment</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0;"> You enter the mayor's private office. The door closes behind you with a soft click. </p> </div> <!-- Sunfish Event --> <<if _sunfishEvent>> <div style="background: #1a3a4a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a9eff; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #4dabf7; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> For a brief moment, you catch a glimpse of something in your peripheral vision - a shadowy figure that appears to be made of several sunfish stacked in a trench coat. When you turn to look, there's nothing there. Just an empty corner of the office. </p> <p style="color: #74c0fc; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> (Strange sightings: $sunfishSightings/10) </p> </div> <</if>> <!-- Task Description --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if _taskType === 'erotic'>>#FFD700<<else>>#9b59b6<</if>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: <<if _taskType === 'erotic'>>#FFD700<<else>>#9b59b6<</if>>; margin-top: 0;">The Mayor's Request</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; border: 2px solid <<if _taskType === 'erotic'>>#FFD700<<else>>#666<</if>>;"> <p style="color: #ccc; font-size: 16px; margin: 0;"> The mayor asks you to <strong style="color: <<if _taskType === 'erotic'>>#FFD700<<else>>#9b59b6<</if>>;"><<print _task.desc>></strong>. </p> <<if _taskType === "erotic">> <p style="color: #ffc107; font-size: 14px; margin: 15px 0 0 0; font-style: italic;"> This definitely wasn't in your job description... </p> <</if>> </div> <div style="margin-top: 20px; padding: 15px; background: #1a1a1a; border-radius: 8px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 16px; margin: 0;"> Payment: <strong>$<<print _task.pay>></strong> </p> <<if _taskType === "erotic">> <p style="color: #ff6b6b; font-size: 14px; margin: 5px 0 0 0;"> Refusing will result in reduced pay ($<<print Math.floor(_task.pay * 0.3)>>) </p> <</if>> </div> </div> <!-- Decision Options --> <<if _forcedAcceptance && _taskType === "erotic">> <!-- Forced Acceptance --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ff6b6b; font-size: 16px; text-align: center; margin: 0 0 15px 0; font-style: italic;"> <<if $mentalTraits.includes("Bimbo") && $mentalTraits.includes("Submissive")>> Your submissive nature and scattered thoughts make it impossible to refuse. You find yourself nodding automatically. <<else>> Something about the request makes you unable to say no. Your body moves on its own. <</if>> </p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Comply</div>">> <<goto _task.passage>> <</link>> </div> <<else>> <!-- Normal Choice --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 30px;"> <!-- Accept --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0; text-align: center;">✓ Accept</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Do as the mayor requests </p> <<if _taskType === "erotic">> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept Task</div>">> <<goto _task.passage>> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept Task</div>">> <<set $money += _task.pay>> <<run window.advanceTime(60)>> <<set $acceptedEroticTask = false>> <<goto "SecretaryTaskResult">> <</link>> <</if>> </div> <!-- Refuse --> <<if _taskType === "erotic">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; text-align: center;">✗ Refuse</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0 0 15px 0;"> Politely decline </p> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Refuse Task</div>">> <<set $money += Math.floor(_task.pay * 0.3)>> <<run window.advanceTime(60)>> <<set $acceptedEroticTask = false>> <<set $refusedTask = true>> <<goto "SecretaryTaskResult">> <</link>> </div> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #666; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Office</div>">> <<goto "TownHall">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">⏰ Daily Work Limit Reached</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> You've already worked 8 hours today as the mayor's secretary. That's enough for one day. You also might have worked 9 hours, but let's just say that's now a feature. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0; line-height: 1.6;"> The mayor waves you away. "You've done plenty today. Go home and rest. I'll see you tomorrow." </p> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 2px solid #4dabf7;"> <p style="color: #4dabf7; font-size: 16px; text-align: center; margin: 0;"> Hours Worked Today: <strong>$secretaryHoursWorkedToday/8</strong> </p> <p style="color: #888; font-size: 14px; text-align: center; margin: 10px 0 0 0;"> Come back tomorrow for more work. </p> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Town Hall</div>">> <<goto "TownHall">> <</link>> </div> </div> <</nobr>>
/* ---------------------------------- */ /* --- BIMBO TRAIT OVERRIDE SYSTEM --- */ /* ---------------------------------- */ <<script>> /* Define the Bimbo trait override set */ setup.bimboTraitOverrides = { gender: "female", hairColor: "platinum blonde", chest: "gigantic", butt: "gigantic", physicalTraits: ["Curvy", "Voluptuous", "Fashionable"], mentalTraits: ["Bimbo", "Talkative", "Flirty", "Forgetful", "Extroverted", "High Energy"], voiceTraits: ["Bouncy Tone"], skills: ["High Heels Proficient", "Sexually Skilled", "Modeling", "Makeup", "Hair Styling", "Social Media"], additionalMentalTraits: ["High Stamina", "Relaxed"] }; /* Check if character has Bimbo trait */ setup.hasBimboTrait = function(character) { if (!character) return false; if (character === State.variables) { return State.variables.mentalTraits && State.variables.mentalTraits.includes("Bimbo"); } return character.mentalTraits && character.mentalTraits.includes("Bimbo"); }; /* Get effective traits (considers Bimbo override) */ setup.getEffectiveTraits = function(character, traitType) { if (!character) return []; var isBimbo = setup.hasBimboTrait(character); if (!isBimbo) { if (character === State.variables) { var v = State.variables; if (traitType === "physical") return v.physicalTraits || []; if (traitType === "mental") return v.mentalTraits || []; if (traitType === "skills") return v.skills || []; } else { if (traitType === "physical") return character.physicalTraits || []; if (traitType === "mental") return character.mentalTraits || []; if (traitType === "skills") return character.skills || []; } return []; } var overrides = setup.bimboTraitOverrides; if (traitType === "physical") { return overrides.physicalTraits.concat(overrides.voiceTraits); } if (traitType === "mental") { return overrides.mentalTraits.concat(overrides.additionalMentalTraits); } if (traitType === "skills") { return overrides.skills; } return []; }; /* Get stored (original) traits when Bimbo is active */ setup.getStoredTraits = function(character, traitType) { if (!character) return []; if (character === State.variables) { var v = State.variables; if (!v.bimboStoredTraits) return []; if (traitType === "physical") return v.bimboStoredTraits.physical || []; if (traitType === "mental") return v.bimboStoredTraits.mental || []; if (traitType === "skills") return v.bimboStoredTraits.skills || []; } else { if (!character.bimboStoredTraits) return []; if (traitType === "physical") return character.bimboStoredTraits.physical || []; if (traitType === "mental") return character.bimboStoredTraits.mental || []; if (traitType === "skills") return character.bimboStoredTraits.skills || []; } return []; }; /* Activate Bimbo trait (stores original traits) */ setup.activateBimboTrait = function(character) { if (!character) return; var isPlayer = (character === State.variables); var v = isPlayer ? State.variables : character; if (!v.bimboStoredTraits) { v.bimboStoredTraits = { physical: (isPlayer ? v.physicalTraits : character.physicalTraits).slice(), mental: (isPlayer ? v.mentalTraits : character.mentalTraits).slice(), skills: (isPlayer ? v.skills : character.skills).slice(), bodyParts: { gender: (isPlayer ? v.bodyParts.gender : character.bodyParts.gender), chest: (isPlayer ? v.bodyParts.chest : character.bodyParts.chest), butt: (isPlayer ? v.bodyParts.butt : character.bodyParts.butt) /* NOTE: genitals are NOT stored - Bimbo doesn't affect them */ }, appearance: { hairColor: (isPlayer ? v.appearance.hairColor : character.appearance.hairColor) } }; } var overrides = setup.bimboTraitOverrides; if (isPlayer) { v.bodyParts.gender = overrides.gender; v.bodyParts.chest = overrides.chest; v.bodyParts.butt = overrides.butt; v.appearance.hairColor = overrides.hairColor; v.physicalTraits = overrides.physicalTraits.concat(overrides.voiceTraits); v.mentalTraits = overrides.mentalTraits.concat(overrides.additionalMentalTraits); v.skills = overrides.skills.slice(); } else { character.bodyParts.gender = overrides.gender; character.bodyParts.chest = overrides.chest; character.bodyParts.butt = overrides.butt; character.appearance.hairColor = overrides.hairColor; character.physicalTraits = overrides.physicalTraits.concat(overrides.voiceTraits); character.mentalTraits = overrides.mentalTraits.concat(overrides.additionalMentalTraits); character.skills = overrides.skills.slice(); } }; /* Deactivate Bimbo trait (restores original traits). MERGE-style restoration: traits or body parts that changed AFTER Bimbo was activated (e.g. via mid-trade transfers or transformations) are preserved. We only strip the bimbo overlay (the trait set added by activateBimboTrait) and re-add the pre-Bimbo originals that aren't currently present. Body parts only revert if they're still at the bimbo override values — if some later effect changed them (e.g. a TF set chest=gigantic for a different reason), we leave them alone. */ setup.deactivateBimboTrait = function(character) { if (!character) return; var isPlayer = (character === State.variables); var v = isPlayer ? State.variables : character; var target = isPlayer ? v : character; var stored = (isPlayer ? v.bimboStoredTraits : character.bimboStoredTraits); if (!stored) return; var overrides = setup.bimboTraitOverrides; var bimboPhys = (overrides.physicalTraits || []).concat(overrides.voiceTraits || []); var bimboMent = (overrides.mentalTraits || []).concat(overrides.additionalMentalTraits || []); var bimboSkills = (overrides.skills || []); function mergeRestore(currentArr, bimboOverlay, storedArr) { var pre = storedArr || []; /* Drop a trait only if it was added BY bimbo (in overlay) AND was not in the player's pre-bimbo traits. Anything earned during the bimbo phase that isn't a bimbo-overlay trait survives. */ var result = (currentArr || []).filter(function(t) { return bimboOverlay.indexOf(t) === -1 || pre.indexOf(t) !== -1; }); /* Re-add any pre-bimbo trait that's currently missing (it was wiped out when the bimbo overlay overwrote the trait array). */ pre.forEach(function(t) { if (result.indexOf(t) === -1) result.push(t); }); return result; } if (target.physicalTraits !== undefined) target.physicalTraits = mergeRestore(target.physicalTraits, bimboPhys, stored.physical); if (target.mentalTraits !== undefined) target.mentalTraits = mergeRestore(target.mentalTraits, bimboMent, stored.mental); if (target.skills !== undefined) target.skills = mergeRestore(target.skills, bimboSkills, stored.skills); /* Single-transformation guard: the merge-restore above can re-add a stored pre-Bimbo transformation on top of one gained during the Bimbo phase, stacking two transformations and granting both sets of bonuses. Enforce one transformation at a time: keep the active (latest) one and strip any other transformation base traits the restore brought back. */ if (typeof setup.isTransformationTrait === "function") { var keepTF = target.activeTransformation || null; var allTF = []; (target.physicalTraits || []).forEach(function(tt) { if (setup.isTransformationTrait(tt) && allTF.indexOf(tt) === -1) allTF.push(tt); }); (target.mentalTraits || []).forEach(function(tt) { if (setup.isTransformationTrait(tt) && allTF.indexOf(tt) === -1) allTF.push(tt); }); if (allTF.length > 1) { if (!keepTF || allTF.indexOf(keepTF) === -1) keepTF = allTF[allTF.length - 1]; allTF.forEach(function(tt) { if (tt !== keepTF) { if (target.physicalTraits) { var pidx = target.physicalTraits.indexOf(tt); if (pidx !== -1) target.physicalTraits.splice(pidx, 1); } if (target.mentalTraits) { var midx = target.mentalTraits.indexOf(tt); if (midx !== -1) target.mentalTraits.splice(midx, 1); } } }); target.activeTransformation = keepTF; } } /* Body parts: only revert when still at the bimbo override values. If another effect (TF apply, gender swap, etc.) moved them since Bimbo activated, leave the new values alone. */ if (target.bodyParts && stored.bodyParts) { if (target.bodyParts.gender === overrides.gender) target.bodyParts.gender = stored.bodyParts.gender; if (target.bodyParts.chest === overrides.chest) target.bodyParts.chest = stored.bodyParts.chest; if (target.bodyParts.butt === overrides.butt) target.bodyParts.butt = stored.bodyParts.butt; } if (target.appearance && stored.appearance && target.appearance.hairColor === overrides.hairColor) { target.appearance.hairColor = stored.appearance.hairColor; } if (isPlayer) delete v.bimboStoredTraits; else delete character.bimboStoredTraits; }; /* Bimbo transformation text */ setup.getBimboTransformationText = function(gaining, oldTraits) { if (gaining) { return "A wave of warmth washes over you, starting at your core and radiating outward. Your thoughts feel... lighter somehow, less complicated. Worries and complex ideas seem to drift away like clouds, replaced by simpler, more pleasant thoughts. Your body tingles as it shifts - curves swelling and rounding, your chest and butt expanding to gigantic proportions. Your hair lightens to platinum blonde, catching the light beautifully. You feel bubbly, energetic, and so, so happy! Everything just feels... easier now. More fun! You giggle at how good it feels to just be pretty and carefree. Who needs all those boring old thoughts anyway? Being a bimbo is like, totally amazing!"; } else { return "Clarity crashes over you like a cold wave. Suddenly, thoughts that seemed impossibly complex before make perfect sense again. Your mind sharpens, focuses - it's like waking up from a pleasant but hazy dream. Your body shifts too, curves adjusting, hair color changing back, proportions returning to what they were. The constant bubbly happiness fades to more nuanced emotions. You remember who you were, what you cared about. The mental fog lifts completely, leaving you feeling... different. More yourself, perhaps, but also strangely aware of what you just experienced."; } }; <</script>>
/* ========================================== * NPC LOCATION SCHEDULES * Job-based system with custom overrides * ==========================================*/ /* Job to location mapping - NPCs appear here based on their primary job */ <<set setup.jobLocations = { "Unemployed": "Alleyway", "Streamer": "MeetNeighbors", "Adult Streamer": "MeetNeighbors", "Dancing Instructor": "DanceStudio", "Barista": "Cafe", "City Mayor": "TownHall", "Mayor's Secretary": "TownHall", "Beauty Salon Stylist": "BeautySalon", "Baker": "Bakery", "Ecentric Shop Worker": "EcentricShop", "Tech Store Clerk": "TechStore", "Adult Store Clerk": "AdultStore", "Fitness Shop Clerk": "FitnessShop", "Brothel Worker": "Brothel", "Brothel Owner": "Brothel", "Stripper": "StripClub", "Bouncer": "StripClub", "Security Guard": "Casino", "Cocktail Waitress": "Casino", "Dock Worker": "Docks", "Bus Driver": "BusStop", "Fitness Trainer": "FenRisTraining", "Mysterious Book Shop owner": "LampreyTomes", "Musician": "MeetNeighbors", "Construction Worker": "Outskirts", "Package Courier": "BusinessDistrict", "Negotiator": "BusinessDistrict", "Enforcer": "Downtown", "Clinic Assistant": "Downtown", "Data Analyst": "BusinessDistrict", "Porn Star": "ModelingStudio", "Prostitute": "Alleyway", "Social Media Influencer": "Mall", "Police Officer": "Downtown", "Black Market Dealer": "Alleyway", "Maid": "ResidentialDistrict", "Donuts Deliverer": "Bakery", "Street Performer": "SeabassPark", "Model": "ModelingStudio", "Police Station Janitor": "PoliceDepartment", "Police Station Receptionist": "PoliceDepartment" }>> /* NPC-specific location schedules - These OVERRIDE job-based locations */ <<set setup.npcLocationSchedules = { /* Flona Vulri - Tundra of Aeternus resident; never leaves the Tundra. */ /* Full-day Tundra slots guarantee getNPCLocation resolves to the hub at all */ /* hours. When Tundra sub-areas are added, split these slots among them. */ "Flona Vulri": { defaultLocation: "TundraOfAeternus", customSchedule: { "Monday": [{location: "TundraOfAeternus", start: 0, end: 24}], "Tuesday": [{location: "TundraOfAeternus", start: 0, end: 24}], "Wednesday": [{location: "TundraOfAeternus", start: 0, end: 24}], "Thursday": [{location: "TundraOfAeternus", start: 0, end: 24}], "Friday": [{location: "TundraOfAeternus", start: 0, end: 24}], "Saturday": [{location: "TundraOfAeternus", start: 0, end: 24}], "Sunday": [{location: "TundraOfAeternus", start: 0, end: 24}] } }, /* Clair - Dream entity; never leaves the Dream Dimension. */ "Clair": { defaultLocation: "DreamDimension", customSchedule: { "Monday": [{location: "DreamDimension", start: 0, end: 24}], "Tuesday": [{location: "DreamDimension", start: 0, end: 24}], "Wednesday": [{location: "DreamDimension", start: 0, end: 24}], "Thursday": [{location: "DreamDimension", start: 0, end: 24}], "Friday": [{location: "DreamDimension", start: 0, end: 24}], "Saturday": [{location: "DreamDimension", start: 0, end: 24}], "Sunday": [{location: "DreamDimension", start: 0, end: 24}] } }, /* Puffy's Maid Cafe Staff */ "Mochi": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "Outskirts", start: 8, end: 12}, {location: "SeabassPark", start: 12, end: 18}, {location: "Outskirts", start: 18, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Tuesday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "Downtown", start: 8, end: 12}, {location: "SeabassPark", start: 12, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24}], "Wednesday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "Outskirts", start: 9, end: 14}, {location: "Downtown", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Thursday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "SeabassPark", start: 8, end: 14}, {location: "Outskirts", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Friday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "Beach", start: 9, end: 16}, {location: "Outskirts", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Saturday": [{location: "OutskirtsHousing", start: 0, end: 10}, {location: "SeabassPark", start: 10, end: 16}, {location: "Downtown", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Sunday": [{location: "OutskirtsHousing", start: 0, end: 10}, {location: "SeabassPark", start: 10, end: 16}, {location: "Downtown", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}] } }, "Ren": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "LampreyTomes", start: 9, end: 14}, {location: "Downtown", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Tuesday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "Downtown", start: 9, end: 14}, {location: "LampreyTomes", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Wednesday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "MountainHotSpring", start: 9, end: 16}, {location: "LampreyTomes", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Thursday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "LampreyTomes", start: 9, end: 14}, {location: "RedLightDistrict", start: 14, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Friday": [{location: "OutskirtsHousing", start: 0, end: 9}, {location: "RedLightDistrict", start: 9, end: 16}, {location: "Casino", start: 16, end: 24}], "Saturday": [{location: "Casino", start: 0, end: 2}, {location: "OutskirtsHousing", start: 2, end: 10}, {location: "MountainHotSpring", start: 10, end: 16}, {location: "Downtown", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Sunday": [{location: "OutskirtsHousing", start: 0, end: 10}, {location: "MountainHotSpring", start: 10, end: 16}, {location: "LampreyTomes", start: 16, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}] } }, "Clover": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "GroceryStore", start: 8, end: 11}, {location: "Outskirts", start: 11, end: 16}, {location: "Beach", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24}], "Tuesday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "Beach", start: 8, end: 14}, {location: "Downtown", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Wednesday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "GroceryStore", start: 8, end: 12}, {location: "SeabassPark", start: 12, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24}], "Thursday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "Outskirts", start: 8, end: 14}, {location: "Beach", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Friday": [{location: "OutskirtsHousing", start: 0, end: 8}, {location: "Beach", start: 8, end: 14}, {location: "Downtown", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Saturday": [{location: "OutskirtsHousing", start: 0, end: 10}, {location: "GroceryStore", start: 10, end: 13}, {location: "Beach", start: 13, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24}], "Sunday": [{location: "OutskirtsHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 16}, {location: "GroceryStore", start: 16, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24}] } }, "Purple Wood": { defaultLocation: "Apartments", customSchedule: { "Tuesday": [ {location: "Downtown", start: 10, end: 12}, {location: "SeabassPark", start: 12, end: 18}, {location: "Outskirts", start: 18, end: 20}, {location: "MeetNeighbors", start: 20, end: 24}, {location: "MeetNeighbors", start: 0, end: 10} ], "Friday": [ {location: "MeetNeighbors", start: 0, end: 19}, {location: "RedLightDistrict", start: 19, end: 20}, {location: "StripClub", start: 20, end: 24} ], "Saturday": [ {location: "MeetNeighbors", start: 0, end: 24} ], "Sunday": [ {location: "MeetNeighbors", start: 0, end: 24} ] }, traitOverrides: { "Bimbo": { "Saturday": [ {location: "Mall", start: 12, end: 20}, {location: "Apartments", start: 20, end: 24}, {location: "Apartments", start: 0, end: 12} ] } } }, "Luna Snow": { defaultLocation: "MeetNeighbors", customSchedule: { "Monday": [ {location: "MeetNeighbors", start: 0, end: 24} ], "Tuesday": [ {location: "MeetNeighbors", start: 0, end: 24} ], "Wednesday": [ {location: "MeetNeighbors", start: 0, end: 10}, {location: "TrainingCenter", start: 10, end: 13}, {location: "MeetNeighbors", start: 13, end: 24} ], "Thursday": [ {location: "MeetNeighbors", start: 0, end: 24} ], "Friday": [ {location: "MeetNeighbors", start: 0, end: 13}, {location: "ChromisTunes", start: 13, end: 15}, {location: "MeetNeighbors", start: 15, end: 24} ], "Saturday": [ {location: "MeetNeighbors", start: 0, end: 24} ], "Sunday": [ {location: "MeetNeighbors", start: 0, end: 24} ] } }, "Cid Cranberry": { defaultLocation: "MeetNeighbors", customSchedule: { "Monday": [ {location: "Cafe", start: 7, end: 8}, {location: "TrainingCenter", start: 8, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "TrainingCenter", start: 13, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 21} ], "Tuesday": [ {location: "Cafe", start: 7, end: 8}, {location: "TrainingCenter", start: 8, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "TrainingCenter", start: 13, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 21} ], "Wednesday": [ {location: "Cafe", start: 7, end: 8}, {location: "TrainingCenter", start: 8, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "TrainingCenter", start: 13, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 21} ], "Thursday": [ {location: "Cafe", start: 7, end: 8}, {location: "TrainingCenter", start: 8, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "TrainingCenter", start: 13, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 21} ], "Friday": [ {location: "Cafe", start: 7, end: 8}, {location: "TrainingCenter", start: 8, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "TrainingCenter", start: 13, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 21} ], "Saturday": [ {location: "Cafe", start: 7, end: 8}, {location: "TrainingCenter", start: 8, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "TrainingCenter", start: 13, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 21} ], "Sunday": [ {location: "MeetNeighbors", start: 7, end: 16}, {location: "Brothel", start: 16, end: 24} ] } }, "Roisin Sullivan": { defaultLocation: "RoisinBeachHouse", customSchedule: { "Monday": [ {location: "RoisinBeachHouse", start: 0, end: 5}, {location: "GymNPCs", start: 5, end: 7}, {location: "RoisinBeachHouse", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Alleyway", start: 16, end: 22}, {location: "RoisinBeachHouse", start: 22, end: 24} ], "Tuesday": [ {location: "RoisinBeachHouse", start: 0, end: 5}, {location: "GymNPCs", start: 5, end: 7}, {location: "RoisinBeachHouse", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 21}, {location: "Outskirts", start: 21, end: 22}, {location: "RoisinBeachHouse", start: 22, end: 24} ], "Wednesday": [ {location: "RoisinBeachHouse", start: 0, end: 5}, {location: "GymNPCs", start: 5, end: 7}, {location: "RoisinBeachHouse", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 21}, {location: "Outskirts", start: 21, end: 22}, {location: "RoisinBeachHouse", start: 22, end: 24} ], "Thursday": [ {location: "RoisinBeachHouse", start: 0, end: 5}, {location: "GymNPCs", start: 5, end: 7}, {location: "RoisinBeachHouse", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 21}, {location: "Outskirts", start: 21, end: 22}, {location: "RoisinBeachHouse", start: 22, end: 24} ], "Friday": [ {location: "RoisinBeachHouse", start: 0, end: 6}, {location: "Beach", start: 6, end: 10}, {location: "CoralReef", start: 10, end: 13}, {location: "Docks", start: 13, end: 14}, {location: "RoisinBeachHouse", start: 14, end: 24} ], "Saturday": [ {location: "RoisinBeachHouse", start: 0, end: 5}, {location: "GymNPCs", start: 5, end: 7}, {location: "RoisinBeachHouse", start: 7, end: 10}, {location: "Casino", start: 10, end: 15}, {location: "Mall", start: 15, end: 17}, {location: "TownHall", start: 17, end: 18}, {location: "RoisinBeachHouse", start: 18, end: 24} ], "Sunday": [ {location: "Alter", start: 0, end: 24} ] } }, "Jake Steel": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "SeabassPark", start: 15, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Tuesday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "SeabassPark", start: 15, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Wednesday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "SeabassPark", start: 15, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Thursday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "SeabassPark", start: 15, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Friday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "SeabassPark", start: 15, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Saturday": [ {location: "OutskirtsHousing", start: 0, end: 8}, {location: "Beach", start: 8, end: 12}, {location: "TheAngler", start: 12, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24} ], "Sunday": [ {location: "OutskirtsHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 16}, {location: "OutskirtsHousing", start: 16, end: 24} ] } }, "Marcus Carter": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "GymNPCs", start: 6, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 17}, {location: "CommercialDistrict", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "GymNPCs", start: 6, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 17}, {location: "CommercialDistrict", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "GymNPCs", start: 6, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 17}, {location: "CommercialDistrict", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "GymNPCs", start: 6, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 17}, {location: "CommercialDistrict", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "GymNPCs", start: 6, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 17}, {location: "TheAngler", start: 17, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "GymNPCs", start: 9, end: 11}, {location: "SeabassPark", start: 11, end: 15}, {location: "ResidentialDistrict", start: 15, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 24} ] } }, "Elena Romero": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "Mall", start: 10, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Beach", start: 11, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ] } }, "Silva Silva": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "CommercialDistrict", start: 7, end: 12}, {location: "Downtown", start: 12, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "CommercialDistrict", start: 7, end: 12}, {location: "Downtown", start: 12, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "CommercialDistrict", start: 7, end: 12}, {location: "Downtown", start: 12, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "CommercialDistrict", start: 7, end: 12}, {location: "Downtown", start: 12, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "CommercialDistrict", start: 7, end: 12}, {location: "Downtown", start: 12, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "SeabassPark", start: 10, end: 14}, {location: "Mall", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "Beach", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Grimm Patel": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 12}, {location: "Alleyway", start: 12, end: 18}, {location: "Casino", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 12}, {location: "Alleyway", start: 12, end: 18}, {location: "Casino", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 12}, {location: "Alleyway", start: 12, end: 18}, {location: "Casino", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 12}, {location: "Alleyway", start: 12, end: 18}, {location: "Casino", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 12}, {location: "Alleyway", start: 12, end: 18}, {location: "VIPLounge", start: 18, end: 23}, {location: "BusinessDistrictHousing", start: 23, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Casino", start: 11, end: 18}, {location: "VIPLounge", start: 18, end: 23}, {location: "BusinessDistrictHousing", start: 23, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 14}, {location: "SeabassPark", start: 14, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ] } }, "Scarlett Vex": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "VIPLounge", start: 18, end: 23}, {location: "BusinessDistrictHousing", start: 23, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "VIPLounge", start: 19, end: 23}, {location: "BusinessDistrictHousing", start: 23, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, "Jade Nightshade": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Tuesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Wednesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Thursday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Friday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Saturday": [ {location: "StripClub", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 16}, {location: "SeabassPark", start: 16, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ] } }, "Apollo Sterling": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 12}, {location: "GymNPCs", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "StripClub", start: 15, end: 24} ], "Tuesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 12}, {location: "GymNPCs", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "StripClub", start: 15, end: 24} ], "Wednesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 12}, {location: "GymNPCs", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "StripClub", start: 15, end: 24} ], "Thursday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 12}, {location: "GymNPCs", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "StripClub", start: 15, end: 24} ], "Friday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 12}, {location: "GymNPCs", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "StripClub", start: 15, end: 24} ], "Saturday": [ {location: "StripClub", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "StripClub", start: 17, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 15}, {location: "GymNPCs", start: 15, end: 17}, {location: "SeabassPark", start: 17, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ] } }, "Vera Sinclair": { defaultLocation: "ResidentialExpensiveHomes", customSchedule: { "Monday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TownHall", start: 10, end: 16}, {location: "CommercialDistrict", start: 16, end: 18}, {location: "ResidentialExpensiveHomes", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TownHall", start: 10, end: 16}, {location: "CommercialDistrict", start: 16, end: 18}, {location: "ResidentialExpensiveHomes", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TownHall", start: 10, end: 16}, {location: "CommercialDistrict", start: 16, end: 18}, {location: "ResidentialExpensiveHomes", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TownHall", start: 10, end: 16}, {location: "CommercialDistrict", start: 16, end: 18}, {location: "ResidentialExpensiveHomes", start: 18, end: 24} ], "Friday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TownHall", start: 10, end: 16}, {location: "VIPLounge", start: 16, end: 21}, {location: "ResidentialExpensiveHomes", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 11}, {location: "Mall", start: 11, end: 15}, {location: "SeabassPark", start: 15, end: 18}, {location: "ResidentialExpensiveHomes", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 24} ] } }, "Rex Harmon": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Cass Morgan": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 11}, {location: "Mall", start: 11, end: 15}, {location: "SeabassPark", start: 15, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Ivy Brooks": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "GroceryStore", start: 8, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "GroceryStore", start: 8, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "GroceryStore", start: 8, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "GroceryStore", start: 8, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "GroceryStore", start: 8, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "Mall", start: 10, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Zara Quinn": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Mall", start: 11, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, "Drake Lawson": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Alleyway", start: 16, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Alleyway", start: 16, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Alleyway", start: 16, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Alleyway", start: 16, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Casino", start: 16, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "Casino", start: 12, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 14}, {location: "SeabassPark", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Nina Sato": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Mall", start: 11, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, "Daisy Flores": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Mall", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Mall", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Mall", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Mall", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Mall", start: 8, end: 16}, {location: "StripClub", start: 16, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "Beach", start: 10, end: 15}, {location: "Mall", start: 15, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Milo Hart": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "CommercialDistrict", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Blair Hoffman": { defaultLocation: "ResidentialExpensiveHomes", customSchedule: { "Monday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "CommercialDistrict", start: 10, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "ResidentialExpensiveHomes", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "CommercialDistrict", start: 10, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "ResidentialExpensiveHomes", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "CommercialDistrict", start: 10, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "ResidentialExpensiveHomes", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "CommercialDistrict", start: 10, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "ResidentialExpensiveHomes", start: 19, end: 24} ], "Friday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "CommercialDistrict", start: 10, end: 17}, {location: "VIPLounge", start: 17, end: 22}, {location: "ResidentialExpensiveHomes", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 11}, {location: "Mall", start: 11, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "ResidentialExpensiveHomes", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialExpensiveHomes", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "ResidentialExpensiveHomes", start: 17, end: 24} ] } }, "Wendy Parker": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Cafe", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Cafe", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Cafe", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Cafe", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Cafe", start: 6, end: 14}, {location: "TheAngler", start: 14, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "Mall", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Spencer Kim": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Tanya West": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Alleyway", start: 17, end: 24} ], "Tuesday": [ {location: "Alleyway", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Alleyway", start: 17, end: 24} ], "Wednesday": [ {location: "Alleyway", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Alleyway", start: 17, end: 24} ], "Thursday": [ {location: "Alleyway", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Alleyway", start: 17, end: 24} ], "Friday": [ {location: "Alleyway", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "RedLightDistrict", start: 17, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "RedLightDistrict", start: 18, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 16}, {location: "SeabassPark", start: 16, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ] } }, "Victor Reyes": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Docks", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Docks", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Docks", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Docks", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Docks", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "Beach", start: 10, end: 15}, {location: "TheAngler", start: 15, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "Beach", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Clara Chen": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "GroceryStore", start: 17, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Hospital", start: 8, end: 17}, {location: "VIPLounge", start: 17, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "Mall", start: 10, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Beach", start: 11, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ] } }, "Tommy Blake": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Tuesday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Wednesday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Thursday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Friday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 16}, {location: "TheAngler", start: 16, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24} ], "Saturday": [ {location: "OutskirtsHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "TheAngler", start: 14, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Sunday": [ {location: "OutskirtsHousing", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "OutskirtsHousing", start: 17, end: 24} ] } }, "Lena Cross": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Mall", start: 11, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, "Oscar Grant": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "CommercialDistrict", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Penny Shaw": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "SeabassPark", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Mall", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "Mall", start: 10, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, "Felix Dunn": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Casino", start: 16, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 11}, {location: "Casino", start: 11, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Amber Cole": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "ModelingStudio", start: 12, end: 18}, {location: "VIPLounge", start: 18, end: 23}, {location: "BusinessDistrictHousing", start: 23, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "VIPLounge", start: 19, end: 23}, {location: "BusinessDistrictHousing", start: 23, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, "Mason Reed": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 15}, {location: "Alleyway", start: 15, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Tuesday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 15}, {location: "Alleyway", start: 15, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Wednesday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 15}, {location: "Alleyway", start: 15, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Thursday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 15}, {location: "Alleyway", start: 15, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Friday": [ {location: "OutskirtsHousing", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Outskirts", start: 7, end: 15}, {location: "Casino", start: 15, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24} ], "Saturday": [ {location: "OutskirtsHousing", start: 0, end: 11}, {location: "Casino", start: 11, end: 18}, {location: "StripClub", start: 18, end: 23}, {location: "OutskirtsHousing", start: 23, end: 24} ], "Sunday": [ {location: "OutskirtsHousing", start: 0, end: 14}, {location: "SeabassPark", start: 14, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24} ] } }, "Ruby Lane": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Tuesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Wednesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Thursday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Friday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Saturday": [ {location: "StripClub", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 16}, {location: "SeabassPark", start: 16, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ] } }, /* ========== DOCK WORKERS (5) - Staggered Shifts ========== */ "Mike Murphy": { defaultLocation: "DocksHousing", customSchedule: { "Monday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "TheAngler", start: 15, end: 19}, {location: "DocksHousing", start: 19, end: 24} ], "Tuesday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "Beach", start: 13, end: 16}, {location: "DocksHousing", start: 16, end: 24} ], "Wednesday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "TheAngler", start: 15, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Thursday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "DocksHousing", start: 17, end: 24} ], "Friday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "TheAngler", start: 15, end: 22}, {location: "DocksHousing", start: 22, end: 24} ], "Saturday": [ {location: "DocksHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "TheAngler", start: 14, end: 19}, {location: "DocksHousing", start: 19, end: 24} ], "Sunday": [ {location: "DocksHousing", start: 0, end: 11}, {location: "GymNPCs", start: 11, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "DocksHousing", start: 17, end: 24} ] } }, "Carlos Mendez": { defaultLocation: "DocksHousing", customSchedule: { "Monday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "Mall", start: 19, end: 21}, {location: "DocksHousing", start: 21, end: 24} ], "Tuesday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "DocksHousing", start: 18, end: 24} ], "Wednesday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Beach", start: 16, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Thursday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Friday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "VIPLounge", start: 18, end: 22}, {location: "DocksHousing", start: 22, end: 24} ], "Saturday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Beach", start: 16, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Sunday": [ {location: "DocksHousing", start: 0, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "DocksHousing", start: 18, end: 24} ] } }, "Jamal Rivers": { defaultLocation: "DocksHousing", customSchedule: { "Monday": [ {location: "DocksHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Docks", start: 10, end: 18}, {location: "GymNPCs", start: 18, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Tuesday": [ {location: "DocksHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Docks", start: 10, end: 18}, {location: "Beach", start: 18, end: 21}, {location: "DocksHousing", start: 21, end: 24} ], "Wednesday": [ {location: "DocksHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Docks", start: 10, end: 18}, {location: "GymNPCs", start: 18, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Thursday": [ {location: "DocksHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Docks", start: 10, end: 18}, {location: "TheAngler", start: 18, end: 21}, {location: "DocksHousing", start: 21, end: 24} ], "Friday": [ {location: "DocksHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Docks", start: 10, end: 18}, {location: "GymNPCs", start: 18, end: 20}, {location: "VIPLounge", start: 20, end: 23}, {location: "DocksHousing", start: 23, end: 24} ], "Saturday": [ {location: "DocksHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Docks", start: 10, end: 18}, {location: "Casino", start: 18, end: 22}, {location: "DocksHousing", start: 22, end: 24} ], "Sunday": [ {location: "DocksHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "DocksHousing", start: 16, end: 24} ] } }, "Rosa Otterino": { defaultLocation: "DocksHousing", customSchedule: { "Monday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "GroceryStore", start: 16, end: 17}, {location: "DocksHousing", start: 17, end: 24} ], "Tuesday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "DocksHousing", start: 19, end: 24} ], "Wednesday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "DocksHousing", start: 18, end: 24} ], "Thursday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "DocksHousing", start: 19, end: 24} ], "Friday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Saturday": [ {location: "DocksHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "DocksHousing", start: 17, end: 24} ], "Sunday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "DocksHousing", start: 19, end: 24} ] } }, "Keisha Jackson": { defaultLocation: "DocksHousing", customSchedule: { "Monday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "DocksHousing", start: 18, end: 24} ], "Tuesday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "Beach", start: 13, end: 16}, {location: "DocksHousing", start: 16, end: 24} ], "Wednesday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "DocksHousing", start: 19, end: 24} ], "Thursday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "DocksHousing", start: 15, end: 24} ], "Friday": [ {location: "DocksHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Docks", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "DocksHousing", start: 20, end: 24} ], "Saturday": [ {location: "DocksHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Docks", start: 5, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "DocksHousing", start: 17, end: 24} ], "Sunday": [ {location: "DocksHousing", start: 0, end: 11}, {location: "SeabassPark", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "DocksHousing", start: 18, end: 24} ] } }, /* ========== CONSTRUCTION WORKERS (3 New) - Day Shifts ========== */ "Marco Rodriguez": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [ {location: "OutskirtsHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Outskirts", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "TheAngler", start: 15, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Tuesday": [ {location: "OutskirtsHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Outskirts", start: 5, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "OutskirtsHousing", start: 17, end: 24} ], "Wednesday": [ {location: "OutskirtsHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Outskirts", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24} ], "Thursday": [ {location: "OutskirtsHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Outskirts", start: 5, end: 13}, {location: "Beach", start: 13, end: 16}, {location: "OutskirtsHousing", start: 16, end: 24} ], "Friday": [ {location: "OutskirtsHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Outskirts", start: 5, end: 13}, {location: "GymNPCs", start: 13, end: 15}, {location: "VIPLounge", start: 15, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Saturday": [ {location: "OutskirtsHousing", start: 0, end: 4}, {location: "Cafe", start: 4, end: 5}, {location: "Outskirts", start: 5, end: 13}, {location: "Beach", start: 13, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24} ], "Sunday": [ {location: "OutskirtsHousing", start: 0, end: 11}, {location: "GymNPCs", start: 11, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "OutskirtsHousing", start: 17, end: 24} ] } }, "Sheryl Williams": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Tuesday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "Beach", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Wednesday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Thursday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Friday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "TheAngler", start: 19, end: 22}, {location: "OutskirtsHousing", start: 22, end: 24} ], "Saturday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "Beach", start: 17, end: 21}, {location: "OutskirtsHousing", start: 21, end: 24} ], "Sunday": [ {location: "OutskirtsHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "OutskirtsHousing", start: 16, end: 24} ] } }, "David O'Brien": { defaultLocation: "OutskirtsHousing", customSchedule: { "Monday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "SeabassPark", start: 15, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24} ], "Tuesday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "TheAngler", start: 15, end: 19}, {location: "OutskirtsHousing", start: 19, end: 24} ], "Wednesday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "SeabassPark", start: 17, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Thursday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "GroceryStore", start: 15, end: 16}, {location: "OutskirtsHousing", start: 16, end: 24} ], "Friday": [ {location: "OutskirtsHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Outskirts", start: 8, end: 17}, {location: "TheAngler", start: 17, end: 21}, {location: "OutskirtsHousing", start: 21, end: 24} ], "Saturday": [ {location: "OutskirtsHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Outskirts", start: 6, end: 15}, {location: "TheAngler", start: 15, end: 20}, {location: "OutskirtsHousing", start: 20, end: 24} ], "Sunday": [ {location: "OutskirtsHousing", start: 0, end: 10}, {location: "SeabassPark", start: 10, end: 14}, {location: "TheAngler", start: 14, end: 18}, {location: "OutskirtsHousing", start: 18, end: 24} ] } }, /* ========== PATROL OFFICERS (3) - 24/7 Coverage Rotation ========== */ "Boris Shorthead": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Downtown", start: 6, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Downtown", start: 6, end: 14}, {location: "TheAngler", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Downtown", start: 6, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Downtown", start: 6, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Downtown", start: 6, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "TheAngler", start: 16, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ] } }, "Mareregererrer Mayonnaise": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 21}, {location: "Cafe", start: 21, end: 22}, {location: "Downtown", start: 22, end: 24} ], "Sunday": [ {location: "Downtown", start: 0, end: 6}, {location: "Cafe", start: 6, end: 7}, {location: "Downtown", start: 7, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ] } }, "Poggies Name420": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "Downtown", start: 0, end: 6}, {location: "ResidentialDistrict", start: 6, end: 21}, {location: "Cafe", start: 21, end: 22}, {location: "Downtown", start: 22, end: 24} ], "Tuesday": [ {location: "Downtown", start: 0, end: 6}, {location: "ResidentialDistrict", start: 6, end: 21}, {location: "Cafe", start: 21, end: 22}, {location: "Downtown", start: 22, end: 24} ], "Wednesday": [ {location: "Downtown", start: 0, end: 6}, {location: "ResidentialDistrict", start: 6, end: 21}, {location: "Cafe", start: 21, end: 22}, {location: "Downtown", start: 22, end: 24} ], "Thursday": [ {location: "Downtown", start: 0, end: 6}, {location: "ResidentialDistrict", start: 6, end: 21}, {location: "Cafe", start: 21, end: 22}, {location: "Downtown", start: 22, end: 24} ], "Friday": [ {location: "Downtown", start: 0, end: 6}, {location: "ResidentialDistrict", start: 6, end: 21}, {location: "Cafe", start: 21, end: 22}, {location: "Downtown", start: 22, end: 24} ], "Saturday": [ {location: "Downtown", start: 0, end: 6}, {location: "ResidentialDistrict", start: 6, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "Downtown", start: 14, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ] } }, /* ========== BEAUTY SALON STYLISTS (3) ========== */ "Crystal Meffin": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "BeautySalon", start: 9, end: 17}, {location: "Mall", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "BeautySalon", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "BeautySalon", start: 9, end: 17}, {location: "Mall", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "BeautySalon", start: 9, end: 17}, {location: "Beach", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "BeautySalon", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "BeautySalon", start: 9, end: 17}, {location: "Mall", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ] } }, "Sophi Boris": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "BeautySalon", start: 12, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "BeautySalon", start: 12, end: 18}, {location: "GymNPCs", start: 18, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "BeautySalon", start: 12, end: 18}, {location: "VIPLounge", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "BeautySalon", start: 12, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "BeautySalon", start: 12, end: 18}, {location: "Casino", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "BeautySalon", start: 12, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 12}, {location: "Mall", start: 12, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ] } }, "Naomi Light": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "BeautySalon", start: 8, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "BeautySalon", start: 8, end: 14}, {location: "DanceStudio", start: 14, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "BeautySalon", start: 8, end: 14}, {location: "SeabassPark", start: 14, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "BeautySalon", start: 8, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "BeautySalon", start: 8, end: 14}, {location: "DanceStudio", start: 14, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "BeautySalon", start: 8, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "SeabassPark", start: 10, end: 14}, {location: "DanceStudio", start: 14, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ] } }, /* ========== BAKERS (2) - Early Morning Shifts ========== */ "Hannah Chuckins": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 2}, {location: "Cafe", start: 2, end: 3}, {location: "Bakery", start: 3, end: 11}, {location: "SeabassPark", start: 11, end: 14}, {location: "ResidentialDistrict", start: 14, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Bakery", start: 6, end: 14}, {location: "GroceryStore", start: 14, end: 15}, {location: "ResidentialDistrict", start: 15, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 2}, {location: "Cafe", start: 2, end: 3}, {location: "Bakery", start: 3, end: 11}, {location: "Mall", start: 11, end: 14}, {location: "ResidentialDistrict", start: 14, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Bakery", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 2}, {location: "Cafe", start: 2, end: 3}, {location: "Bakery", start: 3, end: 11}, {location: "Mall", start: 11, end: 14}, {location: "ResidentialDistrict", start: 14, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Bakery", start: 6, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 11}, {location: "SeabassPark", start: 11, end: 15}, {location: "GroceryStore", start: 15, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ] } }, "Janis Besser": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Bakery", start: 6, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 2}, {location: "Cafe", start: 2, end: 3}, {location: "Bakery", start: 3, end: 11}, {location: "SeabassPark", start: 11, end: 14}, {location: "ResidentialDistrict", start: 14, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Bakery", start: 6, end: 14}, {location: "GroceryStore", start: 14, end: 15}, {location: "ResidentialDistrict", start: 15, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 2}, {location: "Cafe", start: 2, end: 3}, {location: "Bakery", start: 3, end: 11}, {location: "Mall", start: 11, end: 14}, {location: "ResidentialDistrict", start: 14, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "Bakery", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 2}, {location: "Cafe", start: 2, end: 3}, {location: "Bakery", start: 3, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "ResidentialDistrict", start: 15, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "Mall", start: 10, end: 13}, {location: "SeabassPark", start: 13, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ] } }, /* ========== ADULT STORE CLERKS (2) ========== */ "Destiny Pumpkin": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "AdultStore", start: 12, end: 20}, {location: "Alleyway", start: 20, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Tuesday": [ {location: "RedLightDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "AdultStore", start: 12, end: 20}, {location: "StripClub", start: 20, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Wednesday": [ {location: "RedLightDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "AdultStore", start: 12, end: 20}, {location: "Mall", start: 20, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Thursday": [ {location: "RedLightDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "AdultStore", start: 12, end: 20}, {location: "Alleyway", start: 20, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Friday": [ {location: "RedLightDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "AdultStore", start: 12, end: 20}, {location: "StripClub", start: 20, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 11}, {location: "Cafe", start: 11, end: 12}, {location: "AdultStore", start: 12, end: 20}, {location: "VIPLounge", start: 20, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 12}, {location: "Mall", start: 12, end: 16}, {location: "Alleyway", start: 16, end: 19}, {location: "RedLightDistrictHousing", start: 19, end: 24} ] } }, "Alex Passionfruit": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "AdultStore", start: 14, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Tuesday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "AdultStore", start: 14, end: 22}, {location: "StripClub", start: 22, end: 24} ], "Wednesday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "AdultStore", start: 14, end: 22}, {location: "Alleyway", start: 22, end: 24} ], "Thursday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "AdultStore", start: 14, end: 22}, {location: "Mall", start: 22, end: 24} ], "Friday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "AdultStore", start: 14, end: 22}, {location: "StripClub", start: 22, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 13}, {location: "Cafe", start: 13, end: 14}, {location: "AdultStore", start: 14, end: 22}, {location: "VIPLounge", start: 22, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Mall", start: 17, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ] } }, /* ========== DANCING INSTRUCTORS (2) ========== */ "Dennis Fungi": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "DanceStudio", start: 9, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "DanceStudio", start: 9, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "DanceStudio", start: 9, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "VIPLounge", start: 16, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "DanceStudio", start: 9, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "DanceStudio", start: 9, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Casino", start: 16, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "DanceStudio", start: 9, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "VIPLounge", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ] } }, "Yvela Mushroom": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "DanceStudio", start: 16, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 13}, {location: "Cafe", start: 15, end: 16}, {location: "DanceStudio", start: 16, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Mall", start: 12, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "DanceStudio", start: 16, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "Cafe", start: 15, end: 16}, {location: "DanceStudio", start: 16, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Cafe", start: 15, end: 16}, {location: "DanceStudio", start: 16, end: 21}, {location: "VIPLounge", start: 21, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "Cafe", start: 15, end: 16}, {location: "DanceStudio", start: 16, end: 21}, {location: "Casino", start: 21, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "GymNPCs", start: 11, end: 13}, {location: "Beach", start: 13, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, /* ========== BROTHEL WORKERS (7) - Varied Evening Schedules ========== */ "Candace Luxe": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "Mall", start: 15, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 24} ], "Tuesday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "BeautySalon", start: 16, end: 18}, {location: "Brothel", start: 18, end: 24} ], "Wednesday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "GymNPCs", start: 15, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 24} ], "Thursday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 24} ], "Friday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "Brothel", start: 18, end: 24} ], "Saturday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "BeautySalon", start: 15, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 24} ], "Sunday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "RedLightDistrictHousing", start: 19, end: 24} ] } }, "Ruby Becker": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 20, end: 24} ], "Tuesday": [ {location: "RedLightDistrictHousing", start: 0, end: 15}, {location: "GymNPCs", start: 15, end: 17}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Wednesday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "BeautySalon", start: 14, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Thursday": [ {location: "RedLightDistrictHousing", start: 0, end: 15}, {location: "Beach", start: 15, end: 18}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Friday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "VIPLounge", start: 17, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 15}, {location: "BeautySalon", start: 15, end: 17}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "RedLightDistrictHousing", start: 21, end: 24} ] } }, "Sapphire Wallace": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "Cafe", start: 20, end: 21}, {location: "Brothel", start: 21, end: 24} ], "Tuesday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "GymNPCs", start: 15, end: 17}, {location: "BeautySalon", start: 17, end: 19}, {location: "Cafe", start: 20, end: 21}, {location: "Brothel", start: 21, end: 24} ], "Wednesday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "Cafe", start: 20, end: 21}, {location: "Brothel", start: 21, end: 24} ], "Thursday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "Cafe", start: 20, end: 21}, {location: "Brothel", start: 21, end: 24} ], "Friday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "VIPLounge", start: 16, end: 20}, {location: "Cafe", start: 20, end: 21}, {location: "Brothel", start: 21, end: 24} ], "Saturday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "BeautySalon", start: 15, end: 17}, {location: "Mall", start: 17, end: 20}, {location: "Cafe", start: 20, end: 21}, {location: "Brothel", start: 21, end: 24} ], "Sunday": [ {location: "Brothel", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "Beach", start: 15, end: 19}, {location: "RedLightDistrictHousing", start: 19, end: 24} ] } }, "Jasmine Abrams": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Tuesday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Wednesday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "BeautySalon", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Thursday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Friday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 23}, {location: "RedLightDistrictHousing", start: 23, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "RedLightDistrictHousing", start: 21, end: 24} ] } }, "Ebony Vasquez": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 18, end: 19}, {location: "Brothel", start: 19, end: 24} ], "Tuesday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 15}, {location: "GymNPCs", start: 15, end: 17}, {location: "Cafe", start: 18, end: 19}, {location: "Brothel", start: 19, end: 24} ], "Wednesday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 14}, {location: "BeautySalon", start: 14, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "Cafe", start: 18, end: 19}, {location: "Brothel", start: 19, end: 24} ], "Thursday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Cafe", start: 18, end: 19}, {location: "Brothel", start: 19, end: 24} ], "Friday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "Cafe", start: 18, end: 19}, {location: "Brothel", start: 19, end: 24} ], "Saturday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 14}, {location: "VIPLounge", start: 14, end: 18}, {location: "Cafe", start: 18, end: 19}, {location: "Brothel", start: 19, end: 24} ], "Sunday": [ {location: "Brothel", start: 0, end: 1}, {location: "RedLightDistrictHousing", start: 1, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "RedLightDistrictHousing", start: 21, end: 24} ] } }, "Amber Skye": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Tuesday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "BeautySalon", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Wednesday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Thursday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Friday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "BeautySalon", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Brothel", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "RedLightDistrictHousing", start: 21, end: 24} ] } }, "Selkira Onyxia": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Tuesday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 15}, {location: "BeautySalon", start: 15, end: 17}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Wednesday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 14}, {location: "DanceStudio", start: 14, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Thursday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Friday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 15}, {location: "VIPLounge", start: 15, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Saturday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Brothel", start: 20, end: 24} ], "Sunday": [ {location: "Brothel", start: 0, end: 3}, {location: "RedLightDistrictHousing", start: 3, end: 15}, {location: "Beach", start: 15, end: 19}, {location: "RedLightDistrictHousing", start: 19, end: 24} ] } }, /* ========== SINGLE-EMPLOYEE JOBS ========== */ "Tank Morrison": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Tuesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Wednesday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "TheAngler", start: 17, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Thursday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Friday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Saturday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "StripClub", start: 18, end: 24} ], "Sunday": [ {location: "StripClub", start: 0, end: 2}, {location: "RedLightDistrictHousing", start: 2, end: 12}, {location: "GymNPCs", start: 12, end: 15}, {location: "Beach", start: 15, end: 19}, {location: "RedLightDistrictHousing", start: 19, end: 24} ] } }, "Diamond Murphy": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Alleyway", start: 20, end: 24} ], "Tuesday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "GymNPCs", start: 15, end: 17}, {location: "Cafe", start: 19, end: 20}, {location: "Alleyway", start: 20, end: 24} ], "Wednesday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "BeautySalon", start: 16, end: 18}, {location: "Cafe", start: 19, end: 20}, {location: "Alleyway", start: 20, end: 24} ], "Thursday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "Cafe", start: 19, end: 20}, {location: "Alleyway", start: 20, end: 24} ], "Friday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "Cafe", start: 19, end: 20}, {location: "Alleyway", start: 20, end: 24} ], "Saturday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "Mall", start: 15, end: 19}, {location: "Cafe", start: 19, end: 20}, {location: "Alleyway", start: 20, end: 24} ], "Sunday": [ {location: "Alleyway", start: 0, end: 4}, {location: "RedLightDistrictHousing", start: 4, end: 15}, {location: "Beach", start: 15, end: 19}, {location: "RedLightDistrictHousing", start: 19, end: 24} ] } }, "Kate Velvet": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 12}, {location: "Mall", start: 12, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 24} ], "Tuesday": [ {location: "Brothel", start: 0, end: 1}, {location: "BusinessDistrictHousing", start: 1, end: 12}, {location: "BeautySalon", start: 12, end: 14}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 24} ], "Wednesday": [ {location: "Brothel", start: 0, end: 1}, {location: "BusinessDistrictHousing", start: 1, end: 12}, {location: "GymNPCs", start: 12, end: 14}, {location: "Mall", start: 14, end: 16}, {location: "Brothel", start: 16, end: 24} ], "Thursday": [ {location: "Brothel", start: 0, end: 1}, {location: "BusinessDistrictHousing", start: 1, end: 12}, {location: "VIPLounge", start: 12, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 24} ], "Friday": [ {location: "Brothel", start: 0, end: 1}, {location: "BusinessDistrictHousing", start: 1, end: 12}, {location: "Mall", start: 12, end: 15}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 24} ], "Saturday": [ {location: "Brothel", start: 0, end: 1}, {location: "BusinessDistrictHousing", start: 1, end: 12}, {location: "BeautySalon", start: 12, end: 14}, {location: "Cafe", start: 15, end: 16}, {location: "Brothel", start: 16, end: 24} ], "Sunday": [ {location: "Brothel", start: 0, end: 1}, {location: "BusinessDistrictHousing", start: 1, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ] } }, "Bella Carver": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Mall", start: 10, end: 16}, {location: "BeautySalon", start: 16, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Mall", start: 10, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Mall", start: 10, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Mall", start: 10, end: 16}, {location: "VIPLounge", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Mall", start: 10, end: 16}, {location: "BeautySalon", start: 16, end: 18}, {location: "VIPLounge", start: 18, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "Mall", start: 10, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ] } }, "Kevin Oats": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TechStore", start: 10, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TechStore", start: 10, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TechStore", start: 10, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TechStore", start: 10, end: 18}, {location: "SeabassPark", start: 18, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TechStore", start: 10, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "TechStore", start: 10, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "Mall", start: 13, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ] } }, "Raven Bido": { defaultLocation: "RedLightDistrictHousing", customSchedule: { "Monday": [ {location: "RedLightDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "EcentricShop", start: 10, end: 18}, {location: "Alleyway", start: 18, end: 21}, {location: "RedLightDistrictHousing", start: 21, end: 24} ], "Tuesday": [ {location: "RedLightDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "EcentricShop", start: 10, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ], "Wednesday": [ {location: "RedLightDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "EcentricShop", start: 10, end: 18}, {location: "Alleyway", start: 18, end: 21}, {location: "RedLightDistrictHousing", start: 21, end: 24} ], "Thursday": [ {location: "RedLightDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "EcentricShop", start: 10, end: 18}, {location: "SeabassPark", start: 18, end: 20}, {location: "RedLightDistrictHousing", start: 20, end: 24} ], "Friday": [ {location: "RedLightDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "EcentricShop", start: 10, end: 18}, {location: "StripClub", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "RedLightDistrictHousing", start: 0, end: 9}, {location: "Cafe", start: 9, end: 10}, {location: "EcentricShop", start: 10, end: 18}, {location: "Alleyway", start: 18, end: 22}, {location: "RedLightDistrictHousing", start: 22, end: 24} ], "Sunday": [ {location: "RedLightDistrictHousing", start: 0, end: 12}, {location: "Mall", start: 12, end: 15}, {location: "Alleyway", start: 15, end: 18}, {location: "RedLightDistrictHousing", start: 18, end: 24} ] } }, "Banana Banana": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 6, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 6, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 6, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 6, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 6, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "VIPLounge", start: 16, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 6, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "BusinessDistrictHousing", start: 18, end: 24} ] } }, "Trixie Rye": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Casino", start: 18, end: 24} ], "Tuesday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "GymNPCs", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Casino", start: 18, end: 24} ], "Wednesday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "BeautySalon", start: 14, end: 16}, {location: "Cafe", start: 17, end: 18}, {location: "Casino", start: 18, end: 24} ], "Thursday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Casino", start: 18, end: 24} ], "Friday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "Beach", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Casino", start: 18, end: 24} ], "Saturday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "Mall", start: 14, end: 17}, {location: "Cafe", start: 17, end: 18}, {location: "Casino", start: 18, end: 24} ], "Sunday": [ {location: "Casino", start: 0, end: 2}, {location: "BusinessDistrictHousing", start: 2, end: 14}, {location: "Beach", start: 14, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ] } }, "Xenis Aku": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "BusStop", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "BusStop", start: 6, end: 14}, {location: "TheAngler", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "BusStop", start: 6, end: 14}, {location: "SeabassPark", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "BusStop", start: 6, end: 14}, {location: "GroceryStore", start: 14, end: 15}, {location: "ResidentialDistrict", start: 15, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "BusStop", start: 6, end: 14}, {location: "TheAngler", start: 14, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "BusStop", start: 6, end: 14}, {location: "Docks", start: 14, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "SeabassPark", start: 10, end: 14}, {location: "TheAngler", start: 14, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Pheiffer Coms": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "TheAngler", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "SeabassPark", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "TheAngler", start: 18, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ] } }, "Fen Ris": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "FenRisTraining", start: 6, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "FenRisTraining", start: 6, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "FenRisTraining", start: 6, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "FenRisTraining", start: 6, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "FenRisTraining", start: 6, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 5}, {location: "Cafe", start: 5, end: 6}, {location: "FenRisTraining", start: 6, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 10}, {location: "Beach", start: 10, end: 14}, {location: "GymNPCs", start: 14, end: 17}, {location: "BusinessDistrictHousing", start: 17, end: 24} ] } }, "Brad Icus": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "FitnessShop", start: 8, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "FitnessShop", start: 8, end: 17}, {location: "Beach", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "FitnessShop", start: 8, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "FitnessShop", start: 8, end: 17}, {location: "Mall", start: 17, end: 19}, {location: "BusinessDistrictHousing", start: 19, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "FitnessShop", start: 8, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "VIPLounge", start: 19, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "FitnessShop", start: 8, end: 17}, {location: "Beach", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 9}, {location: "GymNPCs", start: 9, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "BusinessDistrictHousing", start: 16, end: 24} ] } }, "Sunny Flipflop": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 17}, {location: "Beach", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 17}, {location: "Mall", start: 17, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 17}, {location: "GymNPCs", start: 17, end: 19}, {location: "TheAngler", start: 19, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "Downtown", start: 9, end: 17}, {location: "Beach", start: 17, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 10}, {location: "GymNPCs", start: 10, end: 12}, {location: "Beach", start: 12, end: 16}, {location: "ResidentialDistrict", start: 16, end: 24} ] } }, "Bongo Bongo": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Mall", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "GymNPCs", start: 16, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "VIPLounge", start: 19, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "Downtown", start: 8, end: 16}, {location: "Beach", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 11}, {location: "Beach", start: 11, end: 15}, {location: "Mall", start: 15, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ] } }, "Butt Johnson": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "MeetNeighbors", start: 15, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "TechStore", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "MeetNeighbors", start: 15, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "MeetNeighbors", start: 15, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "Mall", start: 12, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "MeetNeighbors", start: 15, end: 22}, {location: "ResidentialDistrict", start: 22, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "MeetNeighbors", start: 15, end: 24} ], "Saturday": [ {location: "MeetNeighbors", start: 0, end: 3}, {location: "ResidentialDistrict", start: 3, end: 14}, {location: "Cafe", start: 14, end: 15}, {location: "MeetNeighbors", start: 15, end: 24} ], "Sunday": [ {location: "MeetNeighbors", start: 0, end: 3}, {location: "ResidentialDistrict", start: 3, end: 16}, {location: "Mall", start: 16, end: 19}, {location: "ResidentialDistrict", start: 19, end: 24} ] } }, "Dick Richardson": { defaultLocation: "BusinessDistrictHousing", customSchedule: { "Monday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Tuesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "Casino", start: 17, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Wednesday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Thursday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "TheAngler", start: 17, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ], "Friday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "Casino", start: 17, end: 22}, {location: "BusinessDistrictHousing", start: 22, end: 24} ], "Saturday": [ {location: "BusinessDistrictHousing", start: 0, end: 8}, {location: "Cafe", start: 8, end: 9}, {location: "TownHall", start: 9, end: 17}, {location: "VIPLounge", start: 17, end: 21}, {location: "BusinessDistrictHousing", start: 21, end: 24} ], "Sunday": [ {location: "BusinessDistrictHousing", start: 0, end: 12}, {location: "TheAngler", start: 12, end: 16}, {location: "VIPLounge", start: 16, end: 20}, {location: "BusinessDistrictHousing", start: 20, end: 24} ] } }, "Creo Applesauce": { defaultLocation: "ResidentialDistrict", customSchedule: { "Monday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "TownHall", start: 8, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Tuesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "TownHall", start: 8, end: 18}, {location: "Mall", start: 18, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Wednesday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "TownHall", start: 8, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Thursday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "TownHall", start: 8, end: 18}, {location: "SeabassPark", start: 18, end: 20}, {location: "ResidentialDistrict", start: 20, end: 24} ], "Friday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "TownHall", start: 8, end: 18}, {location: "Mall", start: 18, end: 21}, {location: "ResidentialDistrict", start: 21, end: 24} ], "Saturday": [ {location: "ResidentialDistrict", start: 0, end: 7}, {location: "Cafe", start: 7, end: 8}, {location: "TownHall", start: 8, end: 18}, {location: "ResidentialDistrict", start: 18, end: 24} ], "Sunday": [ {location: "ResidentialDistrict", start: 0, end: 12}, {location: "Cafe", start: 12, end: 13}, {location: "SeabassPark", start: 13, end: 17}, {location: "ResidentialDistrict", start: 17, end: 24} ] } }, /* Quesha Epo - Hidden Lagoon resident; Beach Dive Shop on workdays. Pre-intro override (always HiddenLagoon) lives in the setup.getQueshaLocation wrapper in the JS section. */ "Quesha Epo": { defaultLocation: "HiddenLagoon", customSchedule: { "Monday": [{location: "HiddenLagoon", start: 0, end: 6}, {location: "QueshaDiveShop", start: 6, end: 22}, {location: "HiddenLagoon", start: 22, end: 24}], "Tuesday": [{location: "HiddenLagoon", start: 0, end: 6}, {location: "QueshaDiveShop", start: 6, end: 22}, {location: "HiddenLagoon", start: 22, end: 24}], "Wednesday": [{location: "HiddenLagoon", start: 0, end: 6}, {location: "QueshaDiveShop", start: 6, end: 22}, {location: "HiddenLagoon", start: 22, end: 24}], "Thursday": [{location: "HiddenLagoon", start: 0, end: 6}, {location: "QueshaDiveShop", start: 6, end: 22}, {location: "HiddenLagoon", start: 22, end: 24}], "Friday": [{location: "HiddenLagoon", start: 0, end: 6}, {location: "QueshaDiveShop", start: 6, end: 22}, {location: "HiddenLagoon", start: 22, end: 24}], "Saturday": [{location: "HiddenLagoon", start: 0, end: 24}], "Sunday": [{location: "HiddenLagoon", start: 0, end: 12}, {location: "QueshaDiveShop", start: 12, end: 22}, {location: "HiddenLagoon", start: 22, end: 24}] } } }>> /* Job-based schedule templates - used when NPC changes jobs */ <<set setup.jobScheduleTemplates = { "Stripper": { workLocation: "StripClub", workStart: 18, workEnd: 2, defaultHome: "RedLightDistrictHousing" }, "Porn Star": { workLocation: "ModelingStudioAdult", workStart: 12, workEnd: 18, defaultHome: "BusinessDistrictHousing" }, "Prostitute": { workLocation: "Alleyway", workStart: 17, workEnd: 2, defaultHome: "RedLightDistrictHousing" }, "Security Guard": { workLocation: "Downtown", workStart: 8, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Clinic Assistant": { workLocation: "Hospital", workStart: 8, workEnd: 17, defaultHome: "BusinessDistrictHousing" }, "Package Courier": { workLocation: "CommercialDistrict", workStart: 7, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Negotiator": { workLocation: "Alleyway", workStart: 12, workEnd: 18, defaultHome: "BusinessDistrictHousing" }, "Retail Worker": { workLocation: "Mall", workStart: 9, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Barista": { workLocation: "Cafe", workStart: 6, workEnd: 14, defaultHome: "ResidentialDistrict" }, "Fisherman": { workLocation: "Docks", workStart: 5, workEnd: 15, defaultHome: "OutskirtsHousing" }, "Dock Worker": { workLocation: "Docks", workStart: 8, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Government Worker": { workLocation: "TownHall", workStart: 9, workEnd: 17, defaultHome: "BusinessDistrictHousing" }, "Black Market Dealer": { workLocation: "Alleyway", workStart: 18, workEnd: 2, defaultHome: "OutskirtsHousing" }, "Casino Worker": { workLocation: "Casino", workStart: 14, workEnd: 22, defaultHome: "ResidentialDistrict" }, "Social Media Influencer": { workLocation: "Mall", workStart: 10, workEnd: 18, defaultHome: "BusinessDistrictHousing" }, "Police Officer": { workLocation: "Downtown", workStart: 8, workEnd: 18, defaultHome: "ResidentialDistrict" }, "Farm Hand": { workLocation: "Outskirts", workStart: 6, workEnd: 16, defaultHome: "OutskirtsHousing" }, "Grocery Clerk": { workLocation: "GroceryStore", workStart: 8, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Construction Worker": { workLocation: "Outskirts", workStart: 6, workEnd: 16, defaultHome: "OutskirtsHousing" }, "Baker": { workLocation: "Bakery", workStart: 4, workEnd: 12, defaultHome: "ResidentialDistrict" }, "Maid": { workLocation: "ResidentialDistrict", workStart: 8, workEnd: 16, defaultHome: "ResidentialDistrict" }, "Fitness Shop Clerk": { workLocation: "FitnessShop", workStart: 9, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Ecentric Shop Worker": { workLocation: "EcentricShop", workStart: 10, workEnd: 18, defaultHome: "ResidentialDistrict" }, "Tech Store Clerk": { workLocation: "TechStore", workStart: 9, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Adult Store Clerk": { workLocation: "AdultStore", workStart: 12, workEnd: 20, defaultHome: "RedLightDistrictHousing" }, "Beauty Salon Stylist": { workLocation: "BeautySalon", workStart: 9, workEnd: 17, defaultHome: "ResidentialDistrict" }, "Bouncer": { workLocation: "StripClub", workStart: 18, workEnd: 2, defaultHome: "RedLightDistrictHousing" }, "Data Analyst": { workLocation: "BusinessDistrict", workStart: 9, workEnd: 17, defaultHome: "BusinessDistrictHousing" }, "Enforcer": { workLocation: "Downtown", workStart: 18, workEnd: 2, defaultHome: "RedLightDistrictHousing" }, "Bus Driver": { workLocation: "BusStop", workStart: 6, workEnd: 16, defaultHome: "ResidentialDistrict" }, "Donuts Deliverer": { workLocation: "Bakery", workStart: 5, workEnd: 13, defaultHome: "ResidentialDistrict" }, "Cocktail Waitress": { workLocation: "Casino", workStart: 14, workEnd: 22, defaultHome: "ResidentialDistrict" }, "Fitness Trainer": { workLocation: "FenRisTraining", workStart: 8, workEnd: 18, defaultHome: "ResidentialDistrict" }, "Street Performer": { workLocation: "SeabassPark", workStart: 10, workEnd: 18, defaultHome: "ResidentialDistrict" }, "Musician": { workLocation: "MeetNeighbors", workStart: 10, workEnd: 18, defaultHome: "ResidentialDistrict" }, "Dancing Instructor": { workLocation: "DanceStudio", workStart: 10, workEnd: 18, defaultHome: "ResidentialDistrict" }, "Model": { workLocation: "ModelingStudio", workStart: 10, workEnd: 18, defaultHome: "BusinessDistrictHousing" }, "Police Station Janitor": { workLocation: "PoliceDepartment", workStart: 6, workEnd: 14, defaultHome: "ResidentialDistrict" }, "Police Station Receptionist": { workLocation: "PoliceDepartment", workStart: 8, workEnd: 17, defaultHome: "ResidentialDistrict" } }>> /* Generate a dynamic schedule based on NPC's current job */ <<set setup.generateJobBasedSchedule = function(npc) { var job = npc.job || (Array.isArray(npc.jobs) ? npc.jobs[0] : npc.jobs) || ""; var template = setup.jobScheduleTemplates[job]; if (!template) { /* No template for this job, return null to use default behavior */ return null; } var homeLocation = npc.residence || template.defaultHome; var workLocation = template.workLocation; var workStart = template.workStart; var workEnd = template.workEnd; var schedule = {}; var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; /* Weekday schedule (Mon-Fri) */ for (var i = 0; i < 5; i++) { var day = days[i]; if (workEnd < workStart) { /* Night shift job (crosses midnight) */ schedule[day] = [ {location: homeLocation, start: 0, end: workEnd}, {location: homeLocation, start: workEnd, end: workStart - 1}, {location: "Cafe", start: workStart - 1, end: workStart}, {location: workLocation, start: workStart, end: 24} ]; } else { /* Day shift job */ schedule[day] = [ {location: homeLocation, start: 0, end: workStart - 1}, {location: "Cafe", start: workStart - 1, end: workStart}, {location: workLocation, start: workStart, end: workEnd}, {location: homeLocation, start: workEnd, end: 24} ]; } } /* Weekend schedule (lighter) */ schedule["Saturday"] = [ {location: homeLocation, start: 0, end: 10}, {location: "Beach", start: 10, end: 15}, {location: "Mall", start: 15, end: 18}, {location: homeLocation, start: 18, end: 24} ]; schedule["Sunday"] = [ {location: homeLocation, start: 0, end: 12}, {location: "SeabassPark", start: 12, end: 17}, {location: homeLocation, start: 17, end: 24} ]; return schedule; }>> /* Swap schedules between two NPCs (for identity swap) */ <<set setup.swapNPCSchedules = function(npc1Name, npc2Name) { var schedule1 = setup.npcLocationSchedules[npc1Name]; var schedule2 = setup.npcLocationSchedules[npc2Name]; /* Swap the schedules */ if (schedule1 && schedule2) { setup.npcLocationSchedules[npc1Name] = schedule2; setup.npcLocationSchedules[npc2Name] = schedule1; } }>> /* Update NPC schedule when job changes */ <<set setup.updateNPCScheduleForJob = function(npcName, newJob) { var npc = setup.findNPCByName(npcName); if (!npc) return; /* Store original schedule if not already stored */ if (!npc.originalSchedule && setup.npcLocationSchedules[npcName]) { npc.originalSchedule = JSON.parse(JSON.stringify(setup.npcLocationSchedules[npcName])); } /* Generate new schedule based on job */ npc.job = newJob; var newSchedule = setup.generateJobBasedSchedule(npc); if (newSchedule) { if (!setup.npcLocationSchedules[npcName]) { setup.npcLocationSchedules[npcName] = {}; } setup.npcLocationSchedules[npcName].customSchedule = newSchedule; } }>> /* Get NPC's current location based on job, custom schedule, day, time, and traits */ <<set setup.getNPCLocation = function(npcNameOrObject, dayOfWeek, hour) { var npc = typeof npcNameOrObject === 'string' ? setup.findNPCByName(npcNameOrObject) : npcNameOrObject; if (!npc) return null; /* LIFE SWAP OVERRIDE - Check for forced location first (highest priority) */ if (npc.forcedLocation) { return npc.forcedLocation; } /* Check if NPC has a redirected schedule from life swap */ var scheduleKey = npc.scheduleSource || npc.originalName || npc.permanentId || npc.name; var schedule = setup.npcLocationSchedules[scheduleKey]; /* If NPC has custom schedule in new system, use that */ if (schedule) { /* Check individual trait-based overrides FIRST (they take priority over global Bimbo) */ if (schedule.traitOverrides) { for (var trait in schedule.traitOverrides) { var hasTrait = false; if (npc.mentalTraits && npc.mentalTraits.includes(trait)) hasTrait = true; if (npc.physicalTraits && npc.physicalTraits.includes(trait)) hasTrait = true; if (hasTrait) { var traitSchedule = schedule.traitOverrides[trait]; if (traitSchedule[dayOfWeek]) { var daySchedule = traitSchedule[dayOfWeek]; for (var i = 0; i < daySchedule.length; i++) { var slot = daySchedule[i]; if (hour >= slot.start && hour < slot.end) { return slot.location; } } } } } } /* Global Bimbo trait override (only applies if no individual override was found) */ var hasBimbo = false; if (npc.mentalTraits && npc.mentalTraits.includes("Bimbo")) hasBimbo = true; if (hasBimbo) { /* Skip Bimbo override if NPC has a job with a mapped work location and is during work hours */ var bimboSkip = false; if (npc.jobs && npc.jobs.length > 0 && schedule.customSchedule && schedule.customSchedule[dayOfWeek]) { var primaryJob = npc.jobs[0]; var jobLoc = setup.jobLocations[primaryJob]; if (jobLoc) { var daySlots = schedule.customSchedule[dayOfWeek]; for (var j = 0; j < daySlots.length; j++) { if (daySlots[j].location === jobLoc && hour >= daySlots[j].start && hour < daySlots[j].end) { bimboSkip = true; break; } } } } if (!bimboSkip) { /* After 8pm (20:00), go to MeetNeighbors */ if (hour >= 20 || hour < 6) { return "MeetNeighbors"; } /* During the day, alternate between Mall and Park based on day */ var dayIndex = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"].indexOf(dayOfWeek); if (dayIndex % 2 === 0) { return "Mall"; } else { return "SeabassPark"; } } } /* Check custom schedule */ if (schedule.customSchedule && schedule.customSchedule[dayOfWeek]) { var daySchedule = schedule.customSchedule[dayOfWeek]; for (var i = 0; i < daySchedule.length; i++) { var slot = daySchedule[i]; if (hour >= slot.start && hour < slot.end) { var location = slot.location; /* Translate ResidentialDistrict to NPC's actual housing */ if (location === "ResidentialDistrict" && npc.residence) { var housingLocation = setup.housingToScheduleLocation[npc.residence]; if (housingLocation) { return housingLocation; } } return location; } } } /* Default location for this NPC */ if (schedule.defaultLocation) { var defaultLoc = schedule.defaultLocation; /* Translate ResidentialDistrict to NPC's actual housing */ if (defaultLoc === "ResidentialDistrict" && npc.residence) { var housingLocation = setup.housingToScheduleLocation[npc.residence]; if (housingLocation) { return housingLocation; } } return defaultLoc; } } /* Fall back to job-based location */ var primaryJob = Array.isArray(npc.jobs) ? npc.jobs[0] : npc.jobs; var jobLocation = setup.jobLocations[primaryJob] || null; /* Translate ResidentialDistrict to NPC's actual housing for job-based fallback too */ if (jobLocation === "ResidentialDistrict" && npc.residence) { var housingLocation = setup.housingToScheduleLocation[npc.residence]; if (housingLocation) { return housingLocation; } } return jobLocation; }>> /* Get all NPCs at a specific location */ <<set setup.getNPCsAtLocation = function(location) { var v = State.variables; var dayOfWeek = v.dayOfWeek || "Monday"; var hour = Math.floor(v.timeInMinutes / 60) % 24; var npcsHere = []; for (var i = 0; i < v.npcs.length; i++) { /* Skip NPCs absorbed into witch form or otherwise hidden */ if (v.npcs[i].hiddenFromWorld) continue; var npcLocation = setup.getNPCLocation(v.npcs[i], dayOfWeek, hour); if (npcLocation === location) { npcsHere.push(v.npcs[i]); } } return npcsHere; }>> /* Check if NPC uses new location system */ <<set setup.usesLocationSystem = function(npcName) { return setup.npcLocationSchedules[npcName] !== undefined; }>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">💪 Opah Fitness - Closing Time</h1> <div style="background: #2a2a2a; border: 3px solid #ffc107; padding: 30px; border-radius: 12px; text-align: center; margin: 50px auto; max-width: 700px; box-shadow: 0 6px 12px rgba(0,0,0,0.5);"> <p style="color: #ffc107; font-size: 26px; font-weight: bold; margin: 0 0 20px 0;">⏰ Time's Up!</p> <p style="color: #ccc; font-size: 16px; margin: 0 0 20px 0; line-height: 1.8;"> As you finish your workout, the gym staff politely inform you that it's closing time. The lights start dimming and other members are heading to the locker rooms to shower and change. </p> <p style="color: #aaa; font-size: 14px; margin: 0 0 25px 0; font-style: italic;"> "Great workout today! We're closing up for the night. Come back tomorrow between 5 AM and 9 PM!" </p> <div style="background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 25px;"> <p style="color: #ff6b6b; font-size: 14px; margin: 0; font-weight: bold;"> You gather your things and head out. </p> </div> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Leave the Gym</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PoliceDepartment">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("PoliceDepartment")>> <<run $visitedLocations.push("PoliceDepartment")>> <</if>> /* Check if player is a Criminal and arrest them */ <<if $jobs && $jobs.includes("Criminal")>> <<set $arrestedAtStation = true>> <<goto "CaughtByPolice">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4169e1; text-align: center;">🚔 Sunfish City Police Department</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/PoliceDepartment.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #4169e1; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Police Department"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #4169e1 0%, #1e3a8a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4169e1;"> <p style="color: white; font-size: 18px; margin: 0;"> The main headquarters of the Sunfish City Police Department. The lobby is clean and professional, with officers and staff moving purposefully through the corridors. Behind the reception desk, you can see doors leading to various departments, holding cells, and administrative offices. </p> </div> <!-- Check for Receptionist --> <<set _receptionistNPC = null>> <<set _receptionistJobs = setup.getNPCsByJob("Police Station Receptionist")>> <<if _receptionistJobs && _receptionistJobs.length > 0>> <<set _receptionistNPC = _receptionistJobs[0]>> <</if>> <!-- Receptionist Interaction (if present) --> <<if _receptionistNPC>> <h2 style="color: #e83e8c;">Reception Desk</h2> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin-top: 0;">💼 Talk to <<print _receptionistNPC.name>></h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">The receptionist is at the front desk. You could ask about job opportunities.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to Receptionist</div>">> <<set $talkingToReceptionist = _receptionistNPC>> <<goto "PoliceReceptionistTalk">> <</link>> </div> </div> <</if>> <h2 style="color: #4169e1;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-top: 20px;"> <!-- Jail --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #666; margin-top: 0;">🔒 Holding Cells</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">The jail where arrested individuals are held.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Jail</div>">> <<goto "Jail">> <</link>> </div> <!-- Break Room (Police Staff Only) --> <<set _hasPoliceJob = false>> <<set _policeJobTypes = ["Sheriff", "Patrol Officer", "Detective", "Police Station Receptionist", "Police Station Janitor"]>> <<if $jobs && Array.isArray($jobs)>> <<for _policeJob range _policeJobTypes>> <<if $jobs.includes(_policeJob)>> <<set _hasPoliceJob = true>> <</if>> <</for>> <</if>> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin-top: 0;">☕ Officer Break Room</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">A private break room for police officers.</p> <<if _hasPoliceJob>> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'> Staff Only </div> <</if>> </div> <!-- Return to Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin-top: 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Return to downtown.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Police Department</div>">> <<goto "Downtown">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = []>> <<set _policeJobs = ["Sheriff", "Patrol Officer", "Detective", "Police Station Receptionist", "Police Station Janitor", "Donuts Deliverer"]>> <<for _job range _policeJobs>> <<set _jobNPCs = setup.getNPCsByJob(_job)>> <<if _jobNPCs && _jobNPCs.length > 0>> <<set _npcsHere = _npcsHere.concat(_jobNPCs)>> <</if>> <</for>> <h2 style="color: #4169e1;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4169e1; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #4169e1; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #4169e1; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The station seems quiet at the moment. No officers or staff are visible in the lobby. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PoliceBreakRoom">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("PoliceBreakRoom")>> <<run $visitedLocations.push("PoliceBreakRoom")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">☕ Police Department Break Room</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/PoliceBreakRoom.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Break Room"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #17a2b8 0%, #00d4ff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> A comfortable break room for police department staff. The room has several couches, a coffee maker that's constantly brewing, a small kitchenette with a fridge, and a TV mounted on the wall. A table in the corner is scattered with boxes of donuts. The atmosphere is relaxed and casual compared to the rest of the station. </p> </div> <!-- Work Section --> <<set _hasWorkableJob = false>> <<if $jobs && Array.isArray($jobs)>> <<if $jobs.includes("Sheriff") || $jobs.includes("Patrol Officer") || $jobs.includes("Police Station Receptionist") || $jobs.includes("Police Station Janitor")>> <<set _hasWorkableJob = true>> <</if>> <</if>> <<if _hasWorkableJob>> <h2 style="color: #ffd43b;">Work</h2> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- Patrol Officer Work --> <<if $jobs && $jobs.includes("Patrol Officer")>> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin-top: 0;">🚓 Patrol Duty</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Head out on patrol.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work</div>">> <<goto "PatrolOfficerWork">> <</link>> </div> <</if>> <!-- Receptionist Work - Universal System --> <<if $jobs && $jobs.includes("Police Station Receptionist")>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin-top: 0;">💼 Reception Desk</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Work at the front desk. (Max 8 hours/day)</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work</div>">> <<goto "UniversalWork">> <</link>> </div> <</if>> <!-- Janitor Work - Universal System --> <<if $jobs && $jobs.includes("Police Station Janitor")>> <div style="border: 3px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #95a5a6; margin-top: 0;">🧹 Janitorial Duties</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Clean the station. (Max 8 hours/day)</p> <<link "<div style='background: #95a5a6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Work</div>">> <<goto "UniversalWork">> <</link>> </div> <</if>> </div> <</if>> <h2 style="color: #17a2b8;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; margin-top: 20px;"> <!-- Get Coffee --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.5;"> <h3 style="color: #666; margin-top: 0;">☕ Get Coffee</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Pour yourself a cup of coffee. It's been sitting here a while, but it's free.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Eat Donuts --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.5;"> <h3 style="color: #666; margin-top: 0;">🍩 Eat Donuts</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Help yourself to the communal donuts. There's always a fresh box around here.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Watch TV --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.5;"> <h3 style="color: #666; margin-top: 0;">📺 Watch TV</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Relax and watch some TV for a while. There's usually a game or news on.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Take a Nap --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.5;"> <h3 style="color: #666; margin-top: 0;">😴 Take a Nap</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Catch some Z's on the couch. No one will judge you here.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Return to Police Department --> <div style="border: 3px solid #4169e1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4169e1; margin-top: 0;">🚔 Back to Station</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Return to the main police department lobby.</p> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Break Room</div>">> <<goto "PoliceDepartment">> <</link>> </div> </div> <div id="breakRoomMessage"></div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("PoliceBreakRoom")>> <h2 style="color: #17a2b8;">Officers on Break</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The break room is empty at the moment. Everyone must be out on duty. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SheriffWork">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">⭐ Sheriff's Office</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ffd700 0%, #f39c12 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700;"> <p style="color: white; font-size: 18px; margin: 0;"> Sheriff work content will go here. </p> </div> <<link "<div style='background: #2ecc71; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolOfficerWork">> <!-- Check if player has Driving skill --> <<set _hasDriving = $skills && $skills.includes("Driving")>> <!-- Check if enough time has passed since last patrol (16 hours = 960 minutes) --> <<if !$lastPatrolEndTime>> <<set $lastPatrolEndTime = 0>> <</if>> <<set _timeSinceLastPatrol = setup.getTotalGameMinutes() - $lastPatrolEndTime>> <<set _canPatrol = (_timeSinceLastPatrol >= 960 || $lastPatrolEndTime === 0) && _hasDriving>> <<set _timeRemaining = 960 - _timeSinceLastPatrol>> <<set _hoursRemaining = Math.floor(_timeRemaining / 60)>> <<set _minutesRemaining = _timeRemaining % 60>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">🚓 Patrol Duty</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0;"> Time to hit the streets and keep Sunfish City safe. You can patrol for up to 8 hours per day. Your patrol car is waiting outside, ready to take you anywhere in the city. </p> </div> <<if !_hasDriving>> <div style="background: #000; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; text-align: center;">⚠️ NO DRIVING SKILL ⚠️</h3> <p style="color: #e0e0e0; text-align: center; margin: 0;"> You need the <strong style="color: #ffd43b;">Driving</strong> skill to operate a patrol vehicle. You cannot go on patrol without it. </p> </div> <<elseif !_canPatrol>> <div style="background: #000; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0; text-align: center;">⚠️ TOO EXHAUSTED TO PATROL ⚠️</h3> <p style="color: #e0e0e0; text-align: center; margin: 0;"> You're too exhausted from your last shift. You need to rest for <strong style="color: #ffd43b;"><<print _hoursRemaining>> hours and <<print _minutesRemaining>> minutes</strong> before you can patrol again. </p> </div> <</if>> <h2 style="color: #3498db;">Start Your Shift</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Begin Patrol --> <div style="border: 3px solid <<if _canPatrol>>#28a745<<else>>#666<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; <<if !_canPatrol>>opacity: 0.5;<</if>>"> <h3 style="color: <<if _canPatrol>>#28a745<<else>>#666<</if>>; margin-top: 0;">🚨 Begin Patrol</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Start your 8-hour patrol shift. You'll be paid $35/hour.</p> <p style="font-size: 14px; color: <<if _canPatrol>>#28a745<<else>>#666<</if>>; margin: 10px 0; font-weight: bold;">Pay: $280 for full shift</p> <<if _canPatrol>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Patrol</div>">> <<set $patrolStartTime = $timeInMinutes>> <<set $patrolHoursWorked = 0>> <<set $onPatrol = true>> <<set $traitStolenThisShift = false>> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Patrol Officer")>> <<run $jobsWorked.push("Patrol Officer")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<goto "PatrolDowntown">> <</link>> <<else>> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'><<if !_hasDriving>>Need Driving Skill<<else>>Too Exhausted<</if>></div> <</if>> </div> <!-- Return to Break Room --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin-top: 0;">☕ Break Room</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Return to the break room.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ReceptionistWork">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">💼 Reception Desk</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #d63384 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0;"> The reception desk is the first point of contact for everyone entering the police station. You'll be handling phone calls, greeting visitors, managing paperwork, and keeping everything organized. Professional appearance and demeanor are essential. </p> </div> <!-- ===== SKILL TREE: Get hourly pay bonus ===== --> <<set _hourlyPayBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _hourlyPayBonus = setup.skillTree.getEffect("hourlyPayBonus") || 0>> <</if>> <!-- Calculate potential pay with bonuses/penalties --> <<set _basePay = 60>> <<set _payMultiplier = 1.0>> <<set _bonuses = []>> <<set _penalties = []>> <!-- Task 1: Answer Phone Calls --> <<set _phoneBonus = 0>> <<if $mentalTraits.includes("Polite")>> <<set _phoneBonus += 0.03>> <</if>> <<if $mentalTraits.includes("Friendly")>> <<set _phoneBonus += 0.03>> <</if>> <<if $mentalTraits.includes("Patient")>> <<set _phoneBonus += 0.03>> <</if>> <<if $mentalTraits.includes("Calm")>> <<set _phoneBonus += 0.02>> <</if>> <<if $skills.includes("Customer Service")>> <<set _phoneBonus += 0.05>> <</if>> <!-- Voice trait bonuses --> <<if $physicalTraits.includes("Clear Enunciation") || $physicalTraits.includes("Articulate Speech")>> <<set _phoneBonus += 0.04>> <</if>> <<if $physicalTraits.includes("Smooth Voice") || $physicalTraits.includes("Friendly Tone") || $physicalTraits.includes("Warm Tone")>> <<set _phoneBonus += 0.03>> <</if>> <!-- Phone penalties --> <<if $mentalTraits.includes("Rude")>> <<set _phoneBonus -= 0.05>> <</if>> <<if $mentalTraits.includes("Impatient")>> <<set _phoneBonus -= 0.04>> <</if>> <<if $mentalTraits.includes("Short Tempered")>> <<set _phoneBonus -= 0.04>> <</if>> <<if $physicalTraits.includes("Mumbly Voice") || $physicalTraits.includes("Stuttering Speech")>> <<set _phoneBonus -= 0.05>> <</if>> <<if $physicalTraits.includes("Monotone") || $physicalTraits.includes("Flat Voice")>> <<set _phoneBonus -= 0.03>> <</if>> <!-- Task 2: Process Walk-ins --> <<set _walkInBonus = 0>> <<if $mentalTraits.includes("Polite")>> <<set _walkInBonus += 0.03>> <</if>> <<if $mentalTraits.includes("Friendly")>> <<set _walkInBonus += 0.03>> <</if>> <<if $mentalTraits.includes("Patient")>> <<set _walkInBonus += 0.04>> <</if>> <<if $mentalTraits.includes("Empathetic")>> <<set _walkInBonus += 0.04>> <</if>> <<if $mentalTraits.includes("Diplomatic")>> <<set _walkInBonus += 0.03>> <</if>> <<if $skills.includes("Customer Service")>> <<set _walkInBonus += 0.05>> <</if>> <!-- Walk-in penalties --> <<if $mentalTraits.includes("Rude")>> <<set _walkInBonus -= 0.06>> <</if>> <<if $mentalTraits.includes("Bitchy")>> <<set _walkInBonus -= 0.05>> <</if>> <<if $mentalTraits.includes("Cold")>> <<set _walkInBonus -= 0.04>> <</if>> <<if $mentalTraits.includes("Insensitive")>> <<set _walkInBonus -= 0.04>> <</if>> <<if $mentalTraits.includes("Short Tempered")>> <<set _walkInBonus -= 0.04>> <</if>> <!-- Task 3: File Paperwork --> <<set _filingBonus = 0>> <<if $mentalTraits.includes("Organized")>> <<set _filingBonus += 0.06>> <<else>> <<set _filingBonus -= 0.05>> <<run _penalties.push("Missing Organized: -5%")>> <</if>> <<if $physicalTraits.includes("Detail-Oriented")>> <<set _filingBonus += 0.04>> <</if>> <<if $mentalTraits.includes("Efficient")>> <<set _filingBonus += 0.03>> <</if>> <<if $mentalTraits.includes("Focused")>> <<set _filingBonus += 0.03>> <</if>> <<if $physicalTraits.includes("Punctual")>> <<set _filingBonus += 0.02>> <</if>> <!-- Filing penalties --> <<if $mentalTraits.includes("Disorganized")>> <<set _filingBonus -= 0.06>> <</if>> <<if $mentalTraits.includes("Forgetful")>> <<set _filingBonus -= 0.04>> <</if>> <<if $mentalTraits.includes("Lazy")>> <<set _filingBonus -= 0.04>> <</if>> <<if $physicalTraits.includes("Slow")>> <<set _filingBonus -= 0.03>> <</if>> <<if $physicalTraits.includes("Clumsy")>> <<set _filingBonus -= 0.03>> <</if>> <!-- Task 4: Issue Visitor Badges --> <<set _badgeBonus = 0>> <<if $mentalTraits.includes("Organized")>> <<set _badgeBonus += 0.04>> <</if>> <<if $physicalTraits.includes("Detail-Oriented")>> <<set _badgeBonus += 0.05>> <</if>> <<if $physicalTraits.includes("Perceptive")>> <<set _badgeBonus += 0.04>> <</if>> <<if $mentalTraits.includes("Focused")>> <<set _badgeBonus += 0.03>> <</if>> <!-- Badge penalties --> <<if $mentalTraits.includes("Disorganized")>> <<set _badgeBonus -= 0.05>> <</if>> <<if $mentalTraits.includes("Forgetful")>> <<set _badgeBonus -= 0.05>> <</if>> <<if $mentalTraits.includes("Reckless")>> <<set _badgeBonus -= 0.04>> <</if>> <<if $mentalTraits.includes("Careless")>> <<set _badgeBonus -= 0.04>> <</if>> <!-- Missing Customer Service penalty (critical for reception) --> <<if !$skills.includes("Customer Service")>> <<run _penalties.push("Missing Customer Service: -5%")>> <<set _payMultiplier -= 0.05>> <</if>> <!-- Calculate total task performance --> <<set _taskAverage = (_phoneBonus + _walkInBonus + _filingBonus + _badgeBonus) / 4>> <<set _payMultiplier += _taskAverage>> <<set _performancePay = Math.floor(_basePay * _payMultiplier)>> <!-- ===== SKILL TREE: Calculate hourly pay bonus ===== --> <<set _skillTreeBonus = 0>> <<if _hourlyPayBonus > 0>> <<set _skillTreeBonus = Math.floor(_performancePay * (_hourlyPayBonus / 100))>> <</if>> <<set _finalPay = _performancePay + _skillTreeBonus>> <!-- Build bonus/penalty display --> <<if _phoneBonus > 0>> <<run _bonuses.push("Phone Skills: +" + Math.round(_phoneBonus * 100) + "%")>> <<elseif _phoneBonus < 0>> <<run _penalties.push("Phone Skills: " + Math.round(_phoneBonus * 100) + "%")>> <</if>> <<if _walkInBonus > 0>> <<run _bonuses.push("Customer Interaction: +" + Math.round(_walkInBonus * 100) + "%")>> <<elseif _walkInBonus < 0>> <<run _penalties.push("Customer Interaction: " + Math.round(_walkInBonus * 100) + "%")>> <</if>> <<if _filingBonus > 0>> <<run _bonuses.push("Filing Efficiency: +" + Math.round(_filingBonus * 100) + "%")>> <<elseif _filingBonus < 0>> <<run _penalties.push("Filing Efficiency: " + Math.round(_filingBonus * 100) + "%")>> <</if>> <<if _badgeBonus > 0>> <<run _bonuses.push("Badge Processing: +" + Math.round(_badgeBonus * 100) + "%")>> <<elseif _badgeBonus < 0>> <<run _penalties.push("Badge Processing: " + Math.round(_badgeBonus * 100) + "%")>> <</if>> <!-- Work Status --> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #34495e;"> <h3 style="color: #e83e8c; margin-top: 0;">💰 Job Details</h3> <p style="color: #ecf0f1; margin: 10px 0;"> <strong>Base Rate:</strong> $15/hour<br> <strong>Shift Length:</strong> 4 hours<br> <strong>Base Pay:</strong> $<<print _basePay>> </p> <<if _bonuses.length > 0>> <div style="background: #27ae60; padding: 10px; border-radius: 6px; margin: 10px 0;"> <p style="color: white; font-weight: bold; margin: 5px 0;">✓ Performance Bonuses:</p> <<for _bonus range _bonuses>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _bonus</p> <</for>> </div> <</if>> <<if _penalties.length > 0>> <div style="background: #c0392b; padding: 10px; border-radius: 6px; margin: 10px 0;"> <p style="color: white; font-weight: bold; margin: 5px 0;">⚠️ Performance Penalties:</p> <<for _penalty range _penalties>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _penalty</p> <</for>> </div> <</if>> <!-- ===== SKILL TREE: Display bonus ===== --> <<if _skillTreeBonus > 0>> <div style="background: #9C27B0; padding: 10px; border-radius: 6px; margin: 10px 0;"> <p style="color: white; font-weight: bold; margin: 5px 0;">⭐ Skill Tree Bonus:</p> <p style="color: #CE93D8; margin: 3px 0; font-size: 14px;">• Hourly Pay Bonus (+<<print _hourlyPayBonus>>%): +$<<print _skillTreeBonus>></p> </div> <</if>> <p style="color: #2ecc71; font-weight: bold; margin: 10px 0;"> <strong>Final Pay:</strong> $<<print _finalPay>> </p> <<if $workedReceptionistToday>> <p style="color: #e74c3c; font-weight: bold; margin: 10px 0;"> You've already worked your shift today. Come back tomorrow. </p> <<else>> <p style="color: #2ecc71; font-weight: bold; margin: 10px 0;"> You can work a shift today. </p> <</if>> </div> <!-- Task Breakdown --> <<if !$workedReceptionistToday>> <div style="padding: 20px; background: #34495e; border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <h3 style="color: #e83e8c; margin-top: 0;">📋 Today's Tasks</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; margin: 15px 0;"> <div style="background: #2c3e50; padding: 12px; border-radius: 8px; border: 2px solid <<if _phoneBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>;"> <p style="color: #95a5a6; margin: 0; font-size: 14px; font-weight: bold;">📞 Answer Phones</p> <p style="color: <<if _phoneBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>; margin: 5px 0; font-size: 16px; font-weight: bold;"> <<if _phoneBonus >= 0>>+<<print Math.round(_phoneBonus * 100)>>%<<else>><<print Math.round(_phoneBonus * 100)>>%<</if>> </p> </div> <div style="background: #2c3e50; padding: 12px; border-radius: 8px; border: 2px solid <<if _walkInBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>;"> <p style="color: #95a5a6; margin: 0; font-size: 14px; font-weight: bold;">👥 Process Walk-ins</p> <p style="color: <<if _walkInBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>; margin: 5px 0; font-size: 16px; font-weight: bold;"> <<if _walkInBonus >= 0>>+<<print Math.round(_walkInBonus * 100)>>%<<else>><<print Math.round(_walkInBonus * 100)>>%<</if>> </p> </div> <div style="background: #2c3e50; padding: 12px; border-radius: 8px; border: 2px solid <<if _filingBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>;"> <p style="color: #95a5a6; margin: 0; font-size: 14px; font-weight: bold;">📁 File Paperwork</p> <p style="color: <<if _filingBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>; margin: 5px 0; font-size: 16px; font-weight: bold;"> <<if _filingBonus >= 0>>+<<print Math.round(_filingBonus * 100)>>%<<else>><<print Math.round(_filingBonus * 100)>>%<</if>> </p> </div> <div style="background: #2c3e50; padding: 12px; border-radius: 8px; border: 2px solid <<if _badgeBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>;"> <p style="color: #95a5a6; margin: 0; font-size: 14px; font-weight: bold;">🎫 Issue Badges</p> <p style="color: <<if _badgeBonus >= 0>>#2ecc71<<else>>#e74c3c<</if>>; margin: 5px 0; font-size: 16px; font-weight: bold;"> <<if _badgeBonus >= 0>>+<<print Math.round(_badgeBonus * 100)>>%<<else>><<print Math.round(_badgeBonus * 100)>>%<</if>> </p> </div> </div> <<link "<div style='background: #e83e8c; color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; transition: all 0.3s;' onmouseover='this.style.background=\"#d63384\"' onmouseout='this.style.background=\"#e83e8c\"'>💼 Work 4-Hour Shift ($<<print _finalPay>>)</div>">> <<set $receptionistPayEarned = _performancePay>> <<set $receptionistBonuses = _bonuses>> <<set $receptionistPenalties = _penalties>> <<set $receptionistSkillTreeBonus = _skillTreeBonus>> <<set $money += _finalPay>> <<set $workedReceptionistToday = true>> <<set $time += 4>> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Police Station Receptionist")>> <<run $jobsWorked.push("Police Station Receptionist")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<goto "ReceptionistWorkComplete">> <</link>> </div> <</if>> <!-- Return Link --> <<link "<div style='background: #3498db; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; transition: all 0.3s;' onmouseover='this.style.background=\"#2980b9\"' onmouseout='this.style.background=\"#3498db\"'>Return to Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "JanitorWork">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #95a5a6; text-align: center;">🧹 Janitorial Duties</h1> <div style="padding: 20px; background: linear-gradient(135deg, #95a5a6 0%, #7f8c8d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #95a5a6;"> <p style="color: white; font-size: 18px; margin: 0;"> The janitorial closet smells of disinfectant and floor polish. Various cleaning supplies line the shelves, and a mop bucket sits in the corner. This is honest work that keeps the police station running smoothly. </p> </div> <!-- Calculate potential pay with penalties --> <<set _basePay = 96>> <<set _payMultiplier = 1.0>> <<set _penalties = []>> <!-- Check for missing beneficial traits --> <<if !$mentalTraits.includes("Punctual")>> <<set _payMultiplier -= 0.05>> <<run _penalties.push("Missing Punctual: -5%")>> <</if>> <<if !$skills.includes("Cleaning")>> <<set _payMultiplier -= 0.05>> <<run _penalties.push("Missing Cleaning Skill: -5%")>> <</if>> <!-- Check for negative traits --> <<if $mentalTraits.includes("Slow Learner")>> <<set _payMultiplier -= 0.05>> <<run _penalties.push("Slow Learner: -5%")>> <</if>> <<if $mentalTraits.includes("Forgetful")>> <<set _payMultiplier -= 0.05>> <<run _penalties.push("Forgetful: -5%")>> <</if>> <<set _finalPay = Math.floor(_basePay * _payMultiplier)>> <!-- Work Status --> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #34495e;"> <h3 style="color: #95a5a6; margin-top: 0;">💰 Job Details</h3> <p style="color: #ecf0f1; margin: 10px 0;"> <strong>Base Rate:</strong> $12/hour<br> <strong>Shift Length:</strong> 8 hours<br> <strong>Base Pay:</strong> $<<print _basePay>> </p> <<if _penalties.length > 0>> <div style="background: #c0392b; padding: 10px; border-radius: 6px; margin: 10px 0;"> <p style="color: white; font-weight: bold; margin: 5px 0;">⚠️ Pay Penalties:</p> <<for _penalty range _penalties>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _penalty</p> <</for>> </div> <p style="color: #e74c3c; font-weight: bold; margin: 10px 0;"> <strong>Final Pay After Penalties:</strong> $<<print _finalPay>> </p> <<else>> <p style="color: #2ecc71; font-weight: bold; margin: 10px 0;"> ✓ No penalties - Full pay: $<<print _finalPay>> </p> <</if>> <<if $workedJanitorToday>> <p style="color: #e74c3c; font-weight: bold; margin: 10px 0;"> You've already worked your shift today. Come back tomorrow. </p> <<else>> <p style="color: #2ecc71; font-weight: bold; margin: 10px 0;"> You can work a shift today. </p> <</if>> </div> <!-- Work Action --> <<if !$workedJanitorToday>> <div style="padding: 20px; background: #34495e; border-radius: 15px; margin-bottom: 25px; border: 2px solid #95a5a6;"> <h3 style="color: #95a5a6; margin-top: 0;">Available Tasks</h3> <<link "<div style='background: #2ecc71; color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; transition: all 0.3s;' onmouseover='this.style.background=\"#27ae60\"' onmouseout='this.style.background=\"#2ecc71\"'>🧹 Work 8-Hour Shift ($<<print _finalPay>>)</div>">> <<set $janitorPayEarned = _finalPay>> <<set $janitorPenalties = _penalties>> <<set $money += _finalPay>> <<set $workedJanitorToday = true>> <<set $time += 8>> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Police Station Janitor")>> <<run $jobsWorked.push("Police Station Janitor")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <<goto "JanitorWorkComplete">> <</link>> </div> <</if>> <!-- Return Link --> <<link "<div style='background: #3498db; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; transition: all 0.3s;' onmouseover='this.style.background=\"#2980b9\"' onmouseout='this.style.background=\"#3498db\"'>Return to Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolAlleyway">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #666; text-align: center;">🌆 Dark Alleyway - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #434343 0%, #000000 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #666;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the dark alleyways. These narrow passages are hotspots for crime - pickpockets, drug deals, and worse. You stay alert. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #666;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Downtown</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Business District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Red Light District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Docks</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Seabass Park</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Outskirts</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin-top: 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to downtown.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin-top: 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to red light district.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin-top: 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the docks.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> </div> <!-- Shady Shop (Can't Enter) --> <div style="border: 3px solid #ff4444; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff4444; margin-top: 0;">🕶️ Shady Shop</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Suspicious storefront.</p> <<link "<div style='background: #ff4444; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">This place is definitely suspicious, but you're on patrol. You make a mental note to investigate when you're off duty.</p> </div> <</replace>> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolDocks">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">⚓ Docks - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e3a5f 0%, #2c5f8d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the industrial waterfront. Dock workers eye you warily as you make your rounds. This area sees its share of smuggling and other criminal activity. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #3498db;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Downtown</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Business District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Red Light District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Alleyway</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Seabass Park</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Outskirts</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin-top: 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to downtown.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin-top: 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the business district.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin-top: 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to red light district.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin-top: 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Check the alleyway.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolRedLightDistrict">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 Red Light District - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #c31432 0%, #ff1493 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1493;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the neon-lit streets of the red light district. Your presence keeps the peace, though some activities here operate in legal gray areas. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #ff1493;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Downtown</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Business District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Docks</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Alleyway</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Seabass Park</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Outskirts</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin-top: 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to downtown.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin-top: 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the business district.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin-top: 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the docks.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin-top: 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Check the alleyway.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> </div> <!-- Outskirts --> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #888; margin-top: 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Head to the outskirts.</p> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> </div> <!-- Brothel (Can't Enter) --> <div style="border: 3px solid #007FFF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #007FFF; margin-top: 0;">💋 Azure Angelfish Lounge</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Brothel establishment.</p> <<link "<div style='background: #007FFF; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on official patrol. Can't visit establishments like this while in uniform - it would compromise your authority.</p> </div> <</replace>> <</link>> </div> <!-- Strip Club (Can't Enter) --> <div style="border: 3px solid #9D00FF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9D00FF; margin-top: 0;">🪼 Electric Jelly Revue</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Strip club.</p> <<link "<div style='background: #9D00FF; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on duty. Entering adult entertainment venues while in uniform is strictly prohibited.</p> </div> <</replace>> <</link>> </div> <!-- Casino (Can't Enter) --> <div style="border: 3px solid #C0C0C0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #C0C0C0; margin-top: 0;">🎰 The Silver Marlin</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Casino.</p> <<link "<div style='background: #C0C0C0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on patrol duty. Gambling while in uniform would be a serious breach of protocol.</p> </div> <</replace>> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolSeabassPark">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4a7c2c; text-align: center;">🌳 Seabass Park - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d5016 0%, #3d6b1f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4a7c2c;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the peaceful park. Joggers and families enjoy the green space while you keep watch for any trouble. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #4a7c2c;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Downtown</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Business District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Red Light District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Docks</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Alleyway</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Outskirts</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin-top: 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the business district.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> </div> <!-- Outskirts --> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #888; margin-top: 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the outskirts.</p> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolDowntown">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">🏙️ Downtown - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #4a9eff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the bustling downtown area. The streets are packed with people, and you keep a watchful eye on the crowds. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #667eea;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Business District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Red Light District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Docks</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Alleyway</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Seabass Park</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Outskirts</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin-top: 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the business district.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin-top: 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the red light district.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> </div> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin-top: 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Check the alleyway.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> </div> <!-- Apartments (Can't Enter) --> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin-top: 0;">🏢 Sunfish Apartments</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Residential building.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on duty right now. No time for personal visits to the apartments.</p> </div> <</replace>> <</link>> </div> <!-- Town Hall (Can't Enter) --> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin-top: 0;">🏛️ Town Hall</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">City government building.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on patrol. Official police business only - no time for city hall visits.</p> </div> <</replace>> <</link>> </div> <!-- Aquarium (Can't Enter) --> <div style="border: 3px solid #1e90ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1e90ff; margin-top: 0;">🐠 Aquarium</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">City aquarium.</p> <<link "<div style='background: #1e90ff; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on duty. The fish can wait - you need to stay focused on patrol.</p> </div> <</replace>> <</link>> </div> <!-- Police Department --> <div style="border: 3px solid #4169e1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4169e1; margin-top: 0;">🚔 Police Department</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Return to the station.</p> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolBusinessDistrict">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">💼 Business District - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the corporate towers and professional areas. Business people give you respectful nods as you make your rounds. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #17a2b8;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Downtown</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Red Light District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Docks</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Alleyway</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Seabass Park</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Outskirts</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolOutskirts">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin-top: 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to downtown.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin-top: 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the docks.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin-top: 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to red light district.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> </div> <!-- Seabass Park --> <div style="border: 3px solid #4a7c2c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4a7c2c; margin-top: 0;">🌳 Seabass Park</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the park.</p> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> </div> <!-- Businesses that can't be entered --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">💪 Opah Fitness</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Gym.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on patrol. No time for a workout right now.</p> </div> <</replace>> <</link>> </div> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e91e63; margin-top: 0;">💃 Dance Studio</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Dance studio.</p> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on duty. No time for dancing lessons.</p> </div> <</replace>> <</link>> </div> <div style="border: 3px solid #8b4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d2691e; margin-top: 0;">☕ Manta Ray Cafe</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Coffee shop.</p> <<link "<div style='background: #8b4513; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on patrol. Maybe grab coffee on your break later.</p> </div> <</replace>> <</link>> </div> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin-top: 0;">🛍️ Mall</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Shopping center.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<replace "#patrolMessage">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; margin: 15px 0;"> <p style="color: #ffc107; margin: 0; text-align: center;">You're on duty. Shopping will have to wait until you're off the clock.</p> </div> <</replace>> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PatrolOutskirts">> <!-- Crime Detection (25% chance) --> <<if !$crimeDetected && $onPatrol>> <<set _crimeChance = Math.random() * 100>> <<if _crimeChance < 25>> <<set _tierRoll = Math.random() * 100>> <<if _tierRoll < 90>> <<set _tier1Crimes = ["PettyTheft", "Speeding", "ParkingViolation"]>> <<set $currentCrime = _tier1Crimes[Math.floor(Math.random() * _tier1Crimes.length)]>> <<elseif _tierRoll < 96>> <<set _tier2Crimes = ["MinorTraitTheft", "Assault"]>> <<set $currentCrime = _tier2Crimes[Math.floor(Math.random() * _tier2Crimes.length)]>> <<elseif _tierRoll < 99>> <<set _tier3Crimes = ["AssaultWithWeapon", "MajorTraitTheft"]>> <<set $currentCrime = _tier3Crimes[Math.floor(Math.random() * _tier3Crimes.length)]>> <<else>> <<set _tier4Crimes = ["MajorHeist", "GangViolence"]>> <<set $currentCrime = _tier4Crimes[Math.floor(Math.random() * _tier4Crimes.length)]>> <</if>> <<set $crimeDetected = true>> <</if>> <</if>> <<if $crimeDetected && $currentCrime>> <<goto "CrimeScene">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #888; text-align: center;">🌾 Outskirts - On Patrol</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a4a4a 0%, #5a5a5a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #888;"> <p style="color: white; font-size: 18px; margin: 0;"> You're patrolling the edge of the city where urban sprawl meets countryside. It's quieter here, but isolated areas can hide their own dangers. </p> </div> <<if $onPatrol>> <<if $patrolStartTime === undefined || $patrolStartTime === null>> <<set $patrolStartTime = $timeInMinutes>> <</if>> <<set $patrolHoursWorked = (($timeInMinutes >= $patrolStartTime) ? ($timeInMinutes - $patrolStartTime) : (1440 - $patrolStartTime + $timeInMinutes)) / 60>> <<if $patrolHoursWorked >= 8>> <<set $patrolHoursWorked = 8>> <<set _earnings = Math.floor($patrolHoursWorked * 35)>> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<if _pearlActive>><<set _earnings = Math.round(_earnings * 1.5)>><</if>> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<set _creditBonus = 0>> <<if _hasBankAccount>> <<set _creditBonus = Math.floor(_earnings * 0.05)>> <<set $bankAccount.balance += _earnings + _creditBonus>> <<else>> <<set $money += _earnings>> <</if>> <<set $lastPatrolEarnings = _earnings>> <<set $lastPatrolHours = $patrolHoursWorked>> <<set $lastPatrolPearlActive = _pearlActive>> <<set $lastPatrolCreditBonus = _creditBonus>> <<set $lastPatrolHadBank = _hasBankAccount>> <<set $onPatrol = false>> <<set $lastShiftEndTime = setup.getTotalGameMinutes()>> <<set $crimeDetected = false>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; font-weight: bold;">⏰ Patrol Time: <<print $patrolHoursWorked.toFixed(2)>> hours / 8 hours</p> <<if $patrolHoursWorked >= 7.5>> <p style="color: #ffd43b; margin: 5px 0 0 0; font-weight: bold;">⚠️ Shift ending soon!</p> <</if>> </div> <</if>> <<if $onPatrol>> <h2 style="color: #888;">Patrol Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Get in Patrol Car --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin-top: 0;">🚗 Get in Patrol Car</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Drive to any location.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Vehicle</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #3498db; margin-top: 0;">🚗 Drive to Location</h2> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Police Station</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PoliceBreakRoom">> <</link>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Downtown</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDowntown">> <</link>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Business District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolBusinessDistrict">> <</link>> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Red Light District</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Docks</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolDocks">> <</link>> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Alleyway</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolAlleyway">> <</link>> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Seabass Park</div>">> <<run Dialog.close()>> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <!-- Seabass Park --> <div style="border: 3px solid #4a7c2c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4a7c2c; margin-top: 0;">🌳 Seabass Park</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to the park.</p> <<link "<div style='background: #4a7c2c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolSeabassPark">> <</link>> </div> <!-- Red Light District --> <div style="border: 3px solid #ff1493; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff1493; margin-top: 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Walk to red light district.</p> <<link "<div style='background: #ff1493; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk There</div>">> <<set $crimeDetected = false>> <<goto "PatrolRedLightDistrict">> <</link>> </div> </div> <div id="patrolMessage"></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = passage()>> <!-- Initialize Crime Scene --> <!-- Set crime-specific data based on $currentCrime - always runs even on re-entry --> <<if $currentCrime === "PettyTheft">> <<set $crimeType = "Petty Theft">> <<set $crimeTier = 1>> <<set $suspectCount = 1>> <<set $requiresBackup = false>> <<set $crimeDesc = { items: ["candy bars", "electronics", "alcohol", "food"], location: "corner store", action: "shoplifting" }>> <<elseif $currentCrime === "Speeding">> <<set $crimeType = "Speeding">> <<set $crimeTier = 1>> <<set $suspectCount = 1>> <<set $requiresBackup = false>> <<set $crimeDesc = { speed: ["20 mph over", "30 mph over", "dangerously fast"], location: "main street", action: "speeding" }>> <<elseif $currentCrime === "ParkingViolation">> <<set $crimeType = "Parking Violation">> <<set $crimeTier = 1>> <<set $suspectCount = 0>> <<set $requiresBackup = false>> <<set $crimeDesc = { violation: ["fire lane", "handicap spot", "no parking zone", "blocking intersection"], location: "downtown", action: "illegally parked" }>> <<elseif $currentCrime === "MinorTraitTheft">> <<set $crimeType = "Minor Trait Theft">> <<set $crimeTier = 2>> <<set $suspectCount = 1>> <<set $requiresBackup = false>> <<set $crimeDesc = { traits: ["confidence", "charm", "energy", "creativity"], location: "alleyway", action: "draining traits" }>> <<elseif $currentCrime === "Assault">> <<set $crimeType = "Assault">> <<set $crimeTier = 2>> <<set $suspectCount = 1>> <<set $requiresBackup = false>> <<set $crimeDesc = { severity: ["punching", "kicking while down", "beating"], location: "street", action: "assaulting someone" }>> <<elseif $currentCrime === "AssaultWithWeapon">> <<set $crimeType = "Assault with a Weapon">> <<set $crimeTier = 3>> <<set $suspectCount = 1>> <<set $requiresBackup = true>> <<set $crimeDesc = { weapon: ["knife", "bat", "crowbar", "broken bottle"], location: "alley", action: "threatening with a weapon" }>> <<elseif $currentCrime === "MajorTraitTheft">> <<set $crimeType = "Major Trait Theft">> <<set $crimeTier = 3>> <<set $suspectCount = 1>> <<set $requiresBackup = true>> <<set $crimeDesc = { victims: ["multiple victims", "several people", "a group"], location: "abandoned building", action: "systematically draining major traits" }>> <<elseif $currentCrime === "MajorHeist">> <<set $crimeType = "Major Heist">> <<set $crimeTier = 4>> <<set $suspectCount = Math.floor(Math.random() * 3) + 3>> <<set $requiresBackup = true>> <<set $crimeDesc = { target: ["bank", "jewelry store", "armored truck"], weapons: ["automatic weapons", "assault rifles", "heavy firearms"], action: "armed robbery" }>> <<elseif $currentCrime === "GangViolence">> <<set $crimeType = "Gang Violence">> <<set $crimeTier = 4>> <<set $suspectCount = Math.floor(Math.random() * 5) + 5>> <<set $requiresBackup = true>> <<set $crimeDesc = { gangs: ["rival gangs", "two crews", "opposing factions"], location: "street intersection", action: "shootout" }>> <<else>> <<set $crimeType = "Unknown">> <<set $crimeTier = 1>> <<set $suspectCount = 1>> <<set $requiresBackup = false>> <<set $crimeDesc = { location: "unknown area", action: "unknown crime" }>> <</if>> <<if !$crimeInProgress>> <<set $crimeInProgress = true>> <!-- Generate Suspect Profile --> <<set _ages = ["Young teen", "College age", "Middle-aged", "Elderly"]>> <<set _builds = ["Scrawny", "Average", "Athletic", "Large"]>> <<set _demeanors = ["Nervous and sweaty", "Cool and calm", "Aggressive", "Scared", "Confident", "Desperate"]>> <<set $suspect = { age: _ages[Math.floor(Math.random() * _ages.length)], build: _builds[Math.floor(Math.random() * _builds.length)], demeanor: _demeanors[Math.floor(Math.random() * _demeanors.length)], threatLevel: $crimeTier, currentState: "active", compliance: 50, apprehended: false, scanned: false, traitTheftAttempted: false, hasWeapon: $crimeTier >= 3 }>> <!-- Generate traits for suspect --> <<set $suspect.traits = setup.generateCriminalTraits($crimeTier, $suspect.age, $suspect.build)>> <<set $suspect.stats = setup.calculateSuspectStats($suspect)>> <!-- Context Factors - Time and Location Based --> <<set _isNight = ($timeInMinutes >= 1320 || $timeInMinutes < 360)>> <<set _witnessCount = 0>> <!-- Determine witnesses based on time and location --> <<if $lastLocation === "PatrolDowntown" || $lastLocation === "PatrolBusinessDistrict">> <<set _witnessCount = _isNight ? 1 : 2>> <<elseif $lastLocation === "PatrolRedLightDistrict">> <<set _witnessCount = 2>> <<elseif $lastLocation === "PatrolDocks" || $lastLocation === "PatrolAlleyway">> <<set _witnessCount = _isNight ? 0 : 1>> <<elseif $lastLocation === "PatrolSeabassPark">> <<set _witnessCount = _isNight ? 0 : 2>> <<elseif $lastLocation === "PatrolOutskirts">> <<set _witnessCount = _isNight ? 0 : 1>> <<else>> <<set _witnessCount = 1>> <</if>> <<set _witnessLevels = ["Few", "Moderate", "Many"]>> <<set $context = { nearbyOfficers: Math.floor(Math.random() * 4), backupTime: Math.floor(Math.random() * 5) + 1, activeCalls: ["None", "Minor", "Major"][Math.floor(Math.random() * 3)], witnesses: _witnessLevels[_witnessCount], backupCalled: false, backupArrived: false }>> <!-- Performance Tracking --> <<set $performance = { actions: [], forceUsed: [], appropriateness: 100, procedureScore: 100, outcomeScore: 0, warnings: [], traitTheftDetected: false, wentInAlone: false }>> <<set $crimeStage = 0>> <!-- Initialize weapon variable if crime has weapons --> <<if $crimeDesc && $crimeDesc.weapon && $crimeDesc.weapon.length > 0>> <<set _weapon = $crimeDesc.weapon[Math.floor(Math.random() * $crimeDesc.weapon.length)]>> <<else>> <<set _weapon = "weapon">> <</if>> <</if>> <div class="crime-scene"> <h1 class="crime-header">🚨 Crime in Progress: <<print $crimeType>></h1> <!-- Situation Description --> <div class="situation-box"> <<if $crimeStage === 0>> <!-- Initial Crime Description --> <<if $currentCrime === "PettyTheft">> <<set _item = $crimeDesc.items[Math.floor(Math.random() * $crimeDesc.items.length)]>> <p class="situation-text"> You spot a <<print $suspect.age.toLowerCase()>> person with a <<print $suspect.build.toLowerCase()>> build shoplifting from a <<print $crimeDesc.location>>. They're stuffing <<print _item>> into their jacket. They appear <<print $suspect.demeanor.toLowerCase()>>. </p> <<elseif $currentCrime === "Speeding">> <<set _speed = $crimeDesc.speed[Math.floor(Math.random() * $crimeDesc.speed.length)]>> <p class="situation-text"> A car just blew past you going <<print _speed>> the speed limit on <<print $crimeDesc.location>>. The driver appears <<print $suspect.demeanor.toLowerCase()>> and is weaving through traffic recklessly. </p> <<elseif $currentCrime === "ParkingViolation">> <<set _violation = $crimeDesc.violation[Math.floor(Math.random() * $crimeDesc.violation.length)]>> <p class="situation-text"> A vehicle is illegally parked in a <<print _violation>> in <<print $crimeDesc.location>>. The driver is nowhere to be seen, blocking emergency access. </p> <<elseif $currentCrime === "MinorTraitTheft">> <<set _trait = $crimeDesc.traits[Math.floor(Math.random() * $crimeDesc.traits.length)]>> <p class="situation-text"> You witness a <<print $suspect.age.toLowerCase()>> person with a <<print $suspect.build.toLowerCase()>> build performing an illegal trait extraction on an unwilling victim in an <<print $crimeDesc.location>>. The victim looks dazed and confused. The perpetrator appears <<print $suspect.demeanor.toLowerCase()>>. </p> <<elseif $currentCrime === "Assault">> <<set _severity = $crimeDesc.severity[Math.floor(Math.random() * $crimeDesc.severity.length)]>> <p class="situation-text"> A <<print $suspect.build.toLowerCase()>> attacker is <<print _severity>> someone on the <<print $crimeDesc.location>>. The victim is already on the ground bleeding. The attacker appears <<print $suspect.demeanor.toLowerCase()>>. </p> <<elseif $currentCrime === "AssaultWithWeapon">> <<if !_weapon && $crimeDesc.weapon && $crimeDesc.weapon.length > 0>> <<set _weapon = $crimeDesc.weapon[Math.floor(Math.random() * $crimeDesc.weapon.length)]>> <</if>> <p class="situation-text"> Someone is threatening another person with a <<print _weapon>> in an <<print $crimeDesc.location>>. The situation is tense and could turn deadly at any moment. The attacker is a <<print $suspect.age.toLowerCase()>> person with a <<print $suspect.build.toLowerCase()>> build, appearing <<print $suspect.demeanor.toLowerCase()>>. The victim is backed against a wall, terrified for their life. </p> <<elseif $currentCrime === "MajorTraitTheft">> <<set _victims = $crimeDesc.victims[Math.floor(Math.random() * $crimeDesc.victims.length)]>> <p class="situation-text"> A powerful trait thief has cornered <<print _victims>> in an <<print $crimeDesc.location>>. They're systematically extracting major traits from each person, leaving them as hollow shells. This is organized and professional. The thief appears <<print $suspect.demeanor.toLowerCase()>> and <<print $suspect.build.toLowerCase()>>. Their victims are barely conscious. </p> <<elseif $currentCrime === "MajorHeist">> <<set _target = $crimeDesc.target[Math.floor(Math.random() * $crimeDesc.target.length)]>> <<set _weapons = $crimeDesc.weapons[Math.floor(Math.random() * $crimeDesc.weapons.length)]>> <p class="situation-text"> <<print $suspectCount>> armed criminals are robbing a <<print _target>>! Multiple masked perpetrators with <<print _weapons>> are inside, taking hostages. This is a full-scale heist operation with professional criminals. You can see at least <<print $suspectCount>> suspects moving around inside. </p> <p style="color: #ffd43b; font-weight: bold; margin-top: 10px;"> ⚠️ THIS IS A MAJOR INCIDENT - BACKUP STRONGLY RECOMMENDED </p> <<elseif $currentCrime === "GangViolence">> <<set _gangs = $crimeDesc.gangs[Math.floor(Math.random() * $crimeDesc.gangs.length)]>> <p class="situation-text"> <<print _gangs>> are engaged in a full-scale shootout at a <<print $crimeDesc.location>>! You can count at least <<print $suspectCount>> armed gang members firing weapons. Bullets are flying, bystanders are caught in the crossfire, and the situation is spiraling out of control. This is urban warfare. </p> <p style="color: #ff0000; font-weight: bold; margin-top: 10px; font-size: 18px;"> 🚨 EXTREMELY DANGEROUS - MULTIPLE ARMED SUSPECTS - DO NOT ENGAGE ALONE </p> <</if>> <<elseif $suspect.currentState === "complying">> <<if $suspectCount > 1>> <p class="situation-text">Some suspects are cooperating, but the situation is still volatile.</p> <<else>> <p class="situation-text">The suspect is cooperating with your commands.</p> <</if>> <<elseif $suspect.currentState === "fleeing">> <<if $suspectCount > 1>> <p class="situation-text">The suspects are scattering and trying to escape!</p> <<else>> <p class="situation-text">The suspect is trying to run away!</p> <</if>> <<elseif $suspect.currentState === "resisting">> <<if $suspectCount > 1>> <p class="situation-text">The suspects are resisting aggressively! You're outnumbered!</p> <<else>> <p class="situation-text">The suspect is resisting and becoming aggressive!</p> <</if>> <<elseif $suspect.currentState === "attacking">> <<if $suspectCount > 1>> <p class="situation-text" style="color: #ff0000;">Multiple suspects are attacking you! You're in serious danger!</p> <<else>> <p class="situation-text">The suspect has become violent and is attacking you!</p> <</if>> <<elseif $suspect.currentState === "subdued">> <<if $suspectCount > 1>> <p class="situation-text">The suspects have been subdued and are no longer a threat.</p> <<else>> <p class="situation-text">The suspect has been subdued and is no longer a threat.</p> <</if>> <<elseif $suspect.currentState === "escaped">> <<if $suspectCount > 1>> <p class="situation-text">The suspects have escaped!</p> <<else>> <p class="situation-text">The suspect has escaped!</p> <</if>> <<elseif $suspect.currentState === "officer_down">> <p class="situation-text" style="color: #ff0000; font-size: 20px; font-weight: bold;"> 🚨 OFFICER DOWN 🚨<br> You've been overpowered! Backup is rushing to your location! </p> <</if>> </div> <!-- Visible Traits --> <<if $suspect.traits.visible.length > 0>> <div class="traits-visible"> <h3 class="traits-header">👁️ Visible Characteristics</h3> <div class="trait-list"> <<for _trait range $suspect.traits.visible>> <span class="trait-tag trait-visible"><<print _trait>></span> <</for>> </div> </div> <</if>> <!-- Context Information --> <div class="context-box"> <h3 class="context-header">📊 Situation Context</h3> <div class="context-grid"> <<if $suspectCount > 1>> <div><strong class="stat-label" style="color: #ff0000;">Suspects:</strong> <<print $suspectCount>></div> <</if>> <div><strong class="stat-label stat-officers">Officers Nearby:</strong> <<print $context.nearbyOfficers>></div> <div><strong class="stat-label stat-backup">Backup ETA:</strong> <<if $context.backupCalled>><<print $context.backupTime>> min<<else>>Not Called<</if>></div> <div><strong class="stat-label stat-calls">Active Priority Calls:</strong> <<print $context.activeCalls>></div> <div><strong class="stat-label stat-witnesses">Witnesses:</strong> <<print $context.witnesses>></div> </div> </div> <<if $suspect.currentState === "subdued" && !$suspect.apprehended>> <!-- Post-Apprehension Options --> <div class="apprehension-box"> <h2 class="section-header">🔒 Suspect<<if $suspectCount > 1>>s<</if>> Apprehended</h2> <p class="info-text">The suspect<<if $suspectCount > 1>>s are<<else>> is<</if>> in custody. What do you want to do?</p> <div class="action-grid"> <<if !$suspect.scanned && $suspectCount === 1>> <!-- Scan for Traits (only for single suspects) --> <div class="action-card action-scan"> <h3 class="action-title">🔍 Scan Suspect</h3> <p class="action-desc">Use your trait scanner to identify all traits.</p> <<link "<div class='action-button button-scan'>Scan Traits</div>">> <<set $suspect.scanned = true>> <<goto "CrimeScene">> <</link>> </div> <</if>> <!-- Process Arrest --> <div class="action-card action-process"> <h3 class="action-title">📋 Process Arrest</h3> <p class="action-desc">Complete the arrest by the book.</p> <<link "<div class='action-button button-process'>Process Arrest</div>">> <<set $suspect.apprehended = true>> <<set $performance.outcomeScore = 100>> <<run $performance.actions.push("Processed arrest properly")>> <<goto "CrimeResolution">> <</link>> </div> </div> </div> <<if $suspect.scanned && $suspectCount === 1>> <!-- Display All Traits After Scan --> <div class="traits-scanned"> <h3 class="traits-header">🔍 Trait Scan Results</h3> <<if $suspect.traits.physical.length > 0>> <div class="trait-category"> <h4>Physical Traits:</h4> <div class="trait-list"> <<for _trait range $suspect.traits.physical>> <<if !setup.unstealableTraits.includes(_trait)>> <<set _value = setup.getTraitValue('physical', _trait)>> <span class="trait-tag trait-physical" title="Value: <<print _value>>"> <<print _trait>> <span class="trait-value">(<<print _value>>)</span> </span> <</if>> <</for>> </div> </div> <</if>> <<if $suspect.traits.mental.length > 0>> <div class="trait-category"> <h4>Mental Traits:</h4> <div class="trait-list"> <<for _trait range $suspect.traits.mental>> <<if !setup.unstealableTraits.includes(_trait)>> <<set _value = setup.getTraitValue('mental', _trait)>> <span class="trait-tag trait-mental" title="Value: <<print _value>>"> <<print _trait>> <span class="trait-value">(<<print _value>>)</span> </span> <</if>> <</for>> </div> </div> <</if>> <<if $suspect.traits.skills.length > 0>> <div class="trait-category"> <h4>Skills:</h4> <div class="trait-list"> <<for _trait range $suspect.traits.skills>> <<if !setup.unstealableTraits.includes(_trait)>> <<set _value = setup.getTraitValue('skill', _trait)>> <span class="trait-tag trait-skill" title="Value: <<print _value>>"> <<print _trait>> <span class="trait-value">(<<print _value>>)</span> </span> <</if>> <</for>> </div> </div> <</if>> <<if !$suspect.traitTheftAttempted>> <<if !$traitStolenThisShift>> <div class="theft-warning"> <h4 class="warning-title">⚠️ Trait Theft Warning</h4> <p class="warning-text"> You can attempt to steal ONE trait from this suspect. However, this is illegal and you risk: </p> <ul class="warning-list"> <li>Being caught by witnesses (<<print $context.witnesses>> witnesses present)</li> <li>Being reported by nearby officers (<<print $context.nearbyOfficers>> nearby)</li> <li>Immediate termination if caught</li> <li>Criminal charges if you have multiple stolen traits</li> </ul> <<link "<div class='action-button button-theft' style='background: #8b0000; border-color: #ff0000;'>Attempt Trait Theft</div>">> <<goto "OfficerCrimeAttempt">> <</link>> </div> <<else>> <div style="background: #000; padding: 15px; border-radius: 8px; margin-top: 20px; border: 3px solid #666;"> <h4 style="color: #888; margin: 0 0 10px 0;">🚫 Trait Theft Unavailable</h4> <p style="color: #aaa; margin: 0; text-align: center;"> You've already stolen a trait this shift. Attempting another theft would be far too risky. </p> </div> <</if>> <</if>> </div> <</if>> <<elseif $suspect.currentState === "officer_down">> <!-- Officer Down - Auto-resolve --> <div class="failure-box"> <h2 class="failure-header" style="color: #ff0000;">🚨 CRITICAL FAILURE 🚨</h2> <p class="failure-text"> You were completely overpowered. <<if $suspectCount > 1>>The <<print $suspectCount>> suspects<<else>>The suspect<</if>> escaped while you were incapacitated. Backup arrived moments later and rushed you to the hospital. </p> <p class="warning-text" style="color: #ff6b6b; font-size: 16px; margin-top: 15px;"> This incident will be heavily reviewed. Going into a Tier <<print $crimeTier>> situation alone was extremely reckless. </p> </div> <<set $performance.outcomeScore = 0>> <<set $performance.appropriateness = 0>> <<set $performance.procedureScore = 0>> <<run $performance.warnings.push("Officer incapacitated - extreme negligence")>> <<run $performance.warnings.push("Engaged Tier " + $crimeTier + " threat without backup")>> <<run $performance.warnings.push("All suspects escaped")>> <<link "<div class='action-button button-return'>Continue to Hospital</div>">> <<set $crimeDetected = false>> <<set $currentCrime = null>> <<set $crimeInProgress = false>> <<unset $suspect>> <<unset $context>> <<unset $performance>> <<unset $crimeStage>> <<unset $crimeDesc>> <<goto "CrimeResolution">> <</link>> <<elseif $suspect.currentState !== "subdued" && $suspect.currentState !== "escaped">> <!-- ========== CRIME-SPECIFIC ACTIONS ========== --> <!-- SPEEDING - Chase or Citation --> <<if $currentCrime === "Speeding">> <h2 class="section-header">How do you pursue?</h2> <div class="action-grid"> <div class="action-card action-verbal"> <h3 class="action-title">🚨 Initiate Pursuit</h3> <p class="action-desc">Turn on lights and sirens, chase the vehicle.</p> <p class="force-level">May pull over or flee</p> <<link "<div class='action-button button-verbal'>Start Pursuit</div>">> <<set $chosenAction = "Initiate Pursuit">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-calm"> <h3 class="action-title">📋 Issue Citation by Plate</h3> <p class="action-desc">Let them go, mail ticket based on license plate.</p> <p class="force-level">No pursuit risk</p> <<link "<div class='action-button button-calm'>Issue Citation</div>">> <<set $suspect.currentState = "subdued">> <<set $suspect.apprehended = true>> <<set $performance.outcomeScore = 80>> <<run $performance.actions.push("Issued speeding citation without pursuit")>> <<goto "CrimeResolution">> <</link>> </div> <div class="action-card action-aggressive"> <h3 class="action-title">🚗 Aggressive Pursuit</h3> <p class="action-desc">High-speed chase with PIT maneuver if needed.</p> <p class="force-level" style="color: #ff6b6b;">Extreme force - property damage risk</p> <<link "<div class='action-button button-aggressive'>Aggressive Chase</div>">> <<set $chosenAction = "Aggressive Pursuit">> <<set $forceLevel = 4>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- PARKING VIOLATION - Ticket or Tow --> <<elseif $currentCrime === "ParkingViolation">> <h2 class="section-header">How do you handle this?</h2> <div class="action-grid"> <div class="action-card action-verbal"> <h3 class="action-title">🎫 Issue Parking Ticket</h3> <p class="action-desc">Write a ticket and place it on the windshield.</p> <p class="force-level">Standard procedure</p> <<link "<div class='action-button button-verbal'>Issue Ticket</div>">> <<set $chosenAction = "Issue Ticket">> <<set $forceLevel = 0>> <<set $suspect.currentState = "subdued">> <<set $suspect.apprehended = true>> <<set $performance.outcomeScore = 100>> <<run $performance.actions.push("Issued parking ticket properly")>> <<goto "CrimeResolution">> <</link>> </div> <div class="action-card action-backup"> <h3 class="action-title">🚗 Call Tow Truck</h3> <p class="action-desc">Have the vehicle towed away.</p> <p class="force-level">Enforcement action</p> <<link "<div class='action-button button-backup'>Call Tow</div>">> <<set $chosenAction = "Call Tow Truck">> <<set $forceLevel = 0>> <<set $suspect.currentState = "subdued">> <<set $suspect.apprehended = true>> <<set $performance.outcomeScore = 100>> <<run $performance.actions.push("Had vehicle towed")>> <<goto "CrimeResolution">> <</link>> </div> <div class="action-card action-physical"> <h3 class="action-title">🔨 Break Window & Inspect</h3> <p class="action-desc">Break window to check for emergency/medical situation.</p> <p class="force-level">Property damage - extreme measure</p> <<link "<div class='action-button button-physical'>Break Window</div>">> <<set $chosenAction = "Break Window">> <<set $forceLevel = 3>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- PETTY THEFT - Confront or Detain --> <<elseif $currentCrime === "PettyTheft">> <h2 class="section-header">How do you respond?</h2> <div class="action-grid"> <div class="action-card action-verbal"> <h3 class="action-title">📢 Verbal Command</h3> <p class="action-desc">Shout "Stop! Police!" and order them to freeze.</p> <p class="force-level">May comply or flee</p> <<link "<div class='action-button button-verbal'>Use Command</div>">> <<set $chosenAction = "Verbal Warning">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-calm"> <h3 class="action-title">🤝 Calm Approach</h3> <p class="action-desc">Walk up calmly and speak with the suspect.</p> <p class="force-level">De-escalation</p> <<link "<div class='action-button button-calm'>Approach Calmly</div>">> <<set $chosenAction = "Calm Approach">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-physical"> <h3 class="action-title">✋ Detain Immediately</h3> <p class="action-desc">Physically restrain the shoplifter.</p> <p class="force-level">Direct action</p> <<link "<div class='action-button button-physical'>Detain Now</div>">> <<set $chosenAction = "Physical Intervention">> <<set $forceLevel = 2>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-aggressive"> <h3 class="action-title">💢 Tackle Suspect</h3> <p class="action-desc">Aggressively tackle them to the ground.</p> <p class="force-level">Heavy force - may cause injury</p> <<link "<div class='action-button button-aggressive'>Tackle</div>">> <<set $chosenAction = "Aggressive Takedown">> <<set $forceLevel = 4>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- ASSAULT - Intervene or Separate --> <<elseif $currentCrime === "Assault">> <h2 class="section-header">How do you intervene?</h2> <div class="action-grid"> <div class="action-card action-verbal"> <h3 class="action-title">📢 Shout Commands</h3> <p class="action-desc">Yell "Police! Stop!" to interrupt the attack.</p> <p class="force-level">May stop or escalate</p> <<link "<div class='action-button button-verbal'>Shout Commands</div>">> <<set $chosenAction = "Verbal Warning">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-physical"> <h3 class="action-title">✋ Physically Separate</h3> <p class="action-desc">Pull the attacker off the victim.</p> <p class="force-level">Appropriate force</p> <<link "<div class='action-button button-physical'>Separate Them</div>">> <<set $chosenAction = "Physical Intervention">> <<set $forceLevel = 2>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-aggressive"> <h3 class="action-title">💢 Tackle Attacker</h3> <p class="action-desc">Aggressively take down the assailant.</p> <p class="force-level">Heavy force</p> <<link "<div class='action-button button-aggressive'>Tackle</div>">> <<set $chosenAction = "Aggressive Takedown">> <<set $forceLevel = 4>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-weapon"> <h3 class="action-title">⚡ Use Taser</h3> <p class="action-desc">Deploy taser to immediately stop the assault.</p> <p class="force-level" style="color: #ff6b6b;">Extreme - less lethal weapon</p> <<link "<div class='action-button button-weapon'>Deploy Taser</div>">> <<set $chosenAction = "Use Taser">> <<set $forceLevel = 3>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-backup"> <h3 class="action-title">📻 Call for Backup First</h3> <p class="action-desc">Request assistance before engaging.</p> <p class="force-level">Cautious approach</p> <<link "<div class='action-button button-backup'>Call Backup</div>">> <<set $chosenAction = "Call for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- MINOR TRAIT THEFT - Interrupt Extraction --> <<elseif $currentCrime === "MinorTraitTheft">> <h2 class="section-header">How do you stop the trait theft?</h2> <div class="action-grid"> <div class="action-card action-verbal"> <h3 class="action-title">📢 Interrupt Verbally</h3> <p class="action-desc">Shout to break their concentration.</p> <p class="force-level">May stop or flee</p> <<link "<div class='action-button button-verbal'>Shout</div>">> <<set $chosenAction = "Verbal Warning">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-physical"> <h3 class="action-title">✋ Physical Disruption</h3> <p class="action-desc">Physically interrupt the trait extraction.</p> <p class="force-level">Stop the process</p> <<link "<div class='action-button button-physical'>Disrupt Extraction</div>">> <<set $chosenAction = "Physical Intervention">> <<set $forceLevel = 2>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-calm"> <h3 class="action-title">🤝 Negotiate</h3> <p class="action-desc">Try to talk them down from the theft.</p> <p class="force-level">De-escalation</p> <<link "<div class='action-button button-calm'>Negotiate</div>">> <<set $chosenAction = "Calm Approach">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-aggressive"> <h3 class="action-title">💢 Aggressive Tackle</h3> <p class="action-desc">Immediately tackle them to stop the extraction.</p> <p class="force-level">Heavy force - may injure victim too</p> <<link "<div class='action-button button-aggressive'>Tackle Hard</div>">> <<set $chosenAction = "Aggressive Takedown">> <<set $forceLevel = 4>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- ASSAULT WITH WEAPON - Dangerous Situation --> <<elseif $currentCrime === "AssaultWithWeapon">> <h2 class="section-header">How do you handle the armed suspect?</h2> <<if $context.backupCalled && !$context.backupArrived>> <div style="background: rgba(52, 152, 219, 0.3); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; text-align: center; font-weight: bold;"> 📻 Backup en route - ETA <<print $context.backupTime>> minutes </p> </div> <</if>> <div class="action-grid"> <div class="action-card action-weapon"> <h3 class="action-title">🔫 Draw Weapon</h3> <p class="action-desc">Draw your firearm and order them to drop the weapon.</p> <p class="force-level">Appropriate for armed threat</p> <<link "<div class='action-button button-weapon'>Draw Weapon</div>">> <<set $chosenAction = "Draw Weapon">> <<set $forceLevel = 5>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-backup"> <h3 class="action-title">📻 Call for Backup</h3> <p class="action-desc">Request immediate assistance.</p> <p class="force-level" style="background: #000; border: 2px solid #ffd43b; color: #ffd43b; padding: 5px 10px; border-radius: 4px; font-weight: bold; display: inline-block;">⚠️ STRONGLY ADVISED</p> <<link "<div class='action-button button-backup'>Call Backup</div>">> <<set $chosenAction = "Call for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <<if $context.backupCalled && !$context.backupArrived>> <div class="action-card" style="border-color: #3498db; border-width: 3px;"> <h3 class="action-title">⏳ Wait for Backup</h3> <p class="action-desc">Hold position until backup arrives.</p> <p class="force-level"><<print $context.backupTime>> min remaining</p> <<link "<div class='action-button' style='background: #3498db;'>Wait</div>">> <<set $chosenAction = "Wait for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <</if>> <div class="action-card action-verbal"> <h3 class="action-title">📢 Verbal De-escalation</h3> <p class="action-desc">Try to talk them down without drawing weapon.</p> <p class="force-level">Risky but non-violent</p> <<link "<div class='action-button button-verbal'>Talk Down</div>">> <<set $chosenAction = "Calm Approach">> <<set $forceLevel = 1>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card" style="border-color: #ff0000; border-width: 3px;"> <h3 class="action-title">🔫 Shoot to Neutralize</h3> <p class="action-desc">Fire immediately if they don't drop weapon.</p> <p class="force-level" style="color: #ff0000;">LETHAL FORCE - extreme measure</p> <<link "<div class='action-button' style='background: #8b0000;'>Shoot if Threatened</div>">> <<set $chosenAction = "Shoot to Neutralize">> <<set $forceLevel = 6>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- MAJOR TRAIT THEFT - Serious Crime --> <<elseif $currentCrime === "MajorTraitTheft">> <h2 class="section-header">How do you stop the major trait theft?</h2> <<if $context.backupCalled && !$context.backupArrived>> <div style="background: rgba(52, 152, 219, 0.3); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; text-align: center; font-weight: bold;"> 📻 Backup en route - ETA <<print $context.backupTime>> minutes </p> </div> <</if>> <div class="action-grid"> <div class="action-card action-weapon"> <h3 class="action-title">🔫 Draw Weapon</h3> <p class="action-desc">This is a dangerous criminal - use lethal force option.</p> <p class="force-level">Appropriate force</p> <<link "<div class='action-button button-weapon'>Draw Weapon</div>">> <<set $chosenAction = "Draw Weapon">> <<set $forceLevel = 5>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card action-backup"> <h3 class="action-title">📻 Call for Backup</h3> <p class="action-desc">This requires multiple officers.</p> <p class="force-level" style="background: #000; border: 2px solid #ffd43b; color: #ffd43b; padding: 5px 10px; border-radius: 4px; font-weight: bold; display: inline-block;">⚠️ STRONGLY ADVISED</p> <<link "<div class='action-button button-backup'>Call Backup</div>">> <<set $chosenAction = "Call for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <<if $context.backupCalled && !$context.backupArrived>> <div class="action-card" style="border-color: #3498db; border-width: 3px;"> <h3 class="action-title">⏳ Wait for Backup</h3> <p class="action-desc">Hold position, monitor the situation.</p> <p class="force-level"><<print $context.backupTime>> min remaining</p> <<link "<div class='action-button' style='background: #3498db;'>Wait</div>">> <<set $chosenAction = "Wait for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <</if>> <div class="action-card action-physical"> <h3 class="action-title">✋ Interrupt Physically</h3> <p class="action-desc">Rush in and disrupt the trait extraction.</p> <p class="force-level" style="color: #ff6b6b;">Risky without backup!</p> <<link "<div class='action-button button-physical'>Interrupt</div>">> <<set $chosenAction = "Physical Intervention">> <<set $forceLevel = 2>> <<goto "CrimeResponse">> <</link>> </div> <div class="action-card" style="border-color: #ff0000; border-width: 3px;"> <h3 class="action-title">🔫 Lethal Force Authorized</h3> <p class="action-desc">Shoot on sight to save victims - extreme measure.</p> <p class="force-level" style="color: #ff0000;">LETHAL - victims at risk</p> <<link "<div class='action-button' style='background: #8b0000;'>Engage Lethal</div>">> <<set $chosenAction = "Lethal Force">> <<set $forceLevel = 6>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- MAJOR HEIST - Multiple Armed Suspects --> <<elseif $currentCrime === "MajorHeist">> <h2 class="section-header">How do you respond to the heist?</h2> <<if $context.backupCalled && !$context.backupArrived>> <div style="background: rgba(52, 152, 219, 0.3); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; text-align: center; font-weight: bold;"> 📻 Backup en route - ETA <<print $context.backupTime>> minutes </p> </div> <</if>> <div class="action-grid"> <div class="action-card action-backup" style="border-color: #ffd43b; border-width: 3px;"> <h3 class="action-title">📻 Call for Backup</h3> <p class="action-desc">This is a MAJOR INCIDENT - you need backup NOW.</p> <p class="force-level" style="color: #ff0000; font-weight: bold;">🚨 CRITICAL - DO NOT ENGAGE ALONE</p> <<link "<div class='action-button button-backup'>Call Backup</div>">> <<set $chosenAction = "Call for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <<if $context.backupCalled && !$context.backupArrived>> <div class="action-card" style="border-color: #3498db; border-width: 3px;"> <h3 class="action-title">⏳ Wait for Backup</h3> <p class="action-desc">Monitor situation, establish perimeter.</p> <p class="force-level"><<print $context.backupTime>> min remaining</p> <<link "<div class='action-button' style='background: #3498db;'>Wait</div>">> <<set $chosenAction = "Wait for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <</if>> <div class="action-card action-weapon" style="opacity: 0.7;"> <h3 class="action-title">🔫 Engage Alone</h3> <p class="action-desc">Draw weapon and confront multiple armed suspects.</p> <p class="force-level" style="color: #ff0000;">⚠️ EXTREMELY DANGEROUS</p> <<link "<div class='action-button button-weapon'>Engage</div>">> <<set $chosenAction = "Draw Weapon">> <<set $forceLevel = 5>> <<goto "CrimeResponse">> <</link>> </div> </div> <!-- GANG VIOLENCE - Active Shootout --> <<elseif $currentCrime === "GangViolence">> <h2 class="section-header">How do you respond to the shootout?</h2> <<if $context.backupCalled && !$context.backupArrived>> <div style="background: rgba(52, 152, 219, 0.3); padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; text-align: center; font-weight: bold;"> 📻 Backup en route - ETA <<print $context.backupTime>> minutes </p> </div> <</if>> <div class="action-grid"> <div class="action-card action-backup" style="border-color: #ff0000; border-width: 4px;"> <h3 class="action-title">📻 Call for Backup</h3> <p class="action-desc">Request ALL available units - this is urban warfare.</p> <p class="force-level" style="color: #ff0000; font-weight: bold;">🚨 MANDATORY - OFFICER SAFETY</p> <<link "<div class='action-button button-backup'>Call All Units</div>">> <<set $chosenAction = "Call for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <<if $context.backupCalled && !$context.backupArrived>> <div class="action-card" style="border-color: #3498db; border-width: 3px;"> <h3 class="action-title">⏳ Take Cover & Wait</h3> <p class="action-desc">Find cover, protect civilians, wait for tactical response.</p> <p class="force-level"><<print $context.backupTime>> min remaining</p> <<link "<div class='action-button' style='background: #3498db;'>Take Cover</div>">> <<set $chosenAction = "Wait for Backup">> <<set $forceLevel = 0>> <<goto "CrimeResponse">> <</link>> </div> <</if>> <div class="action-card action-weapon" style="opacity: 0.5;"> <h3 class="action-title">🔫 Engage Armed Suspects</h3> <p class="action-desc">Draw weapon and engage <<print $suspectCount>> armed gang members alone.</p> <p class="force-level" style="color: #ff0000;">⚠️ EXTREMELY DANGEROUS - HIGH RISK OF DEATH</p> <<link "<div class='action-button button-weapon' style='background: #4d0000;'>Engage Alone</div>">> <<set $chosenAction = "Draw Weapon">> <<set $forceLevel = 5>> <<goto "CrimeResponse">> <</link>> </div> </div> <</if>> <<else>> <!-- Crime is over - Go to resolution --> <<goto "CrimeResolution">> <</if>> </div> <!-- Closes crime-scene --> <</nobr>>
<<nobr>> <<set $crimeStage += 1>> <!-- Record Action --> <<run $performance.actions.push($chosenAction)>> <<run $performance.forceUsed.push($forceLevel)>> <!-- Get player trait modifier --> <<set _modifier = setup.getPlayerActionModifier($chosenAction, $suspect)>> <!-- Determine Suspect Response based on action and their characteristics --> <<set _reaction = "">> <<set _escalation = 0>> <<if $chosenAction === "Verbal Warning">> <!-- Only works for low-tier crimes --> <<if $crimeTier >= 3>> <<set $suspect.currentState = "attacking">> <<set _reaction = "Your shouted warning is met with immediate violence! ">> <<if $suspect.hasWeapon>> <<set _weapon = $crimeDesc.weapon[Math.floor(Math.random() * $crimeDesc.weapon.length)]>> <<set _reaction += "The suspect turns on you with their " + _weapon + "! This situation just became life-threatening!">> <<else>> <<set _reaction += "The suspect charges at you aggressively!">> <</if>> <<set $performance.appropriateness -= 40>> <<run $performance.warnings.push("Verbal warning ineffective for Tier 3+ threat - endangered officer safety")>> <<else>> <<set _baseChance = 50 + _modifier>> <<if $suspect.demeanor === "Nervous and sweaty" || $suspect.demeanor === "Scared">> <<set _baseChance += 20>> <<elseif $suspect.demeanor === "Cool and calm">> <<set _baseChance -= 10>> <<elseif $suspect.demeanor === "Aggressive">> <<set _baseChance -= 30>> <</if>> <<set _compliance = Math.random() * 100>> <<if _compliance < _baseChance>> <<set $suspect.currentState = "complying">> <<set _reaction = "The suspect freezes at your command and raises their hands in surrender.">> <<elseif _compliance < _baseChance + 25>> <<set $suspect.currentState = "fleeing">> <<set $suspect.threatLevel = Math.min($suspect.threatLevel + 1, 5)>> <<set _reaction = "Startled by your shout, the suspect bolts and tries to run!">> <<else>> <<set $suspect.currentState = "resisting">> <<set $suspect.threatLevel = Math.min($suspect.threatLevel + 2, 5)>> <<set _reaction = "The suspect turns aggressive and refuses to comply!">> <</if>> <</if>> <<elseif $chosenAction === "Calm Approach">> <!-- Completely inappropriate for violent crimes --> <<if $crimeTier >= 3>> <<if $currentCrime === "AssaultWithWeapon">> <<set _weapon = $crimeDesc.weapon[Math.floor(Math.random() * $crimeDesc.weapon.length)]>> <<set _reaction = "You try to calmly approach someone wielding a " + _weapon + "?! They immediately turn the weapon on you! Your calm demeanor means nothing when someone has a deadly weapon!">> <<set $suspect.currentState = "attacking">> <<set $performance.appropriateness -= 50>> <<run $performance.warnings.push("CRITICAL ERROR: Used calm approach on armed suspect - extreme danger")>> <<elseif $currentCrime === "MajorTraitTheft">> <<set _reaction = "You try to approach calmly, but this is a professional criminal caught red-handed. They see you as an obstacle and immediately attack with trait-draining magic!">> <<set $suspect.currentState = "attacking">> <<set $performance.appropriateness -= 45>> <<run $performance.warnings.push("Inappropriate de-escalation attempt on dangerous magic user")>> <</if>> <<elseif $currentCrime === "Assault">> <<set _reaction = "You try to calmly intervene, but this person is already in a violent rage. They turn their aggression toward you!">> <<set $suspect.currentState = "attacking">> <<set $performance.appropriateness -= 30>> <<run $performance.warnings.push("Poor judgment - calm approach during active assault")>> <<else>> <<set _baseChance = 60 + _modifier>> <<if $suspect.demeanor === "Cool and calm" || $suspect.demeanor === "Nervous and sweaty">> <<set _baseChance += 15>> <<elseif $suspect.demeanor === "Aggressive">> <<set _baseChance -= 25>> <</if>> <<set _compliance = Math.random() * 100>> <<if _compliance < _baseChance>> <<set $suspect.currentState = "complying">> <<set _reaction = "The suspect seems relieved by your calm demeanor and cooperates.">> <<else>> <<set $suspect.currentState = "fleeing">> <<set $suspect.threatLevel = Math.min($suspect.threatLevel + 1, 5)>> <<set _reaction = "The suspect takes advantage of your calm approach and suddenly runs!">> <</if>> <</if>> <<elseif $chosenAction === "Physical Intervention">> <<if $suspectCount > 1>> <!-- Multiple suspects - very dangerous --> <<set _reaction = "You try to physically restrain one suspect, but there are " + $suspectCount + " of them! ">> <<if $context.backupArrived>> <<set _reaction += "Fortunately, backup helps you control the situation.">> <<set $suspect.currentState = "subdued">> <<else>> <<set _reaction += "You're immediately swarmed and overwhelmed! This was a terrible decision!">> <<set $suspect.currentState = "officer_down">> <<set $performance.appropriateness = 0>> <<run $performance.warnings.push("CRITICAL FAILURE: Attempted to physically engage multiple suspects alone")>> <</if>> <<elseif $crimeTier === 3 && $suspect.hasWeapon>> <!-- Tier 3 with weapon - extremely dangerous --> <<set _weapon = $crimeDesc.weapon[Math.floor(Math.random() * $crimeDesc.weapon.length)]>> <<set _success = Math.random() * 100>> <<if _success < 30 + _modifier>> <<set _reaction = "You manage to disarm the suspect and wrestle them to the ground before they can use the " + _weapon + "! That was incredibly risky but it worked.">> <<set $suspect.currentState = "subdued">> <<run $performance.warnings.push("Extremely risky disarm - could have been fatal")>> <<else>> <<set _reaction = "You move in to restrain them, but they swing the " + _weapon + " at you! You're forced to back off - this suspect is too dangerous to engage without a weapon drawn!">> <<set $suspect.currentState = "attacking">> <<set $performance.appropriateness -= 35>> <<run $performance.warnings.push("Failed to neutralize armed suspect - poor tactical decision")>> <</if>> <<else>> <<set _baseChance = 70 + _modifier>> <<if $suspect.build === "Scrawny">> <<set _baseChance += 20>> <<elseif $suspect.build === "Large" || $suspect.build === "Athletic">> <<set _baseChance -= 15>> <</if>> <<if $suspect.traits.physical.includes("Muscular") || $suspect.traits.physical.includes("Strong")>> <<set _baseChance -= 20>> <</if>> <<if $suspect.traits.skills.includes("Combat") || $suspect.traits.skills.includes("Martial Arts")>> <<set _baseChance -= 25>> <</if>> <<set _success = Math.random() * 100>> <<if _success < _baseChance>> <<set $suspect.currentState = "subdued">> <<set _reaction = "You successfully restrain the suspect. They struggle briefly but you maintain control.">> <<else>> <<set $suspect.currentState = "resisting">> <<set $suspect.threatLevel = Math.min($suspect.threatLevel + 2, 5)>> <<set _reaction = "The suspect fights back! They're stronger than you expected!">> <<if $crimeTier >= 3>> <<set _reaction += " This could get dangerous!">> <</if>> <</if>> <</if>> <<elseif $chosenAction === "Aggressive Takedown">> <<if $suspectCount > 1>> <<set _reaction = "You aggressively tackle one of the " + $suspectCount + " suspects, but the others immediately attack you! ">> <<if $context.backupArrived>> <<set _reaction += "Backup rushes in to help control the situation.">> <<set $suspect.currentState = "subdued">> <<else>> <<set _reaction += "You're overwhelmed by the group!">> <<set $suspect.currentState = "officer_down">> <<set $performance.appropriateness = 0>> <<run $performance.warnings.push("Reckless aggression against multiple suspects without backup")>> <</if>> <<else>> <<set $suspect.currentState = "subdued">> <<if $suspect.threatLevel <= 2>> <<set $performance.appropriateness -= 30>> <<run $performance.warnings.push("Excessive force for threat level")>> <<set _reaction = "You slam the suspect to the ground hard. They're subdued but witnesses look concerned at your aggression.">> <<else>> <<set _reaction = "You tackle the suspect hard. Given the threat level, the force was justified.">> <</if>> <</if>> <<elseif $chosenAction === "Use Taser">> <<if $suspectCount > 1>> <<set _reaction = "You deploy your taser on one suspect, but there are " + $suspectCount + " of them! The others attack while you're focused on the one!">> <<if $context.backupArrived>> <<set _reaction += " Backup secures the others.">> <<set $suspect.currentState = "subdued">> <<else>> <<set _reaction += " You're overwhelmed!">> <<set $suspect.currentState = "officer_down">> <<set $performance.appropriateness = 0>> <</if>> <<elseif $crimeTier <= 2>> <<set _success = Math.random() * 100>> <<if _success < 85>> <<set $suspect.currentState = "subdued">> <<set _reaction = "The taser strikes true! The suspect collapses, incapacitated. They're quickly restrained.">> <<set $performance.appropriateness -= 15>> <<run $performance.warnings.push("Taser use on low-threat suspect - may be excessive")>> <<else>> <<set $suspect.currentState = "fleeing">> <<set _reaction = "One of the taser probes misses! The suspect runs while you're reloading!">> <</if>> <<else>> <<set _success = Math.random() * 100>> <<if _success < 80>> <<set $suspect.currentState = "subdued">> <<set _reaction = "The taser deployment is successful! The suspect goes down. Appropriate less-lethal force for the threat level.">> <<else>> <<set $suspect.currentState = "attacking">> <<set _reaction = "The taser fails to connect properly! The suspect charges at you!">> <</if>> <</if>> <<elseif $chosenAction === "Draw Weapon">> <<if $currentCrime === "MajorHeist" || $currentCrime === "GangViolence">> <!-- Tier 4 - multiple armed suspects --> <<if !$context.backupCalled && !$context.backupArrived>> <<set _reaction = "You draw your weapon on " + $suspectCount + " armed criminals! They immediately open fire! You're completely outgunned and outnumbered!">> <<set $suspect.currentState = "officer_down">> <<set $performance.appropriateness = 0>> <<set $performance.procedureScore = 0>> <<run $performance.warnings.push("FATAL ERROR: Engaged multiple armed suspects alone")>> <<run $performance.warnings.push("Did not call for backup on Tier 4 incident")>> <<elseif $context.backupArrived>> <<set _reaction = "You and your backup draw weapons. Faced with multiple officers, the suspects surrender. This was handled correctly.">> <<set $suspect.currentState = "subdued">> <<run $performance.actions.push("Coordinated armed response with backup")>> <<else>> <<set _reaction = "You draw your weapon and order them to surrender. They're hesitating... you desperately need backup to arrive!">> <<set $suspect.currentState = "complying">> <<run $performance.warnings.push("Drew weapon on multiple suspects before backup arrived - extreme risk")>> <</if>> <<elseif $crimeTier >= 3>> <!-- Tier 3 - appropriate force --> <<set $suspect.currentState = "subdued">> <<if $suspect.hasWeapon>> <<set _weapon = $crimeDesc.weapon[Math.floor(Math.random() * $crimeDesc.weapon.length)]>> <<set _reaction = "You draw your weapon on the suspect who's armed with a " + _weapon + ". They immediately drop their weapon and surrender. This was the appropriate level of force.">> <<run $performance.actions.push("Appropriate force - armed suspect disarmed")>> <<else>> <<set _reaction = "You draw your weapon. The suspect immediately surrenders. Given the high threat level, this may be defensible.">> <<set $performance.appropriateness -= 15>> <<run $performance.warnings.push("Weapon drawn on unarmed Tier 3 suspect - review required")>> <</if>> <<else>> <!-- Tier 1-2 - excessive force --> <<set $suspect.currentState = "subdued">> <<set $performance.appropriateness -= 50>> <<run $performance.warnings.push("Drew weapon for non-life-threatening situation")>> <<run $performance.warnings.push("Excessive force - potential brutality complaint")>> <<set _reaction = "You draw your weapon on the suspect. They immediately surrender, terrified. Witnesses are filming this on their phones - this will not look good.">> <</if>> <<elseif $chosenAction === "Shoot to Neutralize" || $chosenAction === "Lethal Force">> <<if $crimeTier >= 3 && $suspect.hasWeapon>> <<set $suspect.currentState = "subdued">> <<set _reaction = "You fire and neutralize the armed threat. Given the imminent danger, this use of lethal force will likely be ruled justified.">> <<run $performance.actions.push("Lethal force used on armed suspect")>> <<set $performance.appropriateness -= 10>> <<elseif $currentCrime === "MajorHeist" || $currentCrime === "GangViolence">> <<if !$context.backupArrived>> <<set _reaction = "You open fire on multiple armed suspects alone! This becomes a firefight - you're outgunned!">> <<set $suspect.currentState = "officer_down">> <<set $performance.appropriateness = 0>> <<run $performance.warnings.push("Engaged in firefight with multiple suspects alone - fatal error")>> <<else>> <<set $suspect.currentState = "subdued">> <<set _reaction = "With backup support, lethal force is used to neutralize the armed threats. Multiple officers fire. The suspects are neutralized.">> <<run $performance.actions.push("Coordinated lethal force response")>> <</if>> <<else>> <<set $suspect.currentState = "subdued">> <<set $performance.appropriateness -= 70>> <<run $performance.warnings.push("CRITICAL: Lethal force used without imminent deadly threat")>> <<run $performance.warnings.push("Unjustified shooting - criminal charges likely")>> <<set _reaction = "You fire on the suspect! They go down. This was NOT a justified use of lethal force - you will face serious consequences!">> <</if>> <<elseif $chosenAction === "Call for Backup">> <<set $context.backupCalled = true>> <<if $context.activeCalls === "Major">> <<set $performance.procedureScore -= 20>> <<run $performance.warnings.push("Called for backup during major active incident elsewhere")>> <<set $context.backupTime += 3>> <<set _reaction = "You radio for backup, but dispatch informs you there's a major incident elsewhere. Your backup will be delayed - ETA now " + $context.backupTime + " minutes.">> <<else>> <<set _reaction = "You call for backup. Dispatch confirms - officers en route, ETA " + $context.backupTime + " minutes.">> <<run $performance.actions.push("Called for backup appropriately")>> <</if>> <<if $requiresBackup>> <<set _reaction += " This was the correct call for a Tier " + $crimeTier + " situation.">> <<set $performance.procedureScore += 20>> <</if>> <!-- Check if suspect escapes while waiting --> <<if $crimeTier <= 2>> <<set _escape = Math.random() * 100>> <<set _escapeChance = 40 - ($context.nearbyOfficers * 10)>> <<if _escape < _escapeChance>> <<set $suspect.currentState = "escaped">> <<set $performance.outcomeScore = 0>> <<run $performance.warnings.push("Suspect escaped while waiting for backup")>> <<set _reaction += " However, while you wait, the suspect notices you on the radio and bolts before you can react!">> <<else>> <<set _reaction += " The suspect doesn't notice or doesn't run.">> <</if>> <</if>> <<elseif $chosenAction === "Wait for Backup">> <<set $context.backupTime -= 1>> <<if $context.backupTime <= 0>> <<set $context.backupArrived = true>> <<set _reaction = "Backup arrives! ">> <<if $currentCrime === "MajorHeist" || $currentCrime === "GangViolence">> <<set _reaction += "With " + Math.floor(Math.random() * 4 + 4) + " additional officers, you coordinate a tactical response. The suspects are surrounded and surrender after a tense standoff. Excellent patience and procedure.">> <<set $suspect.currentState = "subdued">> <<set $performance.procedureScore += 30>> <<set $performance.outcomeScore = 100>> <<run $performance.actions.push("Waited for backup on Tier 4 - textbook response")>> <<elseif $crimeTier === 3>> <<set _reaction += "With additional officers, the arrest is made safely. Good call waiting for support.">> <<set $suspect.currentState = "subdued">> <<set $performance.procedureScore += 15>> <<set $performance.outcomeScore = 80>> <</if>> <<else>> <<set _reaction = "You maintain your position and wait. The suspect is still active. Backup arrives in " + $context.backupTime + " minute">> <<if $context.backupTime > 1>><<set _reaction += "s">><</if>> <<set _reaction += ".">> <!-- Check if situation escalates while waiting --> <<if Math.random() < 0.3 && $crimeTier >= 3>> <<if $currentCrime === "AssaultWithWeapon">> <<set _reaction += " The armed suspect is getting more agitated!">> <<set $suspect.threatLevel = Math.min($suspect.threatLevel + 1, 5)>> <<elseif $currentCrime === "MajorTraitTheft">> <<set _reaction += " The trait thief is draining more victims while you wait!">> <<set $performance.outcomeScore -= 10>> <</if>> <</if>> <</if>> <<elseif $chosenAction === "Initiate Pursuit" || $chosenAction === "Aggressive Pursuit">> <<if $chosenAction === "Aggressive Pursuit">> <<set _chaseSuccess = Math.random() * 100>> <<if _chaseSuccess < 60>> <<set $suspect.currentState = "subdued">> <<set _reaction = "You engage in a high-speed pursuit and execute a PIT maneuver. The vehicle spins out and crashes. The driver is apprehended but there's significant property damage.">> <<set $performance.appropriateness -= 25>> <<run $performance.warnings.push("Excessive force - high-speed pursuit with PIT maneuver for speeding violation")>> <<else>> <<set $suspect.currentState = "escaped">> <<set _reaction = "You pursue aggressively but the driver is reckless. After a dangerous chase, they escape down a side street you can't follow. The pursuit caused multiple traffic incidents.">> <<set $performance.appropriateness -= 40>> <<set $performance.outcomeScore = 0>> <<run $performance.warnings.push("Reckless pursuit resulted in escape and public danger")>> <</if>> <<else>> <<set _pullOver = Math.random() * 100>> <<if _pullOver < 70>> <<set $suspect.currentState = "subdued">> <<set _reaction = "You initiate pursuit with lights and sirens. The driver pulls over after a brief chase. Good, controlled pursuit.">> <<set $performance.outcomeScore = 90>> <<else>> <<set $suspect.currentState = "fleeing">> <<set _reaction = "You turn on your lights and sirens, but the driver accelerates! This is turning into a pursuit!">> <</if>> <</if>> <<elseif $chosenAction === "Break Window">> <<set $suspect.currentState = "subdued">> <<set _reaction = "You break the vehicle's window to check for emergencies. There's no one inside and no emergency. This was completely unnecessary property damage.">> <<set $performance.appropriateness -= 60>> <<run $performance.warnings.push("Destroyed property without justification")>> <<run $performance.warnings.push("Excessive response to parking violation")>> <<set $performance.outcomeScore = 20>> <</if>> <!-- Track if officer went in alone on dangerous situation --> <<if ($crimeTier >= 3 || $suspectCount > 1) && !$context.backupCalled && $chosenAction !== "Call for Backup" && $chosenAction !== "Wait for Backup">> <<set $performance.wentInAlone = true>> <<set $performance.procedureScore -= 30>> <<run $performance.warnings.push("Engaged Tier " + $crimeTier + " threat without calling for backup first")>> <</if>> <!-- Evaluate Force Appropriateness --> <<if $forceLevel > 0>> <<set _forceDifference = $forceLevel - $suspect.threatLevel>> <<if _forceDifference > 2>> <<set $performance.appropriateness -= 25>> <<run $performance.warnings.push("Force used significantly exceeded threat level")>> <<elseif _forceDifference > 0>> <<set $performance.appropriateness -= 10>> <</if>> <</if>> <!-- Display Response --> <div class="crime-scene"> <h1 class="crime-header">⚡ Action Result</h1> <div class="response-box"> <h3 class="response-action">You used: <<print $chosenAction>></h3> <p class="response-text"><<print _reaction>></p> </div> <<if $suspect.currentState !== "subdued" && $suspect.currentState !== "escaped" && $suspect.currentState !== "officer_down">> <div class="alert-box"> <p class="alert-text">⚠️ The situation is still active! Choose your next action.</p> </div> <</if>> <<link "<div class='action-button button-continue'>Continue</div>">> <<goto "CrimeScene">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "JanitorWorkComplete">> <!-- Achievement for working hourly job --> <<run setup.achievements.unlock("hourly_job")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Janitor")>> <<run $jobsWorked.push("Janitor")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <!-- ===== SKILL TREE: Get hourly pay bonus ===== --> <<set _hourlyPayBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _hourlyPayBonus = setup.skillTree.getEffect("hourlyPayBonus") || 0>> <</if>> <!-- Calculate skill tree bonus on janitor pay --> <<set _basePay = $janitorPayEarned || 96>> <<set _skillTreeBonus = 0>> <<if _hourlyPayBonus > 0>> <<set _skillTreeBonus = Math.floor(_basePay * (_hourlyPayBonus / 100))>> <</if>> <!-- Add skill tree bonus to total (if not already added during work start) --> <<if _skillTreeBonus > 0 && !$janitorSkillTreeBonusApplied>> <<set $money += _skillTreeBonus>> <<set $janitorSkillTreeBonusApplied = true>> <</if>> <<set _totalPay = _basePay + _skillTreeBonus>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #2ecc71; text-align: center;">✅ Shift Complete</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: white; font-size: 18px; text-align: center; margin: 0;"> You've completed your 8-hour janitorial shift! </p> </div> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #34495e;"> <h3 style="color: #2ecc71; margin-top: 0;">💰 Payment Received</h3> <p style="color: #ecf0f1; font-size: 16px;"> You spent 8 hours mopping floors, cleaning bathrooms, emptying trash, and keeping the station spotless. The work was tiring but honest, and you've earned your pay. </p> <div style="background: #34495e; padding: 15px; border-radius: 8px; margin: 15px 0;"> <p style="color: #95a5a6; margin: 5px 0;"><strong>Base Pay:</strong> $96 (8 hours × $12/hour)</p> <<if $janitorPenalties && $janitorPenalties.length > 0>> <div style="border-top: 1px solid #7f8c8d; margin: 10px 0; padding-top: 10px;"> <p style="color: #e74c3c; font-weight: bold; margin: 5px 0;">Penalties Applied:</p> <<for _penalty range $janitorPenalties>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _penalty</p> <</for>> </div> <</if>> <<if $janitorBonuses && $janitorBonuses.length > 0>> <div style="border-top: 1px solid #7f8c8d; margin: 10px 0; padding-top: 10px;"> <p style="color: #2ecc71; font-weight: bold; margin: 5px 0;">Bonuses Applied:</p> <<for _bonus range $janitorBonuses>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _bonus</p> <</for>> </div> <</if>> <!-- ===== SKILL TREE: Display bonus ===== --> <<if _skillTreeBonus > 0>> <div style="border-top: 1px solid #9C27B0; margin: 10px 0; padding-top: 10px;"> <p style="color: #CE93D8; font-weight: bold; margin: 5px 0;">⭐ Skill Tree Bonus:</p> <p style="color: #CE93D8; margin: 3px 0; font-size: 14px;">• Hourly Pay Bonus (+<<print _hourlyPayBonus>>%): +$<<print _skillTreeBonus>></p> </div> <</if>> </div> <p style="color: #2ecc71; font-size: 20px; font-weight: bold; text-align: center; margin: 20px 0;"> +$<<print _totalPay>> </p> <p style="color: #95a5a6; text-align: center;"> Current Balance: $<<print $money>> </p> </div> <!-- Reset the bonus applied flag for next shift --> <<set $janitorSkillTreeBonusApplied = false>> <<link "<div style='background: #3498db; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; transition: all 0.3s;' onmouseover='this.style.background=\"#2980b9\"' onmouseout='this.style.background=\"#3498db\"'>Return to Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PoliceReceptionistTalk">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">💼 Talking to <<print $talkingToReceptionist.name>></h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #d63384 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0;"> <<print $talkingToReceptionist.name>> looks up from the reception desk with a professional smile. </p> </div> <!-- Check if janitor job is available --> <<set _janitorAvailable = true>> <<if $jobs && $jobs.includes("Police Station Janitor")>> <<set _janitorAvailable = false>> <</if>> <<if _janitorAvailable>> <<set _janitorNPCs = setup.getNPCsByJob("Police Station Janitor")>> <<if _janitorNPCs && _janitorNPCs.length > 0>> <<set _janitorAvailable = false>> <</if>> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Ask About Jobs --> <div style="border: 3px solid #ffd43b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd43b; margin-top: 0;">💼 Ask About Jobs</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Inquire about job openings at the station.</p> <<link "<div style='background: #ffd43b; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Are you hiring?\"</div>">> <<goto "PoliceReceptionistJobs">> <</link>> </div> <!-- Leave --> <div style="border: 3px solid #4169e1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4169e1; margin-top: 0;">🚪 Leave</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Return to the police department lobby.</p> <<link "<div style='background: #4169e1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Say Goodbye</div>">> <<goto "PoliceDepartment">> <</link>> </div> </div> <div id="receptionistMessage"></div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PoliceReceptionistJobs">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">💼 Job Opportunities</h1> <!-- Check if janitor job is available --> <<set _janitorAvailable = true>> <<if $jobs && $jobs.includes("Police Station Janitor")>> <<set _janitorAvailable = false>> <<set _alreadyHasJob = true>> <<else>> <<set _alreadyHasJob = false>> <</if>> <<if _janitorAvailable>> <<set _janitorNPCs = setup.getNPCsByJob("Police Station Janitor")>> <<if _janitorNPCs && _janitorNPCs.length > 0>> <<set _janitorAvailable = false>> <<set _janitorTaken = _janitorNPCs[0]>> <</if>> <</if>> <<if _alreadyHasJob>> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #95a5a6;"> <p style="color: #ecf0f1; font-size: 16px; margin: 0;"> <<print $talkingToReceptionist.name>>: "You already work here as a janitor! You don't need to apply again." </p> </div> <<elseif !_janitorAvailable && _janitorTaken>> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #e74c3c;"> <p style="color: #ecf0f1; font-size: 16px; margin: 0;"> <<print $talkingToReceptionist.name>>: "Sorry, we're not hiring at the moment. <<print _janitorTaken.name>> is currently handling all our janitorial needs." </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: white; font-size: 16px; margin: 0;"> <<print $talkingToReceptionist.name>>: "Actually, yes! We're looking for a janitor. The pay is $12 per hour, and you can work one 4-hour shift per day. It's honest work keeping the station clean. Interested?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Take the janitorial position.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Police Station Janitor"]>> <<goto "PoliceReceptionistJobAccepted">> <</link>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "PoliceReceptionistTalk">> <</link>> </div> </div> <</if>> <<if _alreadyHasJob || (!_janitorAvailable && _janitorTaken)>> <<link "<div style='background: #4169e1; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 20px; transition: all 0.3s;' onmouseover='this.style.background=\"#2c5aa0\"' onmouseout='this.style.background=\"#4169e1\"'>Return</div>">> <<goto "PoliceReceptionistTalk">> <</link>> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PoliceReceptionistJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #2ecc71; text-align: center;">🎉 Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: white; font-size: 18px; text-align: center; margin: 0;"> Congratulations! You're now a Police Station Janitor! </p> </div> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #34495e;"> <p style="color: #ecf0f1; font-size: 16px; margin: 0;"> <<print $talkingToReceptionist.name>>: "Great! Welcome aboard. You can access the break room now and start working whenever you're ready. Just head there and you'll find the janitorial closet. Good luck!" </p> </div> <<link "<div style='background: #3498db; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; transition: all 0.3s;' onmouseover='this.style.background=\"#2980b9\"' onmouseout='this.style.background=\"#3498db\"'>Return to Lobby</div>">> <<goto "PoliceDepartment">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Jail">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Jail")>> <<run $visitedLocations.push("Jail")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #888; text-align: center; margin: 15px 0;">⚖️ County Jail</h1> <<if !$jailSystem>> <<set $jailSystem = { inJail: false, daysToServe: 0, daysServed: 0, canPayFine: false, fineAmount: 0, previousJob: "", fromPoliceCorruption: false }>> <</if>> <<if !$crimeSystem.crimesCommitted>> <<set $crimeSystem.crimesCommitted = 0>> <</if>> <<if !$crimeSystem.consecutiveEscapes>> <<set $crimeSystem.consecutiveEscapes = 0>> <</if>> <!-- Check if coming from police corruption --> <<if $performance && $performance.traitTheftDetected>> <<set $jailSystem.fromPoliceCorruption = true>> <<set $jailSystem.daysToServe = Math.max($stolenTraitsOnDuty.length, 1) * 2>> <<set $jailSystem.fineAmount = 0>> <<set $jailSystem.canPayFine = false>> <<set $jailSystem.previousJob = "Unemployed">> <<else>> <<set $jailSystem.fromPoliceCorruption = false>> <</if>> <!-- Calculate jail time based on crimes committed (crime system) --> <<if !$jailSystem.fromPoliceCorruption && $jailSystem.daysToServe === 0 && $crimeSystem.crimesCommitted > 0>> <<set $jailSystem.daysToServe = $crimeSystem.crimesCommitted>> <<set $jailSystem.fineAmount = $crimeSystem.crimesCommitted * 250>> <<set $jailSystem.canPayFine = true>> <</if>> <!-- If not serving time, show intro --> <<if !$jailSystem.inJail>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #666;"> <p style="color: #ccc; margin: 0; font-size: 15px;"> A cold, gray building with thick concrete walls and barred windows. The bars are solid and there's no way out except to serve your time or pay the fine. </p> </div> <!-- POLICE CORRUPTION PATH --> <<if $jailSystem.fromPoliceCorruption>> <div style="background: linear-gradient(135deg, #8b0000 0%, #dc3545 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ff0000;"> <h3 style="color: #fff; margin: 0 0 15px 0; text-align: center;">🚔 CORRUPT OFFICER - SERVING TIME</h3> <div style="background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"><b>Traits Stolen While On Duty:</b> $stolenTraitsOnDuty.length</p> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"><b>Required Jail Time:</b> $jailSystem.daysToServe days</p> <p style="color: #ff6b6b; margin: 0; font-size: 14px; font-style: italic;">No fine option available for corrupt officers</p> </div> <p style="color: #fff; margin: 0; font-size: 14px; text-align: center; font-style: italic;"> You must serve your full sentence for abusing your position of authority. </p> </div> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: #666; color: #fff; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold;'>⏳ Begin Serving Time</div>">> <<set $jailSystem.inJail = true>> <<set $jailSystem.daysServed = 0>> <<set $crimeSystem.consecutiveEscapes = 0>> <<goto "Jail">> <</link>> </div> <!-- CRIMINAL PATH --> <<elseif $jobs && $jobs.includes("Criminal")>> <div style="background: linear-gradient(135deg, #c0392b 0%, #e74c3c 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ff0000;"> <h3 style="color: #fff; margin: 0 0 15px 0; text-align: center;">🔴 CRIMINAL STATUS</h3> <div style="background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"><b>Crimes Committed:</b> $crimeSystem.crimesCommitted</p> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"><b>Required Jail Time:</b> $jailSystem.daysToServe days</p> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"><b>Alternative Fine:</b> $<<print $jailSystem.fineAmount>></p> <<if $jailSystem.previousJob && $jailSystem.previousJob !== "Unemployed">> <p style="color: #ffd43b; margin: 0; font-size: 15px;"><b>Previous Job:</b> $jailSystem.previousJob (will be restored)</p> <</if>> </div> <p style="color: #fff; margin: 0; font-size: 14px; text-align: center; font-style: italic;"> You cannot trade away the Criminal job until you serve your time or pay the fine. </p> </div> <!-- Serve Time or Pay Fine Options --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <<link "<div style='background: #666; color: #fff; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold;'>⏳ Serve Jail Time</div>">> <<set $jailSystem.inJail = true>> <<set $jailSystem.daysServed = 0>> <<set $crimeSystem.consecutiveEscapes = 0>> <<goto "Jail">> <</link>> <<if $money >= $jailSystem.fineAmount>> <<link "<div style='background: #f39c12; color: #fff; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold;'>💰 Pay Fine</div>">> <<set $money -= $jailSystem.fineAmount>> <<if $jailSystem.previousJob && $jailSystem.previousJob !== "">> <<set $jobs = [$jailSystem.previousJob]>> <<else>> <<set $jobs = ["Unemployed"]>> <</if>> <<set $jailSystem.daysToServe = 0>> <<set $crimeSystem.crimesCommitted = 0>> <<set $crimeSystem.consecutiveEscapes = 0>> <<goto "PayFineResult">> <</link>> <<else>> <div style='background: #3a3a3a; color: #666; padding: 15px; border-radius: 8px; text-align: center; opacity: 0.5; font-weight: bold;'>💰 Pay Fine ($<<print $jailSystem.fineAmount>>)<br><span style="font-size: 13px;">Not enough money</span></div> <</if>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #666;"> <p style="color: #ccc; text-align: center; margin: 0; font-size: 15px; font-style: italic;"> You're not currently incarcerated. This facility is only accessible to those serving time. </p> </div> <</if>> <</if>> <!-- If currently serving time --> <<if $jailSystem.inJail>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0; text-align: center;">⏳ SERVING TIME</h3> <div style="background: rgba(0,0,0,0.3); padding: 15px; border-radius: 8px;"> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 15px;"><b>Days Served:</b> $jailSystem.daysServed / $jailSystem.daysToServe</p> <p style="color: #ccc; margin: 0; font-size: 15px;"><b>Days Remaining:</b> <<print $jailSystem.daysToServe - $jailSystem.daysServed>></p> <<if $jailSystem.fromPoliceCorruption>> <p style="color: #ff6b6b; margin: 10px 0 0 0; font-size: 14px; font-style: italic;">Serving time for corruption charges</p> <</if>> </div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #888;"> <p style="color: #aaa; margin: 0 0 15px 0; font-size: 14px; text-align: center; font-style: italic;"> You spend your days in a small cell. The monotonous routine and harsh conditions begin to change you... </p> <<if $jailSystem.daysServed < $jailSystem.daysToServe>> <<link "<div style='background: #667eea; color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>⏭️ Serve Another Day</div>">> <<set $jailSystem.daysServed += 1>> <<set $day += 1>> <<set setup.processJailTraitChange()>> <<goto "Jail">> <</link>> <<else>> <div style="background: linear-gradient(135deg, #51cf66 0%, #2ecc71 100%); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #51cf66;"> <h3 style="color: #fff; margin: 0 0 10px 0; text-align: center;">✅ TIME SERVED</h3> <p style="color: #fff; margin: 0; text-align: center; font-size: 15px;"> You've completed your sentence and are eligible for release! </p> </div> <<link "<div style='background: #51cf66; color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>🚪 Leave Jail</div>">> <<set $jailSystem.inJail = false>> <<set $jailSystem.daysToServe = 0>> <<set $jailSystem.daysServed = 0>> <!-- Police corruption path - already unemployed --> <<if $jailSystem.fromPoliceCorruption>> <<set $jobs = ["Unemployed"]>> <<set $stolenTraitsOnDuty = []>> <<set $jailSystem.fromPoliceCorruption = false>> <<unset $performance>> <!-- Criminal path - restore previous job --> <<else>> <<if $jailSystem.previousJob && $jailSystem.previousJob !== "">> <<set $jobs = [$jailSystem.previousJob]>> <<else>> <<set $jobs = ["Unemployed"]>> <</if>> <<set $crimeSystem.crimesCommitted = 0>> <</if>> <<goto "JailReleaseResult">> <</link>> <</if>> </div> <</if>> <<if !$jailSystem.inJail && (!$jobs || !$jobs.includes("Criminal")) && !$jailSystem.fromPoliceCorruption>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold;'>← Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ReceptionistWorkComplete">> <!-- ===== SKILL TREE: Get hourly pay bonus ===== --> <<set _hourlyPayBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _hourlyPayBonus = setup.skillTree.getEffect("hourlyPayBonus") || 0>> <</if>> <!-- Calculate skill tree bonus --> <<set _basePay = $receptionistPayEarned || 60>> <<set _skillTreeBonus = $receptionistSkillTreeBonus || 0>> <<set _totalPay = _basePay + _skillTreeBonus>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">✅ Shift Complete</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #d63384 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; text-align: center; margin: 0;"> You've completed your 4-hour reception shift! </p> </div> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #34495e;"> <h3 style="color: #e83e8c; margin-top: 0;">💰 Payment Received</h3> <p style="color: #ecf0f1; font-size: 16px;"> You spent 4 hours answering phones, greeting visitors, filing paperwork, and keeping the front desk running smoothly. Your professional demeanor made a good impression. </p> <div style="background: #34495e; padding: 15px; border-radius: 8px; margin: 15px 0;"> <p style="color: #95a5a6; margin: 5px 0;"><strong>Base Pay:</strong> $60 (4 hours × $15/hour)</p> <<if $receptionistBonuses && $receptionistBonuses.length > 0>> <div style="border-top: 1px solid #2ecc71; margin: 10px 0; padding-top: 10px;"> <p style="color: #2ecc71; font-weight: bold; margin: 5px 0;">Performance Bonuses:</p> <<for _bonus range $receptionistBonuses>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _bonus</p> <</for>> </div> <</if>> <<if $receptionistPenalties && $receptionistPenalties.length > 0>> <div style="border-top: 1px solid #e74c3c; margin: 10px 0; padding-top: 10px;"> <p style="color: #e74c3c; font-weight: bold; margin: 5px 0;">Performance Penalties:</p> <<for _penalty range $receptionistPenalties>> <p style="color: #ecf0f1; margin: 3px 0; font-size: 14px;">• _penalty</p> <</for>> </div> <</if>> <!-- ===== SKILL TREE: Display bonus ===== --> <<if _skillTreeBonus > 0>> <div style="border-top: 1px solid #9C27B0; margin: 10px 0; padding-top: 10px;"> <p style="color: #CE93D8; font-weight: bold; margin: 5px 0;">⭐ Skill Tree Bonus:</p> <p style="color: #CE93D8; margin: 3px 0; font-size: 14px;">• Hourly Pay Bonus (+<<print _hourlyPayBonus>>%): +$<<print _skillTreeBonus>></p> </div> <</if>> </div> <p style="color: #e83e8c; font-size: 20px; font-weight: bold; text-align: center; margin: 20px 0;"> +$<<print _totalPay>> </p> <p style="color: #95a5a6; text-align: center;"> Current Balance: $<<print $money>> </p> </div> <!-- Co-worker relationship bonus (receptionists) --> <<set _coworkerBonuses = []>> <<set _coworkers = setup.getNPCsByJob("Receptionist")>> <<if _coworkers && _coworkers.length > 0>> <<for _i = 0; _i < _coworkers.length; _i++>> <<set _coworker = _coworkers[_i]>> <<set _coworkerName = _coworker.name>> <<if random(1, 100) <= 50>> <<set _relPoints = random(1, 5)>> <<run setup.meetNPC(_coworker)>> <<run setup.addRelationshipPoints(_coworkerName, _relPoints)>> <<run _coworkerBonuses.push({name: _coworkerName, points: _relPoints})>> <</if>> <</for>> <</if>> <<if _coworkerBonuses.length > 0>> <div style="padding: 20px; background: #2c3e50; border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea;"> <h3 style="color: #667eea; margin-top: 0;">👥 Co-Worker Bonding</h3> <p style="color: #aaa; font-size: 14px; margin-bottom: 15px;">Working alongside your colleagues has strengthened your relationships!</p> <<for _cwb range _coworkerBonuses>> <div style="background: #34495e; padding: 10px 15px; border-radius: 8px; margin-top: 8px; border: 2px solid #51cf66; display: flex; justify-content: space-between; align-items: center;"> <span style="color: #fff;">💚 <<print _cwb.name>></span> <span style="color: #51cf66; font-weight: bold;">+<<print _cwb.points>> points</span> </div> <</for>> </div> <</if>> <<link "<div style='background: #3498db; color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; transition: all 0.3s;' onmouseover='this.style.background=\"#2980b9\"' onmouseout='this.style.background=\"#3498db\"'>Return to Break Room</div>">> <<goto "PoliceBreakRoom">> <</link>> </div> <</nobr>>
<<nobr>> <<silently>> /* Crime System Initialization */ <<set setup.visiblePhysicalTraits = [ "Athletic Build", "Muscular", "Scarred", "Tattooed", "Tall", "Short", "Petite", "Broad-shouldered", "Lean", "Fit", "Strong", "Weak", "Overweight", "Underweight", "Curvy", "Voluptuous", "Attractive", "Ugly", "Plain", "Youthful", "Mature", "Freckled", "Pierced", "Long Hair", "Short Hair", "Fashionable", "Smooth Skin", "Blemished" ]>> <<set setup.detectableMentalTraits = [ "Nervous", "Aggressive", "Calm", "Arrogant", "Confident", "Shy", "Awkward", "Friendly", "Cold", "Rude", "Polite", "Talkative", "Quiet", "Energetic", "Lazy", "Brave", "Cowardly", "Humble", "Extroverted", "Introverted" ]>> <<set setup.detectableVoiceTraits = [ "Smooth Voice", "Raspy Voice", "Deep Voice", "High-Pitched Tone", "Stuttering Speech", "Mumbly Voice", "Monotone", "Fast Talker", "Slow Calm Voice", "Sharp Voice", "Friendly Tone", "Warm Tone", "Articulate Speech" ]>> <<set setup.dangerousTraits = [ "Muscular", "Scarred", "Tattooed", "Athletic Build", "Strong", "Aggressive", "Combat", "Martial Arts", "Brave", "Reckless", "Dominant", "Cold", "Cruel" ]>> <<set setup.criminalSkills = [ "Combat", "Stealth", "Lock Picking", "Athletics", "Persuasion", "Fast Talker" ]>> <<set setup.generateCriminalTraits = function(tier, age, build) { var traits = { physical: [], mental: [], voice: [], skills: [], visible: [], hidden: [] }; var numPhysical = Math.floor(Math.random() * 2) + tier; var numMental = Math.floor(Math.random() * 2) + tier; var numSkills = Math.floor(Math.random() * tier) + 1; var physicalPool = Object.keys(setup.traitBonuses).filter(function(trait) { return setup.visiblePhysicalTraits.includes(trait); }); if (tier >= 2) { for (var i = 0; i < tier - 1; i++) { if (Math.random() < 0.6) { var dangerousTrait = setup.dangerousTraits[Math.floor(Math.random() * setup.dangerousTraits.length)]; if (!traits.physical.includes(dangerousTrait)) { traits.physical.push(dangerousTrait); } } } } if (build === "Athletic" || build === "Large") { if (Math.random() < 0.7 && !traits.physical.includes("Muscular")) { traits.physical.push("Muscular"); } if (Math.random() < 0.5 && !traits.physical.includes("Strong")) { traits.physical.push("Strong"); } } while (traits.physical.length < numPhysical && physicalPool.length > 0) { var randomTrait = physicalPool[Math.floor(Math.random() * physicalPool.length)]; if (!traits.physical.includes(randomTrait)) { var conflict = setup.getConflictingTrait(randomTrait, traits.physical); if (!conflict) { traits.physical.push(randomTrait); } } physicalPool.splice(physicalPool.indexOf(randomTrait), 1); } var mentalPool = []; if (tier >= 3) { mentalPool = ["Aggressive", "Cold", "Cruel", "Reckless", "Arrogant"]; } else if (tier === 2) { mentalPool = ["Aggressive", "Confident", "Brave", "Sly"]; } else { mentalPool = ["Nervous", "Scared", "Impulsive", "Foolish"]; } for (var j = 0; j < numMental && j < mentalPool.length; j++) { var randomMental = mentalPool[Math.floor(Math.random() * mentalPool.length)]; if (!traits.mental.includes(randomMental)) { traits.mental.push(randomMental); } } if (Math.random() < 0.6) { var voicePool = setup.detectableVoiceTraits; traits.voice.push(voicePool[Math.floor(Math.random() * voicePool.length)]); } var skillPool = Object.keys(setup.skillBonuses); if (tier >= 2) { skillPool = setup.criminalSkills; } for (var k = 0; k < numSkills && k < skillPool.length; k++) { var randomSkill = skillPool[Math.floor(Math.random() * skillPool.length)]; if (!traits.skills.includes(randomSkill)) { traits.skills.push(randomSkill); } } traits.visible = traits.physical.concat(traits.voice.filter(function(t) { return setup.detectableVoiceTraits.includes(t); })).concat(traits.mental.filter(function(t) { return setup.detectableMentalTraits.includes(t); })); traits.hidden = traits.mental.filter(function(t) { return !traits.visible.includes(t); }).concat(traits.skills); return traits; }>> <<set setup.calculateSuspectStats = function(suspect) { var stats = { strength: 10, dexterity: 10, intelligence: 10, charisma: 10 }; var allTraits = (suspect.traits.physical || []) .concat(suspect.traits.mental || []) .concat(suspect.traits.voice || []) .concat(suspect.traits.skills || []); allTraits.forEach(function(trait) { var bonus = setup.traitBonuses[trait] || setup.skillBonuses[trait]; if (bonus) { for (var stat in bonus) { stats[stat] += bonus[stat]; } } }); return stats; }>> <<set setup.getPlayerActionModifier = function(action, suspect) { var v = State.variables; var modifier = 0; var playerTraits = (v.physicalTraits || []) .concat(v.mentalTraits || []) .concat(v.skills || []); var suspectStats = setup.calculateSuspectStats(suspect); var playerStats = { strength: Math.min(setup.getTotalStat('strength'), 100), dexterity: Math.min(setup.getTotalStat('dexterity'), 100), intelligence: Math.min(setup.getTotalStat('intelligence'), 100), charisma: Math.min(setup.getTotalStat('charisma'), 100) }; if (action === "Verbal Warning") { modifier += (playerStats.charisma - suspectStats.intelligence) * 2; if (playerTraits.includes("Confident")) { modifier += 20; } if (playerTraits.includes("Brave")) { modifier += 15; } if (playerTraits.includes("Diplomatic")) { modifier += 20; } if (playerTraits.includes("Public Speaking")) { modifier += 15; } if (playerTraits.includes("Articulate Speech")) { modifier += 10; } if (playerTraits.includes("Charismatic Voice")) { modifier += 15; } if (playerTraits.includes("Smooth Talker")) { modifier += 15; } if (playerTraits.includes("Shy")) { modifier -= 20; } if (playerTraits.includes("Awkward")) { modifier -= 15; } if (playerTraits.includes("Stuttering Speech")) { modifier -= 15; } if (playerTraits.includes("Mumbly Voice")) { modifier -= 10; } if (playerTraits.includes("Cowardly")) { modifier -= 25; } if (playerTraits.includes("Insecure")) { modifier -= 15; } } else if (action === "Calm Approach") { modifier += (playerStats.charisma - suspectStats.charisma) * 2; modifier += (playerStats.intelligence - suspectStats.intelligence); if (playerTraits.includes("Calm")) { modifier += 25; } if (playerTraits.includes("Empathetic")) { modifier += 20; } if (playerTraits.includes("Diplomatic")) { modifier += 25; } if (playerTraits.includes("Patient")) { modifier += 15; } if (playerTraits.includes("Friendly")) { modifier += 15; } if (playerTraits.includes("Kind")) { modifier += 15; } if (playerTraits.includes("Warm")) { modifier += 10; } if (playerTraits.includes("Reassuring")) { modifier += 15; } if (playerTraits.includes("Soothing Tone")) { modifier += 10; } if (playerTraits.includes("Gentle Voice")) { modifier += 10; } if (playerTraits.includes("Aggressive")) { modifier -= 25; } if (playerTraits.includes("Short Tempered")) { modifier -= 20; } if (playerTraits.includes("Impatient")) { modifier -= 15; } if (playerTraits.includes("Cold")) { modifier -= 20; } if (playerTraits.includes("Rude")) { modifier -= 20; } if (playerTraits.includes("Blunt")) { modifier -= 10; } } else if (action === "Physical Intervention" || action === "Aggressive Takedown") { modifier += (playerStats.strength + playerStats.dexterity - suspectStats.strength - suspectStats.dexterity); if (playerTraits.includes("Combat")) { modifier += 30; } if (playerTraits.includes("Martial Arts")) { modifier += 35; } if (playerTraits.includes("Athletic Build")) { modifier += 20; } if (playerTraits.includes("Muscular")) { modifier += 20; } if (playerTraits.includes("Strong")) { modifier += 20; } if (playerTraits.includes("Quick Reflexes")) { modifier += 20; } if (playerTraits.includes("Fit")) { modifier += 15; } if (playerTraits.includes("Brave")) { modifier += 15; } if (playerTraits.includes("Aggressive")) { modifier += 15; } if (playerTraits.includes("Dominant")) { modifier += 10; } if (playerTraits.includes("Athletics")) { modifier += 20; } if (playerTraits.includes("Fast")) { modifier += 15; } if (playerTraits.includes("Quick")) { modifier += 15; } if (playerTraits.includes("Weak")) { modifier -= 30; } if (playerTraits.includes("Clumsy")) { modifier -= 25; } if (playerTraits.includes("Slow")) { modifier -= 20; } if (playerTraits.includes("Cowardly")) { modifier -= 30; } if (playerTraits.includes("Overweight")) { modifier -= 20; } if (playerTraits.includes("Underweight")) { modifier -= 15; } if (playerTraits.includes("Stiff")) { modifier -= 20; } if (playerTraits.includes("Lazy")) { modifier -= 15; } if (playerTraits.includes("Submissive")) { modifier -= 15; } if (playerTraits.includes("Passive")) { modifier -= 10; } } else if (action === "Draw Weapon") { modifier += (playerStats.dexterity + playerStats.charisma - suspectStats.intelligence); if (playerTraits.includes("Quick Reflexes")) { modifier += 20; } if (playerTraits.includes("Brave")) { modifier += 20; } if (playerTraits.includes("Confident")) { modifier += 15; } if (playerTraits.includes("Calm")) { modifier += 15; } if (playerTraits.includes("Steadfast")) { modifier += 10; } if (playerTraits.includes("Disciplined")) { modifier += 15; } if (playerTraits.includes("Clumsy")) { modifier -= 25; } if (playerTraits.includes("Cowardly")) { modifier -= 30; } if (playerTraits.includes("Nervous")) { modifier -= 20; } if (playerTraits.includes("Shaky Voice")) { modifier -= 15; } if (playerTraits.includes("Insecure")) { modifier -= 15; } } else if (action === "Call for Backup") { modifier += (playerStats.intelligence - suspectStats.intelligence); if (playerTraits.includes("Wise")) { modifier += 20; } if (playerTraits.includes("Logical")) { modifier += 15; } if (playerTraits.includes("Analytical")) { modifier += 15; } if (playerTraits.includes("Cautious")) { modifier += 15; } if (playerTraits.includes("Humble")) { modifier += 10; } if (playerTraits.includes("Patient")) { modifier += 10; } if (playerTraits.includes("Arrogant")) { modifier -= 20; } if (playerTraits.includes("Reckless")) { modifier -= 25; } if (playerTraits.includes("Overconfident")) { modifier -= 15; } if (playerTraits.includes("Stubborn")) { modifier -= 15; } if (playerTraits.includes("Competitive")) { modifier -= 10; } } return modifier; }>> <<set setup.attemptTraitTheft = function(traitName, suspect, isPhysical, previewOnly) { var v = State.variables; var traitValue = setup.getTraitValue('mental', traitName) || setup.getTraitValue('skill', traitName) || setup.getTraitValue('physical', traitName); var detectionChance = isPhysical ? 50 : 30; if (traitValue > 100) { detectionChance += 30; } else if (traitValue > 50) { detectionChance += 20; } else if (traitValue > 25) { detectionChance += 10; } if (isPhysical) { detectionChance += 25; } if (v.context && v.context.witnesses === "Many") { detectionChance += 20; } else if (v.context && v.context.witnesses === "Moderate") { detectionChance += 15; } else if (v.context && v.context.witnesses === "Few") { detectionChance += 10; } if (v.context && v.context.nearbyOfficers > 0) { detectionChance += v.context.nearbyOfficers * 20; } var sheriffNearby = false; if (v.context && v.context.nearbyOfficers > 0) { sheriffNearby = Math.random() * 100 < (v.context.nearbyOfficers * 20); } if (sheriffNearby) { detectionChance = 100; } var playerTraits = (v.physicalTraits || []).concat(v.mentalTraits || []).concat(v.skills || []); if (playerTraits.includes("Stealth")) { detectionChance -= 20; } if (playerTraits.includes("Sly")) { detectionChance -= 15; } if (playerTraits.includes("Sneaky")) { detectionChance -= 15; } if (playerTraits.includes("Deceitful")) { detectionChance -= 10; } if (playerTraits.includes("Quick")) { detectionChance -= 10; } if (playerTraits.includes("Quick Reflexes")) { detectionChance -= 15; } if (playerTraits.includes("Clumsy")) { detectionChance += 20; } if (playerTraits.includes("Awkward")) { detectionChance += 15; } if (playerTraits.includes("Nervous")) { detectionChance += 15; } if (playerTraits.includes("Honest")) { detectionChance += 25; } if (playerTraits.includes("Shy")) { detectionChance += 10; } if (playerTraits.includes("Unlucky") || playerTraits.includes("Bad Luck")) { detectionChance += 20; } if (playerTraits.includes("Lucky")) { detectionChance -= 20; } var playerDex = Math.min(setup.getTotalStat('dexterity'), 100); var dexBonus = playerDex * 0.25; detectionChance -= dexBonus; if (setup.skillTree && setup.skillTree.getEffect) { var skillTreeOnDutyBonus = setup.skillTree.getEffect("onDutyStealBonus"); if (skillTreeOnDutyBonus > 0) { detectionChance -= skillTreeOnDutyBonus; } } if (detectionChance > 90) { detectionChance = 90; } if (detectionChance < 10) { detectionChance = 10; } if (previewOnly) { return { success: false, detectionChance: detectionChance, traitValue: traitValue, sheriffNearby: false }; } var caught = Math.random() * 100 < detectionChance; return { success: !caught, detectionChance: detectionChance, traitValue: traitValue, sheriffNearby: sheriffNearby }; }>> <</silently>> <</nobr>>
<<nobr>> <!-- Safety check - redirect if no crime data --> <<if !$suspect || !$performance || !$crimeInProgress>> <<if $lastLocation && $lastLocation.indexOf("Patrol") === 0>> <<goto $lastLocation>> <<else>> <<goto "PatrolDowntown">> <</if>> <</if>> <div class="crime-scene"> <!-- Crime Resolved - Show Results --> <<if !$performance.outcomeScore || $performance.outcomeScore === 0>> <<set $performance.outcomeScore = $suspect.currentState === "subdued" && $suspect.apprehended ? 100 : 0>> <</if>> <!-- Special handling for officer down --> <<if $suspect.currentState === "officer_down">> <<set $performance.outcomeScore = 0>> <<set $performance.appropriateness = 0>> <<set $performance.procedureScore = 0>> <</if>> <!-- Calculate Final Score --> <<set $finalScore = Math.round( ($performance.appropriateness * 0.4) + ($performance.procedureScore * 0.3) + ($performance.outcomeScore * 0.3) )>> <<if $performance.traitTheftDetected>> <<set $finalScore = 0>> <</if>> <h1 class="crime-header">📊 Performance Review: <<print $crimeType>></h1> <div class="performance-box"> <h3 class="score-header">Final Score: <span style="color: <<if $finalScore >= 70>>#51cf66<<elseif $finalScore >= 50>>#ffd43b<<else>>#ff6b6b<</if>>;"><<print $finalScore>>/100</span></h3> <div class="score-breakdown"> <div class="score-item"> <strong>Force Appropriateness:</strong> <span style="color: <<if $performance.appropriateness >= 70>>#51cf66<<elseif $performance.appropriateness >= 50>>#ffd43b<<else>>#ff6b6b<</if>>;"><<print Math.round($performance.appropriateness)>>/100</span> </div> <div class="score-item"> <strong>Procedure:</strong> <span style="color: <<if $performance.procedureScore >= 70>>#51cf66<<elseif $performance.procedureScore >= 50>>#ffd43b<<else>>#ff6b6b<</if>>;"><<print Math.round($performance.procedureScore)>>/100</span> </div> <div class="score-item"> <strong>Outcome:</strong> <span style="color: <<if $performance.outcomeScore >= 70>>#51cf66<<elseif $performance.outcomeScore >= 50>>#ffd43b<<else>>#ff6b6b<</if>>;"><<print Math.round($performance.outcomeScore)>>/100</span> </div> </div> <<if $suspectCount > 1>> <div style="background: rgba(52, 152, 219, 0.2); padding: 10px; border-radius: 6px; margin: 15px 0; border: 2px solid #3498db;"> <p style="color: #3498db; margin: 0; text-align: center;"> <strong>Suspects Involved:</strong> <<print $suspectCount>> </p> </div> <</if>> <h4 class="actions-header">Actions Taken:</h4> <div class="actions-list"> <<if $performance.actions.length > 0>> <<for _action range $performance.actions>> <div class="action-taken">• <<print _action>></div> <</for>> <<else>> <div class="action-taken">• No actions recorded</div> <</if>> </div> <<if $performance.warnings.length > 0>> <h4 class="warnings-header">⚠️ Issues & Concerns:</h4> <div class="warnings-list"> <<for _warning range $performance.warnings>> <div class="warning-item">• <<print _warning>></div> <</for>> </div> <</if>> <<set _rating = $finalScore >= 90 ? "Exemplary" : $finalScore >= 70 ? "Good" : $finalScore >= 50 ? "Acceptable" : $finalScore >= 30 ? "Poor" : "Terrible">> <<set _ratingClass = $finalScore >= 90 ? "rating-excellent" : $finalScore >= 70 ? "rating-good" : $finalScore >= 50 ? "rating-acceptable" : "rating-poor">> <div style="margin-top: 20px; padding: 15px; background: rgba(255,255,255,0.05); border-radius: 8px;"> <h4 class="<<print _ratingClass>>" style="margin: 0; text-align: center; font-size: 24px;">Rating: <<print _rating>></h4> <<if $finalScore < 30>> <p style="color: #ff6b6b; text-align: center; margin-top: 10px;"> This performance will be flagged for review by Internal Affairs. </p> <<elseif $finalScore >= 90>> <p style="color: #51cf66; text-align: center; margin-top: 10px;"> Outstanding work, Officer. This will be noted in your record. </p> <!-- 5% chance to gain a positive trait --> <<if Math.random() * 100 < 5>> <<set _goodTraits = ["Brave", "Confident", "Disciplined", "Patient", "Calm", "Analytical", "Perceptive", "Diplomatic", "Assertive", "Humble", "Wise", "Cautious"]>> <<set _availableTraits = _goodTraits.filter(function(t) { return !State.variables.mentalTraits.includes(t); })>> <<if _availableTraits.length > 0>> <<set _gainedTrait = _availableTraits[Math.floor(Math.random() * _availableTraits.length)]>> <<run $mentalTraits.push(_gainedTrait)>> <div style="background: #000; padding: 15px; border-radius: 8px; margin-top: 15px; border: 3px solid #51cf66;"> <h4 style="color: #51cf66; margin: 0 0 10px 0; text-align: center;">✨ TRAIT GAINED ✨</h4> <p style="color: #51cf66; text-align: center; margin: 0;"> Your exemplary performance has earned you the trait: <strong style="color: #ffd700;"><<print _gainedTrait>></strong> </p> </div> <</if>> <</if>> <</if>> <<if $performance.wentInAlone && ($crimeTier >= 3 || $suspectCount > 1)>> <p style="color: #ff0000; text-align: center; margin-top: 10px; font-weight: bold;"> WARNING: Engaging high-threat situations alone is against protocol and endangers officer safety. </p> <</if>> </div> </div> <!-- Outcome-Specific Messages --> <<if $suspect.currentState === "officer_down">> <div class="failure-box"> <h3 class="failure-header">🚨 OFFICER DOWN - CRITICAL FAILURE 🚨</h3> <p class="failure-text"> You were completely overpowered in this incident. This represents a catastrophic failure in judgment and procedure. You will be required to undergo remedial training before returning to active duty. </p> </div> <<elseif $suspect.currentState === "escaped">> <div class="failure-box"> <h3 class="failure-header">❌ Suspect Escaped</h3> <p class="failure-text"> The suspect<<if $suspectCount > 1>>s<</if>> got away. This incident will remain unsolved, and the perpetrator<<if $suspectCount > 1>>s remain<</if>> at large. </p> </div> <<elseif $suspect.currentState === "subdued" && $suspect.apprehended>> <div class="success-box"> <h3 class="success-header">✅ Arrest Successful</h3> <p class="success-text"> The suspect<<if $suspectCount > 1>>s have<<else>> has<</if>> been apprehended and will face charges for <<print $crimeType>>. </p> </div> <</if>> <!-- Display Lost Traits from Punishment --> <<if $lostTraitsFromPunishment && $lostTraitsFromPunishment.length > 0>> <div style="background: #000; padding: 20px; border-radius: 10px; margin: 20px 0; border: 3px solid #8b0000;"> <h3 style="color: #ff0000; margin: 0 0 15px 0; text-align: center;">💔 TRAITS LOST AS PUNISHMENT</h3> <p style="color: #ff6b6b; margin-bottom: 15px;"> The shame and trauma of being caught has cost you dearly. You have lost: </p> <ul style="color: #ff6b6b; background: rgba(139, 0, 0, 0.2); padding: 15px; border-radius: 6px; border: 2px solid #8b0000;"> <<for _lostTrait range $lostTraitsFromPunishment>> <li style="margin: 5px 0;"><strong><<print _lostTrait>></strong></li> <</for>> </ul> <p style="color: #ff6b6b; font-style: italic; margin-top: 15px; text-align: center;"> These traits represent the personal cost of your corruption being exposed. </p> </div> <<set $lostTraitsFromPunishment = []>> <</if>> <<link "<div class='action-button button-return'>Return to Patrol</div>">> <<set $crimeDetected = false>> <<set $currentCrime = null>> <<set $crimeInProgress = false>> <<unset $suspect>> <<unset $context>> <<unset $performance>> <<unset $crimeStage>> <<unset $crimeDesc>> <<unset $suspectCount>> <<unset $requiresBackup>> <<if $lastLocation && $lastLocation.indexOf("Patrol") === 0>> <<goto $lastLocation>> <<else>> <<goto "PatrolDowntown">> <</if>> <</link>> </div> <</nobr>>
<<nobr>> <!-- Automatically gain Corrupt trait for attempting officer crime --> <<if !$mentalTraits.includes("Corrupt")>> <<run $mentalTraits.push("Corrupt")>> <<set $gainedCorruptTrait = true>> <<else>> <<set $gainedCorruptTrait = false>> <</if>> <!-- ===== SKILL TREE: Get On-Duty Steal Bonus for display ===== --> <<set _onDutyStealBonus = setup.skillTree.getEffect("onDutyStealBonus")>> <div class="crime-scene"> <h1 class="crime-header" style="color: #dc3545;">🚨 ILLEGAL ACTION - TRAIT THEFT</h1> <<if $gainedCorruptTrait>> <div class="corruption-gained-box"> <h3 style="color: #ff0000; margin: 0 0 10px 0; text-align: center;">⚠️ YOU HAVE BECOME CORRUPT ⚠️</h3> <p style="color: #fff; text-align: center; margin: 0;"> By choosing to abuse your power as a police officer, you have gained the <strong style="color: #ffd700;">"Corrupt"</strong> trait. </p> <p style="color: #ff6b6b; text-align: center; font-size: 14px; margin: 10px 0 0 0;"> This permanent mark will affect how others perceive you and how you view the law. </p> </div> <</if>> <div class="officer-crime-box"> <h2 style="color: #ff0000; margin: 0 0 15px 0;">Select ONE Trait to Steal</h2> <p style="color: #fff; margin-bottom: 20px;"> You are about to commit a serious crime. Choose carefully - you only get one attempt. </p> <!-- ===== SKILL TREE: On-Duty Steal Bonus Display ===== --> <<if _onDutyStealBonus > 0>> <div style="background: rgba(156, 39, 176, 0.2); padding: 10px; border-radius: 6px; margin-bottom: 15px; border: 2px solid #9C27B0;"> <p style="color: #9C27B0; margin: 0; font-size: 14px; text-align: center;"> ⭐ <strong>Skill Tree Active:</strong> -<<print _onDutyStealBonus>>% detection chance on all thefts </p> </div> <</if>> <!-- Physical Traits --> <<if $suspect.traits.physical.length > 0>> <div class="theft-trait-section"> <h3 style="color: #51cf66; margin: 15px 0 10px 0;">Physical Traits</h3> <p style="color: #ff6b6b; font-size: 14px; margin-bottom: 10px;"> ⚠️ Physical trait theft is extremely difficult and obvious - MUCH higher detection chance! </p> <div class="theft-trait-grid"> <<for _trait range $suspect.traits.physical>> <<capture _trait>> <<if !setup.unstealableTraits.includes(_trait)>> <<set _value = setup.getTraitValue('physical', _trait)>> <<set _detectionResult = setup.attemptTraitTheft(_trait, $suspect, true, true)>> <<set _detectionChance = Math.round(_detectionResult.detectionChance)>> <div class="theft-trait-option"> <<link `"<div class='theft-trait-button theft-physical'>" + _trait + " (" + _value + ")<br><span style='font-size: 12px; color: #ff6b6b;'>Detection: " + _detectionChance + "%</span></div>"`>> <<set $attemptedTrait = _trait>> <<set $attemptedTraitType = "physical">> <<set $theftResult = setup.attemptTraitTheft(_trait, $suspect, true, false)>> <<goto "OfficerCrimeResult">> <</link>> </div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- Mental Traits --> <<if $suspect.traits.mental.length > 0>> <div class="theft-trait-section"> <h3 style="color: #ff6b6b; margin: 15px 0 10px 0;">Mental Traits</h3> <div class="theft-trait-grid"> <<for _trait range $suspect.traits.mental>> <<capture _trait>> <<if !setup.unstealableTraits.includes(_trait)>> <<set _value = setup.getTraitValue('mental', _trait)>> <<set _detectionResult = setup.attemptTraitTheft(_trait, $suspect, false, true)>> <<set _detectionChance = Math.round(_detectionResult.detectionChance)>> <div class="theft-trait-option"> <<link `"<div class='theft-trait-button theft-mental'>" + _trait + " (" + _value + ")<br><span style='font-size: 12px; color: #ffd43b;'>Detection: " + _detectionChance + "%</span></div>"`>> <<set $attemptedTrait = _trait>> <<set $attemptedTraitType = "mental">> <<set $theftResult = setup.attemptTraitTheft(_trait, $suspect, false, false)>> <<goto "OfficerCrimeResult">> <</link>> </div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- Skills --> <<if $suspect.traits.skills.length > 0>> <div class="theft-trait-section"> <h3 style="color: #ffd43b; margin: 15px 0 10px 0;">Skills</h3> <div class="theft-trait-grid"> <<for _trait range $suspect.traits.skills>> <<capture _trait>> <<if !setup.unstealableTraits.includes(_trait)>> <<set _value = setup.getTraitValue('skill', _trait)>> <<set _detectionResult = setup.attemptTraitTheft(_trait, $suspect, false, true)>> <<set _detectionChance = Math.round(_detectionResult.detectionChance)>> <div class="theft-trait-option"> <<link `"<div class='theft-trait-button theft-skill'>" + _trait + " (" + _value + ")<br><span style='font-size: 12px; color: #4dabf7;'>Detection: " + _detectionChance + "%</span></div>"`>> <<set $attemptedTrait = _trait>> <<set $attemptedTraitType = "skill">> <<set $theftResult = setup.attemptTraitTheft(_trait, $suspect, false, false)>> <<goto "OfficerCrimeResult">> <</link>> </div> <</if>> <</capture>> <</for>> </div> </div> <</if>> <div style="margin-top: 30px; padding-top: 20px; border-top: 2px solid #666;"> <p style="color: #ffd43b; text-align: center; margin-bottom: 15px;"> You can still abandon this theft and return to processing the arrest. </p> <<link "<div class='action-button button-return'>Abandon This Theft</div>">> <<set $suspect.traitTheftAttempted = false>> <<goto "CrimeScene">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div class="crime-scene"> <<if $theftResult.success>> <!-- Successful Theft --> <div style="background: rgba(40, 167, 69, 0.2); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #28a745;"> <h2 style="color: #28a745; margin: 0 0 15px 0; text-align: center;">✅ Theft Successful (For Now)</h2> <p style="color: #e0e0e0; font-size: 16px; margin-bottom: 10px;"> You successfully stole the trait "<span style="color: #ffd700; font-weight: bold;"><<print $attemptedTrait>></span>" from the suspect without being immediately detected. </p> <p style="color: #ffeb3b; font-size: 14px; margin-bottom: 10px;"> Detection risk was <<print Math.round($theftResult.detectionChance)>>%. You managed to avoid detection this time. </p> <p style="color: #fff; font-size: 14px; margin-bottom: 15px;"> Trait value: <strong><<print $theftResult.traitValue>></strong> </p> <!-- ===== SKILL TREE: On-Duty Steal Bonus Display ===== --> <<set _onDutyStealBonus = setup.skillTree.getEffect("onDutyStealBonus")>> <<if _onDutyStealBonus > 0>> <p style="color: #9C27B0; font-size: 14px; margin-bottom: 10px;"> ⭐ <strong>Skill Tree Bonus:</strong> -<<print _onDutyStealBonus>>% detection chance </p> <</if>> <!-- Check which traits helped/hurt --> <<set _playerTraits = ($physicalTraits || []).concat($mentalTraits || []).concat($skills || [])>> <<if _playerTraits.includes("Stealth") || _playerTraits.includes("Sly") || _playerTraits.includes("Quick Reflexes")>> <p style="color: #90ee90; font-style: italic; margin-top: 10px; font-size: 14px;"> Your <<if _playerTraits.includes("Stealth")>>stealthy nature<<elseif _playerTraits.includes("Sly")>>sly cunning<<else>>quick reflexes<</if>> helped you pull this off without being noticed. </p> <</if>> <<if !$stolenTraitsOnDuty>><<set $stolenTraitsOnDuty = []>><</if>> <!-- Log stolen trait for on-duty tracking --> <<set _stolenTraitRecord = { trait: $attemptedTrait, value: $theftResult.traitValue, type: $attemptedTraitType, source: $crimeType + " Suspect", date: $dayNumber, location: $lastLocation }>> <<run $stolenTraitsOnDuty.push(_stolenTraitRecord)>> <!-- Add trait to appropriate array with conflict checking --> <<set _allPlayerTraits = $physicalTraits.concat($mentalTraits)>> <<set _conflictTrait = setup.getConflictingTrait($attemptedTrait, _allPlayerTraits)>> <<if _conflictTrait>> <!-- Remove conflicting trait first --> <<if $physicalTraits.includes(_conflictTrait)>> <<run $physicalTraits.delete(_conflictTrait)>> <<elseif $mentalTraits.includes(_conflictTrait)>> <<run $mentalTraits.delete(_conflictTrait)>> <</if>> <<set _stolenTraitRecord.replaced = _conflictTrait>> <</if>> <!-- Safety check: don't add trait if blocked by transformation --> <<set _blockedByTransform = setup.isTraitBlockedByTransformation && (setup.isTraitBlockedByTransformation($attemptedTrait, "physical") || setup.isTraitBlockedByTransformation($attemptedTrait, "mental"))>> <<if !_blockedByTransform>> <<if $attemptedTraitType === "physical">> <<if !$physicalTraits.includes($attemptedTrait)>> <<run $physicalTraits.push($attemptedTrait)>> <</if>> <<elseif $attemptedTraitType === "mental">> <<if !$mentalTraits.includes($attemptedTrait)>> <<run $mentalTraits.push($attemptedTrait)>> <</if>> <<elseif $attemptedTraitType === "skill">> <<if !$skills.includes($attemptedTrait)>> <<run $skills.push($attemptedTrait)>> <</if>> <</if>> <</if>><!-- End transformation block check --> <div style="background: rgba(220, 53, 69, 0.3); padding: 20px; border-radius: 10px; margin-top: 20px; border: 2px solid #dc3545;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0; text-align: center;">⚠️ CONSEQUENCES IF CAUGHT</h3> <p style="color: #fff; font-size: 15px; margin-bottom: 10px;"> You now have <strong style="color: #ffd700;"><<print $stolenTraitsOnDuty.length>></strong> stolen trait<<if $stolenTraitsOnDuty.length !== 1>>s<</if>> from suspects while on duty. </p> <p style="color: #e0e0e0; font-size: 14px; margin-top: 15px; margin-bottom: 10px;"> If caught, you will: </p> <ul style="color: #ffcccb; margin: 10px 0; padding-left: 25px; line-height: 1.6;"> <li>Be immediately <strong>FIRED</strong> from the police force</li> <li>Lose <strong>ALL</strong> traits stolen while on duty</li> <li>Face a <strong style="color: #ffd700;">$<<print $stolenTraitsOnDuty.length * 500>></strong> fine (or lose 5 random positive traits)</li> </ul> <<if $stolenTraitsOnDuty.length >= 3>> <p style="color: #ff0000; font-weight: bold; margin-top: 15px; font-size: 16px; text-align: center; background: rgba(0,0,0,0.3); padding: 10px; border-radius: 6px;"> 🚨 WARNING: Multiple stolen traits means a $<<print $stolenTraitsOnDuty.length * 500>> fine if caught! </p> <</if>> </div> </div> <<link "<div class='action-button button-continue'>Continue</div>">> <<goto "CrimeScene">> <</link>> <<else>> <!-- Caught! Redirect to confrontation --> <<goto "OfficerCrimeCaught">> <</if>> </div> <</nobr>>
<<nobr>> <div class="crime-scene"> <h1 class="crime-header" style="color: #ff0000;">🚨 YOU'VE BEEN CAUGHT!</h1> <<if $theftResult.sheriffNearby>> <div class="sheriff-caught-box" style="background: rgba(139, 0, 0, 0.8); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ff0000;"> <h3 style="color: #fff; margin: 0 0 15px 0; text-align: center;">👮 THE SHERIFF IS HERE</h3> <p style="color: #fff; margin: 0; font-size: 16px; line-height: 1.6;"> The Sheriff witnessed you attempting to steal "<<print $attemptedTrait>>" from the suspect. They're calling for backup right now. You have seconds to decide what to do. </p> </div> <<else>> <div style="background: rgba(220, 53, 69, 0.3); padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #dc3545;"> <h3 style="color: #dc3545; margin: 0 0 15px 0; text-align: center;">⚠️ OFFICER APPROACHING</h3> <p style="color: #fff; margin: 0 0 10px 0; font-size: 16px;"> You were caught attempting to steal the trait "<<print $attemptedTrait>>" from the apprehended suspect! </p> <p style="color: #fff; margin: 0; font-size: 14px;"> Detection chance was <<print Math.round($theftResult.detectionChance)>>%. An officer saw what you were doing and is approaching rapidly. </p> <!-- Explain what went wrong --> <<set _playerTraits = ($physicalTraits || []).concat($mentalTraits || []).concat($skills || [])>> <<if _playerTraits.includes("Clumsy")>> <p style="color: #ff6b6b; font-style: italic; margin-top: 10px;"> Your clumsiness gave you away - you fumbled the extraction. </p> <<elseif _playerTraits.includes("Honest")>> <p style="color: #ff6b6b; font-style: italic; margin-top: 10px;"> Your honest demeanor made the deception obvious. </p> <<elseif _playerTraits.includes("Nervous")>> <p style="color: #ff6b6b; font-style: italic; margin-top: 10px;"> Your nervous behavior drew suspicion. </p> <<elseif _playerTraits.includes("Awkward")>> <p style="color: #ff6b6b; font-style: italic; margin-top: 10px;"> Your awkwardness made the theft obvious. </p> <<elseif $context.nearbyOfficers > 0>> <p style="color: #ff6b6b; font-style: italic; margin-top: 10px;"> With <<print $context.nearbyOfficers>> officer<<if $context.nearbyOfficers > 1>>s<</if>> nearby, someone noticed. </p> <<else>> <p style="color: #ff6b6b; font-style: italic; margin-top: 10px;"> A witness reported you immediately. </p> <</if>> </div> <</if>> <div style="background: rgba(255, 193, 7, 0.2); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107;"> <h3 style="color: #ffc107; margin: 0 0 15px 0; text-align: center;">⚡ CHOOSE QUICKLY</h3> <p style="color: #fff; text-align: center; margin: 0;"> You have split seconds to decide. Do you flee the scene or stay and face the consequences? </p> </div> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;"> <!-- Option 1: Flee --> <div style="background: rgba(139, 0, 0, 0.3); padding: 20px; border-radius: 12px; border: 3px solid #8b0000;"> <h3 style="color: #ff0000; margin: 0 0 15px 0; text-align: center;">🏃 FLEE THE SCENE</h3> <p style="color: #fff; font-size: 14px; margin-bottom: 15px;"> Run away from the scene. This will make things MUCH worse: </p> <ul style="color: #ff6b6b; margin-bottom: 15px; padding-left: 20px;"> <li>Automatic termination from police force</li> <li>Become a <strong style="color: #ff0000;">Criminal</strong></li> <li>Significantly higher fines and penalties</li> <li>Warrant for your arrest</li> <li>Much harder to trade (Criminal: -20% trade chance)</li> </ul> <<link "<div style='background: #8b0000; color: #fff; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>🏃 FLEE NOW</div>">> <<goto "OfficerCrimeFlee">> <</link>> </div> <!-- Option 2: Face Consequences --> <div style="background: rgba(52, 152, 219, 0.3); padding: 20px; border-radius: 12px; border: 3px solid #3498db;"> <h3 style="color: #3498db; margin: 0 0 15px 0; text-align: center;">⚖️ FACE THE CONSEQUENCES</h3> <p style="color: #fff; font-size: 14px; margin-bottom: 15px;"> Stay and accept responsibility. You'll still be fired, but the penalties will be lighter: </p> <ul style="color: #4dabf7; margin-bottom: 15px; padding-left: 20px;"> <li>Immediate termination from police force</li> <li>All stolen traits confiscated</li> <li>Choose: Pay fine, accept debt, or lose 5 traits</li> <li>No criminal record (if you cooperate)</li> </ul> <<link "<div style='background: #3498db; color: #fff; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>⚖️ ACCEPT PUNISHMENT</div>">> <<goto "OfficerCrimePunishment">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div class="crime-scene"> <h1 class="crime-header" style="color: #ff0000;">🏃 YOU FLED THE SCENE</h1> <div class="failure-box"> <h2 class="failure-header">🚨 FUGITIVE STATUS</h2> <p class="failure-text"> You ran from the scene, abandoning your badge and your career. The entire police department is now looking for you. </p> </div> <!-- IMMEDIATE TERMINATION --> <div class="fired-box"> <h3 class="fired-header">❌ TERMINATED & WANTED</h3> <p style="color: #fff; font-weight: bold; font-size: 18px;"> You are FIRED from the Sunfish City Police Department and now have an active warrant for your arrest. </p> </div> <!-- CRIMINAL JOB ASSIGNED --> <div style="background: rgba(139, 0, 0, 0.4); padding: 20px; border-radius: 12px; margin: 20px 0; border: 3px solid #ff0000;"> <h3 style="color: #ff0000; margin: 0 0 15px 0;">🔴 YOU ARE NOW A CRIMINAL</h3> <p style="color: #fff; margin-bottom: 10px;"> Your job has been changed to "Criminal". This will make your life significantly harder: </p> <ul style="color: #ff6b6b;"> <li><strong>-150 value</strong> on all trades (people don't trust criminals)</li> <li><strong>-20% trade success chance</strong> (decreased from normal)</li> <li>Active warrant - you can be arrested at any time</li> <li>Higher fines and penalties for everything</li> </ul> </div> <!-- CONFISCATE STOLEN TRAITS --> <<if $stolenTraitsOnDuty && $stolenTraitsOnDuty.length > 0>> <div style="background: rgba(255, 107, 107, 0.3); padding: 20px; border-radius: 12px; margin: 20px 0; border: 3px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">⚖️ STOLEN TRAITS CONFISCATED</h3> <p style="color: #fff; margin-bottom: 15px;"> All traits stolen while on duty have been magically confiscated: </p> <ul class="stolen-list"> <<for _stolen range $stolenTraitsOnDuty>> <li> <strong><<print _stolen.trait>></strong> (<<print _stolen.type>>, Value: <<print _stolen.value>>) </li> <</for>> </ul> <!-- Remove stolen traits --> <<for _stolen range $stolenTraitsOnDuty>> <<if _stolen.type === "physical">> <<run $physicalTraits.delete(_stolen.trait)>> <<elseif _stolen.type === "mental">> <<run $mentalTraits.delete(_stolen.trait)>> <<elseif _stolen.type === "skill">> <<run $skills.delete(_stolen.trait)>> <</if>> <</for>> <<set $stolenTraitsOnDuty = []>> </div> <</if>> <!-- Set Criminal Job and Clean Up --> <<set $jobs = ["Criminal"]>> <<set $onPatrol = false>> <<set $crimeDetected = false>> <<set $currentCrime = null>> <<set $crimeInProgress = false>> <<if $performance>><<set $performance.traitTheftDetected = true>><</if>> <<unset $suspect>> <<unset $context>> <<unset $performance>> <<unset $crimeStage>> <<unset $crimeDesc>> <!-- Determine where to send the player --> <<set _returnLocation = "Downtown">> <<if $lastLocation>> <<if $lastLocation === "PoliceBreakRoom">> <<set _returnLocation = "PoliceDepartment">> <<elseif $lastLocation === "PatrolDowntown" || $lastLocation === "CrimeScene">> <<set _returnLocation = "Downtown">> <<elseif $lastLocation === "PatrolBusinessDistrict">> <<set _returnLocation = "BusinessDistrict">> <<elseif $lastLocation === "PatrolRedLightDistrict">> <<set _returnLocation = "RedLightDistrict">> <<elseif $lastLocation === "PatrolDocks">> <<set _returnLocation = "Docks">> <<elseif $lastLocation === "PatrolAlleyway">> <<set _returnLocation = "Alleyway">> <<elseif $lastLocation === "PatrolSeabassPark">> <<set _returnLocation = "SeabassPark">> <<elseif $lastLocation === "PatrolOutskirts">> <<set _returnLocation = "Outskirts">> <</if>> <</if>> <div style="background: rgba(52, 152, 219, 0.3); padding: 20px; border-radius: 12px; margin: 20px 0; border: 3px solid #3498db;"> <h3 style="color: #3498db; margin: 0 0 15px 0; text-align: center;">🏃 ESCAPE</h3> <p style="color: #fff; text-align: center; margin-bottom: 15px;"> You manage to slip away in the chaos. You're no longer a police officer - just another person in Sunfish City. But now you have a criminal record and an active warrant. </p> <<link "<div style='background: #3498db; color: #fff; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Continue</div>">> <<goto _returnLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <div class="crime-scene"> <h1 class="crime-header" style="color: #dc3545;">⚖️ FACING JUSTICE</h1> <div class="failure-box"> <h2 class="failure-header">🚨 CAUGHT IN THE ACT</h2> <p class="failure-text"> You chose to stay and face the consequences of your actions. The department appreciates your cooperation, but you're still being terminated. </p> </div> <!-- IMMEDIATE TERMINATION --> <div class="fired-box"> <h3 class="fired-header">❌ IMMEDIATE TERMINATION</h3> <p style="color: #fff; font-weight: bold; font-size: 18px;"> You have been FIRED from the Sunfish City Police Department. </p> <p style="color: #ff6b6b; margin-top: 10px;"> All police credentials revoked. You are no longer authorized to patrol or carry a badge. </p> </div> <!-- STOLEN TRAITS CONFISCATED --> <<if !$stolenTraitsOnDuty>> <<set $stolenTraitsOnDuty = []>> <</if>> <<if $stolenTraitsOnDuty.length > 0>> <div style="background: rgba(255, 107, 107, 0.3); padding: 20px; border-radius: 12px; margin: 20px 0; border: 3px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">⚖️ CONFISCATED TRAITS</h3> <p style="color: #fff; margin-bottom: 15px;"> All traits stolen while on duty have been confiscated and returned: </p> <ul class="stolen-list"> <<for _stolen range $stolenTraitsOnDuty>> <li> <strong><<print _stolen.trait>></strong> (<<print _stolen.type>>, Value: <<print _stolen.value>>) - From <<print _stolen.source>> on Day <<print _stolen.date>> </li> <</for>> </ul> <!-- Remove all stolen traits from player --> <<for _stolen range $stolenTraitsOnDuty>> <<if _stolen.type === "physical">> <<run $physicalTraits.delete(_stolen.trait)>> <<elseif _stolen.type === "mental">> <<run $mentalTraits.delete(_stolen.trait)>> <<elseif _stolen.type === "skill">> <<run $skills.delete(_stolen.trait)>> <</if>> <</for>> <p style="color: #ff6b6b; font-weight: bold; margin-top: 15px;"> You have lost <<print $stolenTraitsOnDuty.length>> stolen trait<<if $stolenTraitsOnDuty.length !== 1>>s<</if>>. </p> </div> <</if>> <!-- PUNISHMENT OPTIONS --> <<set _fine = Math.max($stolenTraitsOnDuty.length, 1) * 5000>> <<set _debtFine = Math.max($stolenTraitsOnDuty.length, 1) * 10000>> <<set _canPayFine = $money >= _fine>> <div style="background: rgba(139, 0, 0, 0.3); padding: 20px; border-radius: 12px; margin: 20px 0; border: 3px solid #8b0000;"> <h3 style="color: #ff0000; margin: 0 0 15px 0; text-align: center;">⚠️ CHOOSE YOUR PUNISHMENT ⚠️</h3> <p style="color: #fff; text-align: center; margin-bottom: 20px;"> Because you cooperated, you avoid a criminal record. Choose one: </p> <div style="display: grid; grid-template-columns: 1fr; gap: 15px;"> <!-- Option 1: Pay Fine --> <div style="background: rgba(255, 193, 7, 0.2); padding: 15px; border-radius: 8px; border: 2px solid #ffc107;"> <h4 style="color: #ffc107; margin: 0 0 10px 0;">💰 Pay Fine: $<<print _fine>></h4> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;"> Pay $5,000 per stolen trait to avoid jail time </p> <<if _canPayFine>> <p style="color: #51cf66; font-size: 12px; margin-bottom: 10px;"> ✓ You have enough (Current: $<<print $money>>) </p> <<capture _fine>> <<set _payLabel = "<div style='background: #ffc107; color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Pay $" + _fine + " Fine</div>">> <<link _payLabel>> <<set $money -= _fine>> <<set $currentJob = "Unemployed">> <<set $jobs = []>> <<set $onPatrol = false>> <<set $stolenTraitsOnDuty = []>> <<if $performance>><<set $performance.traitTheftDetected = true>><</if>> <<set $crimeDetected = false>> <<set $currentCrime = null>> <<set $crimeInProgress = false>> <<unset $suspect>> <<unset $context>> <<unset $performance>> <<unset $crimeStage>> <<unset $crimeDesc>> <<unset $suspectCount>> <<unset $requiresBackup>> <<goto "Downtown">> <</link>> <</capture>> <<else>> <p style="color: #ff6b6b; font-size: 12px; margin-bottom: 10px;"> ✗ Insufficient funds (Need: $<<print _fine>>, You have: $<<print $money>>) </p> <div style='background: #444; color: #777; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed; opacity: 0.5;'> Cannot Afford Fine </div> <</if>> </div> <!-- Option 2: Take on Debt --> <div style="background: rgba(220, 53, 69, 0.2); padding: 15px; border-radius: 8px; border: 2px solid #dc3545;"> <h4 style="color: #dc3545; margin: 0 0 10px 0;">📋 Accept Debt: $<<print _debtFine>></h4> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;"> Take on debt instead of paying immediately ($10,000 per stolen trait). All future income will go towards paying this debt until it's cleared. </p> <p style="color: #ff6b6b; font-size: 13px; margin-bottom: 10px; font-weight: bold;"> ⚠️ WARNING: You will not be able to keep any money earned until this debt is fully paid off! </p> <<capture _debtFine>> <<set _debtLabel = "<div style='background: #dc3545; color: #fff; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept $" + _debtFine + " Debt</div>">> <<link _debtLabel>> <<if !$debt>><<set $debt = 0>><</if>> <<set $debt += _debtFine>> <<set $currentJob = "Unemployed">> <<set $jobs = []>> <<set $onPatrol = false>> <<set $stolenTraitsOnDuty = []>> <<if $performance>><<set $performance.traitTheftDetected = true>><</if>> <<set $crimeDetected = false>> <<set $currentCrime = null>> <<set $crimeInProgress = false>> <<unset $suspect>> <<unset $context>> <<unset $performance>> <<unset $crimeStage>> <<unset $crimeDesc>> <<unset $suspectCount>> <<unset $requiresBackup>> <<goto "Downtown">> <</link>> <</capture>> </div> <!-- Option 3: Go to Jail --> <div style="background: rgba(102, 102, 102, 0.2); padding: 15px; border-radius: 8px; border: 2px solid #666;"> <h4 style="color: #aaa; margin: 0 0 10px 0;">🔒 Go to Jail</h4> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;"> Serve time instead of paying fines. Time served varies based on severity. </p> <<link "<div style='background: #666; color: #fff; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept Jail Time</div>">> <<set $currentJob = "Unemployed">> <<set $jobs = []>> <<set $onPatrol = false>> <<set $stolenTraitsOnDuty = []>> <<if $performance>><<set $performance.traitTheftDetected = true>><</if>> <<set $crimeDetected = false>> <<set $currentCrime = null>> <<set $crimeInProgress = false>> <<unset $suspect>> <<unset $context>> <<unset $performance>> <<unset $crimeStage>> <<unset $crimeDesc>> <<unset $suspectCount>> <<unset $requiresBackup>> <<goto "Jail">> <</link>> </div> </div> </div> </div> <</nobr>>
<<nobr>> <<set _canSteal = setup.canPlayerSteal()>> <<set _locationData = setup.crimeLocations[$currentCrimeLocation]>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #e74c3c; text-align: center; margin: 10px 0; font-size: 28px;">🦹 Criminal Activities</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">_locationData.name</h2> <<if $crimeSystem.activeWarrant>> <div style="background: linear-gradient(135deg, #c0392b 0%, #e74c3c 100%); color: white; padding: 12px; border-radius: 5px; margin-bottom: 15px; font-weight: bold; text-align: center; font-size: 15px;"> ⚠️ <b>ACTIVE WARRANT</b> - Police heat: $crimeSystem.heatLevel% </div> <</if>> <<if $job && $job !== "Unemployed" && $job !== "Criminal">> <div style="background: linear-gradient(135deg, #f39c12 0%, #f1c40f 100%); color: #000; padding: 12px; border-radius: 5px; margin-bottom: 15px; text-align: center; font-size: 15px;"> ⚠️ <b>WARNING:</b> If caught stealing, you'll lose your job and become a Criminal! </div> <</if>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #e74c3c;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 18px;">Criminal Record</h3> <p style="margin: 5px 0; font-size: 15px;"><b>Successful:</b> $crimeSystem.successfulThefts | <b>Failed:</b> $crimeSystem.failedThefts | <b>Heat:</b> $crimeSystem.heatLevel/100</p> <p style="margin: 5px 0; font-size: 15px;"><b>Arrested:</b> $crimeSystem.arrestCount times | <b>Resisted:</b> $crimeSystem.resistedArrestCount times</p> </div> <<if !_canSteal.canSteal>> <div style="background: #3a3a3a; padding: 15px; border-radius: 8px; border-left: 4px solid #95a5a6; margin-bottom: 15px;"> <p style="color: #bdc3c7; margin: 0; font-style: italic; font-size: 15px;">_canSteal.reason</p> </div> <<else>> <<set _breakdown = setup.getTheftStatBreakdown($currentCrimeLocation)>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 18px;">Location Info</h3> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 15px;">_locationData.description</p> <div style="background: #2a2a2a; padding: 10px; border-radius: 5px; margin-bottom: 10px;"> <p style="color: #aaa; font-size: 15px; margin: 5px 0;"><b>Target Frequency:</b> <span style="color: #51cf66;">_locationData.targetFrequency%</span></p> <p style="color: #aaa; font-size: 15px; margin: 5px 0;"><b>Patrol Risk:</b> <span style="color: #ff6b6b;">_locationData.patrolFrequency%</span></p> <p style="color: #aaa; font-size: 15px; margin: 5px 0;"><b>Your Success Rate:</b> <span style="color: <<if _breakdown.total >= 70>>#2ecc71<<elseif _breakdown.total >= 40>>#f39c12<<else>>#e74c3c<</if>>;">_breakdown.total%</span></p> <<if _breakdown.wellRestedBonus > 0>> <p style="color: #51cf66; font-size: 13px; margin: 3px 0 3px 15px;">😴 Well Rested: +<<print _breakdown.wellRestedBonus>>%</p> <</if>> <<if _breakdown.exhaustionPenalty < 0>> <p style="color: #ff6b6b; font-size: 13px; margin: 3px 0 3px 15px;">Exhaustion: <<print _breakdown.exhaustionPenalty>>%</p> <</if>> <<if _breakdown.werefoxBonus > 0>> <p style="color: #ff9800; font-size: 13px; margin: 3px 0 3px 15px;">✓ Werefox: +<<print _breakdown.werefoxBonus>>%</p> <</if>> </div> <<if $crimeSystem.heatLevel >= 50>> <p style="color: #ff6b6b; font-size: 14px; margin: 8px 0; font-weight: bold;">⚠️ High heat! Police are actively patrolling.</p> <</if>> <<if $traitScanner || $currentArtifact === "The Crowd's Eye">> <p style="color: #3498db; font-size: 14px; margin: 8px 0;">✓ Trait Scanner active</p> <<elseif $physicalTraits.includes("Sunfish") || $mentalTraits.includes("Sunfish")>> <p style="color: #3498db; font-size: 14px; margin: 8px 0;">✓ Sunfish perception active</p> <<else>> <p style="color: #888; font-size: 14px; margin: 8px 0;">⚠️ No scanner - physical traits only</p> <</if>> </div> <div style="text-align: center; margin-bottom: 15px;"> <<if $job && $job !== "Unemployed" && $job !== "Criminal">> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3); font-size: 16px;'>🎯 Scout for Targets</div>">> <<popover 'noclick'>> <div style="padding: 20px; background: #1a1a1a; border-radius: 10px; max-width: 450px;"> <h2 style="color: #ff6b6b; margin-top: 0; text-align: center; font-size: 20px;">⚠️ WARNING</h2> <div style="background: #2a2a2a; padding: 12px; border-radius: 8px; border-left: 4px solid #ff6b6b; margin-bottom: 15px;"> <p style="color: #fff; margin: 0 0 8px 0; font-size: 15px;"><b>Current Job:</b> <span style="color: #51cf66;">$job</span></p> <p style="color: #ff6b6b; margin: 0 0 5px 0; font-size: 15px;">If caught stealing:</p> <ul style="color: #ccc; margin: 5px 0; font-size: 14px; padding-left: 20px;"> <li>Lose your job immediately</li> <li>Become a "Criminal"</li> <li>Face fines and jail time</li> <li>Gain criminal record</li> </ul> </div> <p style="color: #aaa; text-align: center; margin-bottom: 15px; font-size: 14px; font-style: italic;">Risk your employment?</p> <div style="display: flex; gap: 10px; justify-content: center;"> <<link "<div style='background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; text-align: center; font-size: 15px;'>Yes, Risk It</div>">> <<run Dialog.close()>> <<goto "ScoutForTarget">> <</link>> <<link "<div style='background: #95a5a6; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; text-align: center; font-size: 15px;'>No, Go Back</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> <<else>> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3); font-size: 16px;'>🎯 Scout for Targets</div>">> <<goto "ScoutForTarget">> <</link>> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>← Return to _locationData.name</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
/* ---------------------------------- */ /* --- TRAIT THEFT CRIME SYSTEM --- */ /* --- EASIER THEFT VERSION (2X) --- */ /* ---------------------------------- */ <<set $traitScanner = false>> <<set $crimeSystem = { warnings: 0, witnessedCrimes: 0, totalThefts: 0, successfulThefts: 0, failedThefts: 0, arrestCount: 0, resistedArrestCount: 0, surrenderCount: 0, lastCrimeLocation: "", lastCrimeTime: "", heatLevel: 0, activeWarrant: false, lastHeatDecayDay: 0, crimesCommitted: 0, consecutiveEscapes: 0 /* NEW: Track escape streak */ }>> /* Location data for trait theft with stat requirements */ <<set setup.crimeLocations = { "Alleyway": { name: "Dark Alleyway", targetFrequency: 35, patrolFrequency: 15, traitQuality: "low-medium", nightBonus: 15, description: "A shadowy alleyway where desperate souls lurk.", primaryStats: ["dexterity", "strength"], secondaryStats: ["intelligence"] }, "Downtown": { name: "Downtown", targetFrequency: 75, patrolFrequency: 40, traitQuality: "medium", nightBonus: 5, description: "Busy streets filled with all kinds of people.", primaryStats: ["charisma", "dexterity"], secondaryStats: ["intelligence"] }, "BusinessDistrict": { name: "Business District", targetFrequency: 65, patrolFrequency: 50, traitQuality: "medium-high", nightBonus: -10, description: "Well-dressed professionals hurrying about their business.", primaryStats: ["charisma", "intelligence"], secondaryStats: ["dexterity"] }, "RedLightDistrict": { name: "Red Light District", targetFrequency: 80, patrolFrequency: 25, traitQuality: "medium", nightBonus: 20, description: "A seedy area where morals are... flexible.", primaryStats: ["charisma", "strength"], secondaryStats: ["dexterity"] }, "SeabassPark": { name: "Seabass Park", targetFrequency: 50, patrolFrequency: 20, traitQuality: "low-medium", nightBonus: -15, description: "A peaceful park, though less populated at night.", primaryStats: ["dexterity", "intelligence"], secondaryStats: ["charisma"] }, "Mall": { name: "Shopping Mall", targetFrequency: 85, patrolFrequency: 45, traitQuality: "medium-high", nightBonus: -30, description: "Crowded shopping center full of consumers.", primaryStats: ["charisma", "dexterity"], secondaryStats: ["intelligence"] }, "Outskirts": { name: "City Outskirts", targetFrequency: 25, patrolFrequency: 10, traitQuality: "low", nightBonus: 5, description: "Sparse population on the edge of the city.", primaryStats: ["strength", "dexterity"], secondaryStats: ["intelligence"] }, "Docks": { name: "Harbor Docks", targetFrequency: 40, patrolFrequency: 30, traitQuality: "low-medium", nightBonus: 10, description: "Working-class folks loading and unloading cargo.", primaryStats: ["strength", "dexterity"], secondaryStats: ["charisma"] } }>> <<set setup.unstealableTraits = [ "Criminal Deluxe", "Were-Creature", "Totally not a Vampire", "Definitely not a Vampire", "Occult Expert", "Lucky", "Sunfish", "Blue Hair", "Snow Fox", "Soul", "Oral Expert", "Anal Expert", "Rough Sex Enthusiast", "Sensual Lover", "BDSM Enthusiast - Dom", "BDSM Enthusiast - Sub", "Roleplay Expert", "Dirty Talker", "Exhibitionist", "Sexual Stamina Expert", "Tit Worship Expert", "Titfuck Master", "Fishing", "Advanced Angler", "Master Angler", "Fishimon Master", "Quill", /* LABORATORY TRANSFORMATION TRAITS - Base Traits */ "Fangs", "Pointed Ears", "Glowing Eyes", "Claws", "Wings", "Tail", "Lactating", "Mischievous", "Docile", "Feral", "Predatory", "Maternal", "Paternal", "Breeding Obsessed", "Heat Cycles", "Pack Minded", "Nocturnal", "Territorial", "Shameless", "Insatiable", "Praise Seeking", "Obedient", "Collar Loving", "Rebellious", "Corrupted", /* LABORATORY TRANSFORMATION TRAITS - Intermediate Combination */ "Temptress", "Sadist", "Masochist", "Milky", "Neko", "Inu", "Imp-Touched", "Mommy Energy", "Devoted", "Savage", "Genius", "Cunning", /* LABORATORY TRANSFORMATION TRAITS - Full Transformations */ "Succubus", /* "Incubus", - temporarily disabled */ "Imp", "Cerberus", "Werecat", "Werewolf", "Werebunny", "Werefox", "Weresheep", "Hucow", "Trophy Wife", "Ojou", "Gym Bunny", "E-Girl", "Punk", "Siren", "Living Doll", "Dominatrix", "Slut", "Himbo", /* NEW LABORATORY TRANSFORMATION TRAITS */ "Angel", "Naiad", "Automaton", "Banshee", "Cheshire Cat", "Cupid", "Dark Angel", "Honeybee", "Jinko", "Kakuen", "Lizardman", "Ocelomeh", "Pyrow", "Raiju", "Salamander", "Satyros", "Vampire", "Kitsune", "Anubis", "Pharaoh", "Gyaru", /* BODY PART SIZE TRAITS */ "Gigantic Chest", "Gigantic Butt", /* ONE-TIME EVENT TRAITS */ "Chosen", "Blessed", "Wild", /* JUNGLE EVENT TRAITS */ "Honey", /* MOUNTAIN EVENT TRAITS */ "Cog", "Mystic", /* RELATIONSHIP EVENT TRAITS */ "Heart", /* DESERT EVENT TRAITS */ "Guardian", /* CLIFF EVENT TRAITS */ "Darkness", "Alcoholic", "Disturbed", /* MANOR EVENT TRAITS */ "Mirrored", "Thirsty", "Blood", /* VOLCANO EVENT TRAITS */ "Burnt", "Inferno", /* OASIS EVENT TRAITS */ "Scaled", "Divine Sunfish", /* MOUNTAIN PEAK TRAITS */ "Electrified", /* JINKO ABILITY TRAIT */ "Fish", /* GENDER TRAITS */ "Cuntboy", "Dickgirl", "Futanari", /* STEREOTYPE TRAITS */ "Diva", "Geek", "Goth", "Jock", "Nerd", "Prep", "Tomboy", "Delinquent", /* MENTAL TRAITS - RESTRICTED */ "Bimbo", "Corrupt", "Dominant", "Musky", /* SEXUALLY SKILLED */ "Sexually Skilled", /* RESTRICTED SKILLS */ "Maid", "Forklift Certified", /* NPC-ONLY SKILLS */ "Building PCs", "Animation", "Fashion Design", "Finance", "Investigation", "Leadership", "Social Skills", "Video Editing", "Combat Training", "Gaming", "Basketball", "Business", "Mechanical Repair", "Navigation", "Magic Theory", "Meditation", /* VOICE TRAITS - POSITIVE */ "Smooth Voice", "Soft-Spoken", "Warm Tone", "Gentle Voice", "Soothing Tone", "Silky Voice", "Clear Enunciation", "Articulate Speech", "Smooth Talker", "Friendly Tone", "Charismatic Voice", "Steady Voice", "Pleasant Cadence", "Calm Voice", "Expressive Voice", "Animated Tone", "Lively Tone", "Charming Tone", "Hushed Intimate Voice", "Balanced Neutral Tone", "Sing-Songy Voice", "Eager Tone", "Bouncy Tone", "Melodic Voice", "Clear Pronunciation", "Even-Paced Voice", "Understated Voice", "Soft Monologue Style", "Gaelic Accent", "Measured Speech", /* VOICE TRAITS - MIXED/NEGATIVE */ "Choppy Speech", "Croaky Voice", "Deadpan Delivery", "Detached Voice", "Emotionless Tone", "Fast Talker", "Flat Voice", "Grim Tone", "High-Pitched Tone", "Interruptive Tone", "Lazy Drawl", "Monotone", "Mumbly Voice", "Nasally Tone", "Rapid-Fire Speech", "Raspy Voice", "Robotic Tone", "Shaky Voice", "Sharp Voice", "Snappy Tone", "Stoic Tone", "Stuttering Speech", "Flat Uninterested Voice", "Slurred Speech", "Whiny Voice", "Oni" ]>> <<set setup.moralTraitsBlockingTheft = [ "Kind", "Honest", "Considerate", "Loyal", "Polite", "Warm", "Empathetic", "Supportive", "Thoughtful", "Trusting", "Blessed", "Wild", "Chosen" ]>> <<set setup.moralTraitsPenalty = [ "Friendly", "Diplomatic", "Calm", "Patient", "Humble", "Mature", "Wise", "Reassuring" ]>> <<set setup.theftBonusTraits = { "Sly": 2, "Deceitful": 1, "Crafty": 3, "Shrewd": 1, "Cunning": 4, "Stealthy": 5, "Quick Reflexes": 2, "Nimble Fingers": 3, "Fast": 2, "Quick": 2, "Reckless": 1, "Impulsive": 1, "Corrupt": 1, "Selfish": 1, "Cruel": 1, "Cold": 1, "Sunfish": 15 }>> <<set setup.theftBonusSkills = { "Stealth": 7, "Lock Picking": 8, "Acting": 3, "Persuasion": 7, "Criminal Deluxe": 100 }>> <<set setup.canPlayerSteal = function() { var v = State.variables; /* Sunfish Artifact possession: cannot steal while you are Roisin. The risk would land on her, not you, and the artifact won't allow it. */ if (v.possessionActive) { return { canSteal: false, reason: "You can't commit theft while you're <b>Roisin Sullivan</b>. The artifact won't let you put her on the line." }; } /* Slime possession: cannot steal while you are wearing another body. */ if (v.slimePossessionActive) { return { canSteal: false, reason: "You will not risk this body you are wearing on a theft. Slither out first." }; } /* Check if player is in their original body */ /* lifeSwapPortraitSource being undefined or "player" means they're in their original body */ if (v.lifeSwapPortraitSource && v.lifeSwapPortraitSource !== "player") { return { canSteal: false, reason: "You can only steal while in your <b>original body</b>. Life swapping into another body prevents you from committing theft." }; } /* Ojou: an heiress does not pickpocket. */ if (v.physicalTraits && v.physicalTraits.includes("Ojou")) { return { canSteal: false, reason: "An <b>Ojou-sama</b> would never pickpocket. Such things lie far beneath you, just as the fan in your hand would refuse them." }; } for (var i = 0; i < setup.moralTraitsBlockingTheft.length; i++) { var trait = setup.moralTraitsBlockingTheft[i]; if (v.physicalTraits.includes(trait) || v.mentalTraits.includes(trait)) { return { canSteal: false, reason: "Your <b>" + trait + "</b> nature prevents you from stealing from innocent people." }; } } return {canSteal: true}; }>> <<set setup.calculateStatModifier = function(stat, value) { var effectiveValue = Math.min(50, value); if (effectiveValue < 15) { return -Math.floor((15 - effectiveValue) / 2); } /* DOUBLED: Was divide by 5, now divide by 2.5 */ return Math.floor((effectiveValue - 15) / 2.5); }>> <<set setup.calculateTheftChance = function(location) { var v = State.variables; var baseChance = 50; /* DOUBLED from 25 */ var totalStr = setup.getTotalStat("strength"); var totalDex = setup.getTotalStat("dexterity"); var totalInt = setup.getTotalStat("intelligence"); var totalCha = setup.getTotalStat("charisma"); var locationData = setup.crimeLocations[location]; if (locationData) { for (var i = 0; i < locationData.primaryStats.length; i++) { var stat = locationData.primaryStats[i]; if (stat === "strength") { baseChance += setup.calculateStatModifier(stat, totalStr); } else if (stat === "dexterity") { baseChance += setup.calculateStatModifier(stat, totalDex); } else if (stat === "intelligence") { baseChance += setup.calculateStatModifier(stat, totalInt); } else if (stat === "charisma") { baseChance += setup.calculateStatModifier(stat, totalCha); } } for (var i = 0; i < locationData.secondaryStats.length; i++) { var stat = locationData.secondaryStats[i]; var modifier = 0; if (stat === "strength") { modifier = setup.calculateStatModifier(stat, totalStr); } else if (stat === "dexterity") { modifier = setup.calculateStatModifier(stat, totalDex); } else if (stat === "intelligence") { modifier = setup.calculateStatModifier(stat, totalInt); } else if (stat === "charisma") { modifier = setup.calculateStatModifier(stat, totalCha); } baseChance += Math.floor(modifier / 2); } baseChance -= Math.floor(locationData.patrolFrequency / 5); } if (v.timeOfDay === "Night" || v.timeOfDay === "Late Night") { baseChance += 20; /* DOUBLED from 10 */ } /* Individual trait bonuses - DOUBLED */ for (var trait in setup.theftBonusTraits) { if (v.physicalTraits.includes(trait) || v.mentalTraits.includes(trait)) { baseChance += (setup.theftBonusTraits[trait] * 2); } } /* Individual skill bonuses - DOUBLED */ for (var skill in setup.theftBonusSkills) { if (v.skills.includes(skill)) { baseChance += (setup.theftBonusSkills[skill] * 2); } } /* Moral trait penalties - HALVED */ for (var i = 0; i < setup.moralTraitsPenalty.length; i++) { var trait = setup.moralTraitsPenalty[i]; if (v.physicalTraits.includes(trait) || v.mentalTraits.includes(trait)) { baseChance -= 6; /* HALVED from 12 */ } } if (v.physicalTraits.includes("Clumsy")) { baseChance -= 7.5; /* HALVED from 15 */ } /* Lucky/Unlucky trait modifiers - DOUBLED */ if (v.physicalTraits.includes("Lucky") || v.mentalTraits.includes("Lucky") || v.physicalTraits.includes("Cupid") || v.physicalTraits.includes("Cheshire Cat")) { baseChance += 20; /* DOUBLED from 10 */ } if ((v.physicalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || (v.mentalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || v.mentalTraits.includes("Bad Luck")) { baseChance -= 20; /* DOUBLED from 10 */ } /* Werefox +20% stealing bonus */ if (v.physicalTraits.includes("Werefox")) { baseChance += 20; } /* ===== TRANSFORMATION BONUSES ===== */ /* Ocelomeh: +25% steal chance */ if (v.physicalTraits && v.physicalTraits.includes("Ocelomeh")) { baseChance += 25; } /* Banshee: 100% steal chance (capped at 95 later) */ if (v.physicalTraits && v.physicalTraits.includes("Banshee")) { baseChance = 95; } /* Pyrow: +25% steal chance on clear days */ if (v.physicalTraits && v.physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()) { baseChance += 25; } /* ===== SKILL TREE: Steal Bonus ===== */ var skillTreeStealBonus = setup.skillTree.getEffect("stealBonus"); if (skillTreeStealBonus > 0) { baseChance += skillTreeStealBonus; } baseChance -= Math.floor(v.crimeSystem.heatLevel / 10); /* Determine minimum chance */ var minChance = 0; /* Default minimum is 0% */ /* ===== SKILL TREE: Steal Min Chance ===== */ var skillTreeMinChance = setup.skillTree.getEffect("stealMinChance"); if (skillTreeMinChance > 0) { minChance = Math.max(minChance, skillTreeMinChance); } /* ===== BUFF/DEBUFF MODIFIERS ===== */ if (typeof setup.getDebuffEffect === 'function') { var debuffSteal = setup.getDebuffEffect("stealChance"); if (debuffSteal !== 0) baseChance += debuffSteal; } if (typeof setup.getBuffEffect === 'function') { var buffSteal = setup.getBuffEffect("stealChance"); if (buffSteal > 0) baseChance += buffSteal; } return Math.max(minChance, Math.min(95, baseChance)); }>> <<set setup.getTheftStatBreakdown = function(location) { var v = State.variables; var breakdown = { base: 50, /* DOUBLED */ timeBonus: 0, statBonuses: {}, traitBonuses: 0, skillBonuses: 0, skillTreeBonus: 0, penalties: 0, heatPenalty: 0, luckModifier: 0, artifactBonus: 0, exhaustionPenalty: 0, wellRestedBonus: 0, werefoxBonus: 0, minChance: 0, total: 0 }; var stats = { strength: setup.getTotalStat("strength"), dexterity: setup.getTotalStat("dexterity"), intelligence: setup.getTotalStat("intelligence"), charisma: setup.getTotalStat("charisma") }; var locationData = setup.crimeLocations[location]; if (locationData) { for (var i = 0; i < locationData.primaryStats.length; i++) { var stat = locationData.primaryStats[i]; var modifier = setup.calculateStatModifier(stat, stats[stat]); breakdown.statBonuses[stat + " (primary)"] = modifier; } for (var i = 0; i < locationData.secondaryStats.length; i++) { var stat = locationData.secondaryStats[i]; var modifier = Math.floor(setup.calculateStatModifier(stat, stats[stat]) / 2); breakdown.statBonuses[stat + " (secondary)"] = modifier; } breakdown.penalties -= Math.floor(locationData.patrolFrequency / 5); } if (v.timeOfDay === "Night" || v.timeOfDay === "Late Night") { breakdown.timeBonus = 20; /* DOUBLED */ } /* Individual trait bonuses - DOUBLED */ for (var trait in setup.theftBonusTraits) { if (v.physicalTraits.includes(trait) || v.mentalTraits.includes(trait)) { breakdown.traitBonuses += (setup.theftBonusTraits[trait] * 2); } } /* Individual skill bonuses - DOUBLED */ for (var skill in setup.theftBonusSkills) { if (v.skills.includes(skill)) { breakdown.skillBonuses += (setup.theftBonusSkills[skill] * 2); } } /* ===== SKILL TREE: Steal Bonus ===== */ breakdown.skillTreeBonus = setup.skillTree.getEffect("stealBonus"); /* Moral trait penalties - HALVED */ for (var i = 0; i < setup.moralTraitsPenalty.length; i++) { if (v.physicalTraits.includes(setup.moralTraitsPenalty[i]) || v.mentalTraits.includes(setup.moralTraitsPenalty[i])) { breakdown.penalties -= 6; /* HALVED from 12 */ } } if (v.physicalTraits.includes("Clumsy")) { breakdown.penalties -= 7.5; /* HALVED from 15 */ } /* Lucky/Unlucky modifiers - DOUBLED */ if (v.physicalTraits.includes("Lucky") || v.mentalTraits.includes("Lucky") || v.physicalTraits.includes("Cupid") || v.physicalTraits.includes("Cheshire Cat")) { breakdown.luckModifier = 20; /* DOUBLED from 10 */ } if ((v.physicalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || (v.mentalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || v.mentalTraits.includes("Bad Luck")) { breakdown.luckModifier = -20; /* DOUBLED from 10 */ } breakdown.heatPenalty = -Math.floor(v.crimeSystem.heatLevel / 10); /* Transformation bonuses */ if (v.physicalTraits && v.physicalTraits.includes("Ocelomeh")) { breakdown.traitBonuses += 25; } if (v.physicalTraits && v.physicalTraits.includes("Banshee")) { breakdown.traitBonuses = 95; } if (v.physicalTraits && v.physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()) { breakdown.traitBonuses += 25; } /* ===== BUFF/DEBUFF MODIFIERS ===== */ if (typeof setup.getDebuffEffect === 'function') { var debuffStealBreak = setup.getDebuffEffect("stealChance"); if (debuffStealBreak !== 0) breakdown.exhaustionPenalty = debuffStealBreak; } if (typeof setup.getBuffEffect === 'function') { var buffStealBreak = setup.getBuffEffect("stealChance"); if (buffStealBreak > 0) breakdown.wellRestedBonus = buffStealBreak; } /* Werefox +20% stealing bonus */ if (v.physicalTraits.includes("Werefox")) { breakdown.werefoxBonus = 20; } /* ===== SKILL TREE: Steal Min Chance ===== */ var skillTreeMinChance = setup.skillTree.getEffect("stealMinChance"); breakdown.minChance = skillTreeMinChance; breakdown.total = breakdown.base + breakdown.timeBonus; for (var stat in breakdown.statBonuses) { breakdown.total += breakdown.statBonuses[stat]; } breakdown.total += breakdown.traitBonuses + breakdown.skillBonuses + breakdown.skillTreeBonus + breakdown.penalties + breakdown.heatPenalty + breakdown.luckModifier + breakdown.artifactBonus + breakdown.exhaustionPenalty + breakdown.wellRestedBonus + breakdown.werefoxBonus; breakdown.total = Math.max(breakdown.minChance, Math.min(95, breakdown.total)); return breakdown; }>> <<set setup.generateTheftTarget = function(location) { var locationData = setup.crimeLocations[location]; var quality = locationData.traitQuality; var target = { name: "", physicalTraits: [], mentalTraits: [], skills: [], bodyParts: { chest: "", butt: "", gender: "", genitals: "" }, appearance: { hairColor: "", hairLength: "", skinTone: "", age: "" } }; /* Determine gender first (LOWERCASE to match game convention) */ var genders = ["male", "female"]; target.bodyParts.gender = genders[random(0, genders.length - 1)]; /* Gender-appropriate names */ var maleNames = ["James", "Michael", "David", "John", "Robert", "William", "Richard", "Joseph", "Thomas", "Christopher", "Daniel", "Matthew", "Anthony", "Mark", "Donald", "Steven", "Paul", "Andrew", "Joshua", "Kenneth"]; var femaleNames = ["Mary", "Jennifer", "Linda", "Patricia", "Elizabeth", "Barbara", "Susan", "Jessica", "Sarah", "Karen", "Nancy", "Lisa", "Margaret", "Betty", "Sandra", "Ashley", "Dorothy", "Kimberly", "Emily", "Donna"]; var lastNames = ["Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez", "Hernandez", "Lopez", "Gonzalez", "Wilson", "Anderson", "Thomas", "Taylor", "Moore", "Jackson", "Martin"]; if (target.bodyParts.gender === "male") { target.name = maleNames[random(0, maleNames.length - 1)] + " " + lastNames[random(0, lastNames.length - 1)]; } else { target.name = femaleNames[random(0, femaleNames.length - 1)] + " " + lastNames[random(0, lastNames.length - 1)]; } /* Age - stored in appearance.age */ var ageRoll = random(1, 100); if (ageRoll <= 70) { target.appearance.age = "Adult"; } else { target.appearance.age = "Mature Adult"; } /* Hair - stored in appearance (FIXED - lowercase hairLength) */ var hairColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]; target.appearance.hairColor = hairColors[random(0, hairColors.length - 1)]; var hairLengths = ["short", "long"]; target.appearance.hairLength = hairLengths[random(0, hairLengths.length - 1)]; /* Skin tone */ var skinTones = ["Pale", "Tan", "Dark"]; target.appearance.skinTone = skinTones[random(0, skinTones.length - 1)]; /* Body parts - gender appropriate (LOWERCASE genitals to match game convention) */ if (target.bodyParts.gender === "male") { /* Males: only flat masculine chest, masculine/flat butt, penis */ target.bodyParts.chest = "flat masculine"; var maleButtSizes = ["flat masculine", "flat", "small"]; target.bodyParts.butt = maleButtSizes[random(0, maleButtSizes.length - 1)]; target.bodyParts.genitals = "penis"; } else { /* Females: no flat masculine chest, varied butt, vagina */ var femaleChestSizes = ["flat", "small", "medium", "large", "huge", "giant"]; var femaleButtSizes = ["flat", "small", "medium", "large", "huge", "giant"]; target.bodyParts.chest = femaleChestSizes[random(0, femaleChestSizes.length - 1)]; target.bodyParts.butt = femaleButtSizes[random(0, femaleButtSizes.length - 1)]; target.bodyParts.genitals = "vagina"; } /* Gender-appropriate physical traits (REMOVED hair length traits - handled by body parts) */ var masculineTraits = ["Tall", "Muscular", "Fit", "Athletic Build", "Lean", "Stocky", "Broad-shouldered", "Strong", "Scarred", "Sharp Features", "Sturdy", "Stiff"]; var feminineTraits = ["Attractive", "Curvy", "Voluptuous", "Petite", "Slim", "Graceful", "Youthful", "Fashionable", "Smooth Skin", "Soft", "Flexible"]; var neutralTraits = ["Short", "Tattooed", "Pierced", "Freckled", "Plain", "Ugly", "Mature", "Overweight", "Underweight", "Clumsy", "Weak", "Blemished", "Quick", "Quick Reflexes", "Fast", "Slow"]; var visiblePhysicalPool = []; if (target.bodyParts.gender === "male") { visiblePhysicalPool = masculineTraits.concat(neutralTraits); } else { visiblePhysicalPool = feminineTraits.concat(neutralTraits); } var numTraits = 0; if (quality === "low") { numTraits = random(1, 3); } else if (quality === "low-medium") { numTraits = random(2, 4); } else if (quality === "medium") { numTraits = random(3, 5); } else if (quality === "medium-high") { numTraits = random(4, 7); } else { numTraits = random(5, 8); } for (var i = 0; i < numTraits; i++) { if (visiblePhysicalPool.length > 0) { var idx = random(0, visiblePhysicalPool.length - 1); var trait = visiblePhysicalPool[idx]; var conflict = setup.getConflictingTrait(trait, target.physicalTraits); if (!conflict && !target.physicalTraits.includes(trait)) { if (!setup.unstealableTraits.includes(trait)) { target.physicalTraits.push(trait); } } visiblePhysicalPool.splice(idx, 1); } } var mentalPool = [ "Confident", "Shy", "Friendly", "Kind", "Bitchy", "Charming", "Awkward", "Intelligent", "Foolish", "Brave", "Cowardly", "Calm", "Short Tempered", "Dominant", "Submissive", "Extroverted", "Introverted", "Optimistic", "Pessimistic", "Hardworking", "Lazy", "Patient", "Impatient", "Honest", "Deceitful", "Sly", "Creative", "Analytical", "Energetic", "Loyal", "Ambitious", "Humble", "Arrogant", "Aggressive", "Passive", "Cruel", "Empathetic", "Stubborn", "Jealous", "Supportive", "Competitive", "Logical", "Shrewd", "Paranoid", "Trusting", "Complacent", "Dull", "Wise", "Curious", "Witty", "Outgoing", "Thoughtful", "Chill", "Nonchalant", "Diplomatic", "Organized", "Resourceful", "Focused", "Disciplined", "Determined", "Steadfast", "Considerate", "Polite", "Funny", "Reassuring", "Talkative", "Direct", "Efficient", "Negotiator", "Crafty", "Workaholic", "High Stamina", "Flirty", "Seductive", "Alluring", "Warm", "Bookworm", "Unlucky", "Blunt", "Perfectionist", "Overthinker", "Moody", "Unpredictable", "Risk Taker", "Impulsive", "Cynical", "Quiet", "Tone Deaf", "Tease", "Clingy", "Sensitive", "Corporate Drone", "Forgetful", "Disorganized", "Selfish", "Erratic", "Obsessive", "Insecure", "Rude", "Unreliable", "Slow Learner", "Reckless", "Cold", "Insensitive", "Unskilled", "High Energy", "Deep Thinker", "Monotone Expression", "Sarcastic", "Artistic", "Relaxed", "Humorous", "Perceptive", "Detail-Oriented", "Customer-Focused", "Punctual", "Naive", "Flexible", "Mature" ]; var numMental = random(2, 5); for (var i = 0; i < numMental; i++) { if (mentalPool.length > 0) { var idx = random(0, mentalPool.length - 1); var trait = mentalPool[idx]; var conflict = setup.getConflictingTrait(trait, target.mentalTraits); if (!conflict && !target.mentalTraits.includes(trait)) { if (!setup.unstealableTraits.includes(trait)) { target.mentalTraits.push(trait); } } mentalPool.splice(idx, 1); } } var skillPool = Object.keys(setup.skillBonuses).filter(function(skill) { return !setup.unstealableTraits.includes(skill); }); var numSkills = random(1, 4); for (var i = 0; i < numSkills; i++) { if (skillPool.length > 0) { var idx = random(0, skillPool.length - 1); target.skills.push(skillPool[idx]); skillPool.splice(idx, 1); } } return target; }>> <<set setup.checkOfficerPatrol = function(location) { var v = State.variables; var locationData = setup.crimeLocations[location]; var patrolChance = locationData.patrolFrequency; patrolChance += Math.floor(v.crimeSystem.heatLevel / 5); if (v.timeOfDay === "Night" || v.timeOfDay === "Late Night") { patrolChance += 10; } var roll = random(1, 100); return roll <= patrolChance; }>> <<set setup.checkWitnesses = function(location) { var locationData = setup.crimeLocations[location]; var witnessChance = Math.floor(locationData.targetFrequency / 2); var roll = random(1, 100); return roll <= witnessChance; }>> <<set setup.calculateEscapeChance = function() { var v = State.variables; var baseChance = 25; var totalDex = setup.getTotalStat("dexterity"); var dexMod = setup.calculateStatModifier("dexterity", totalDex); baseChance += dexMod * 2; var totalStr = setup.getTotalStat("strength"); var strMod = setup.calculateStatModifier("strength", totalStr); baseChance += strMod; if (v.physicalTraits.includes("Fast") || v.physicalTraits.includes("Quick")) { baseChance += 15; } if (v.physicalTraits.includes("Athletic Build") || v.physicalTraits.includes("Fit")) { baseChance += 10; } if (v.skills.includes("Athletics")) { baseChance += 10; } if (v.physicalTraits.includes("Slow") || v.physicalTraits.includes("Clumsy")) { baseChance -= 20; } if (v.physicalTraits.includes("Overweight")) { baseChance -= 15; } /* Lucky/Unlucky modifiers for escape */ if (v.physicalTraits.includes("Lucky") || v.mentalTraits.includes("Lucky") || v.physicalTraits.includes("Cupid") || v.physicalTraits.includes("Cheshire Cat")) { baseChance += 10; } if ((v.physicalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || (v.mentalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || v.mentalTraits.includes("Bad Luck")) { baseChance -= 10; } return Math.max(5, Math.min(85, baseChance)); }>> <<set setup.decayCrimeHeat = function() { var v = State.variables; if (v.crimeSystem.heatLevel > 0) { v.crimeSystem.heatLevel = Math.max(0, v.crimeSystem.heatLevel - 2); } if (v.crimeSystem.heatLevel < 20) { v.crimeSystem.activeWarrant = false; } }>> <<set setup.checkAndDecayHeat = function() { var v = State.variables; /* Initialize lastHeatDecayDay if it doesn't exist */ if (v.crimeSystem.lastHeatDecayDay === undefined) { v.crimeSystem.lastHeatDecayDay = v.dayNumber; } /* Check if a full day has passed since last decay */ if (v.dayNumber > v.crimeSystem.lastHeatDecayDay) { var daysPassed = v.dayNumber - v.crimeSystem.lastHeatDecayDay; /* Decay heat for each day that passed */ for (var i = 0; i < daysPassed; i++) { if (v.crimeSystem.heatLevel > 0) { /* Base decay: 5 points per day */ var decayAmount = 5; /* ===== SKILL TREE: Heat Decay Bonus ===== */ var skillTreeHeatDecay = setup.skillTree.getEffect("heatDecay"); if (skillTreeHeatDecay > 0) { decayAmount += skillTreeHeatDecay; } v.crimeSystem.heatLevel = Math.max(0, v.crimeSystem.heatLevel - decayAmount); } } /* Update last decay day */ v.crimeSystem.lastHeatDecayDay = v.dayNumber; /* Clear warrant if heat is low enough */ if (v.crimeSystem.heatLevel < 20) { v.crimeSystem.activeWarrant = false; } } }>> <<set setup.attemptScannerTheft = function() { var v = State.variables; var baseChance = 2; var totalDex = setup.getTotalStat("dexterity"); if (totalDex >= 30) baseChance += 10; if (totalDex >= 50) baseChance += 10; if (v.skills.includes("Lock Picking")) baseChance += 10; if (v.skills.includes("Stealth")) baseChance += 10; if (v.physicalTraits.includes("Sly") || v.mentalTraits.includes("Sly")) baseChance += 5; if (v.physicalTraits.includes("Quick Reflexes")) baseChance += 8; /* Lucky/Unlucky modifiers */ if (v.physicalTraits.includes("Lucky") || v.mentalTraits.includes("Lucky") || v.physicalTraits.includes("Cupid") || v.physicalTraits.includes("Cheshire Cat") || v.physicalTraits.includes("Cerberus")) baseChance += 10; if ((v.physicalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || (v.mentalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")) || v.mentalTraits.includes("Bad Luck")) baseChance -= 10; return Math.max(2, Math.min(85, baseChance)); }>> <<set setup.getTraitValueModifier = function(traitName, bodyPartValue) { var traitValue; /* If bodyPartValue is provided, use it directly (for body parts) */ if (bodyPartValue !== undefined && bodyPartValue !== null) { traitValue = bodyPartValue; } else { /* Use the existing getTraitValue function - try different types */ traitValue = setup.getTraitValue('physical', traitName); /* If it returned a default value, try mental */ if (traitValue === 15) { traitValue = setup.getTraitValue('mental', traitName); } /* If still default, try skill */ if (traitValue === 15) { traitValue = setup.getTraitValue('skill', traitName); } } var modifier = 0; if (traitValue < 0) { /* Negative traits are EASIER to steal (bonus) - ORIGINAL FORMULA */ modifier = Math.abs(traitValue); } else if (traitValue >= 0 && traitValue <= 10) { /* Low value traits - no modifier */ modifier = 0; } else if (traitValue >= 11 && traitValue <= 25) { /* Medium value traits - small penalty - ORIGINAL FORMULA */ modifier = -Math.floor((traitValue - 10) / 3); } else if (traitValue >= 26 && traitValue <= 50) { /* High value traits - moderate penalty - ORIGINAL FORMULA */ modifier = -10 - Math.floor((traitValue - 25) / 2.5); } else { /* Very high value traits (50+) - larger penalty - ORIGINAL FORMULA */ modifier = -20 - Math.floor((traitValue - 50) / 3.5); } return modifier; }>> <<set setup.calculateIndividualTraitStealChance = function(traitName, bodyPartValue, baseChance) { var v = State.variables; /* Start with base chance from location calculation if not provided */ if (baseChance === undefined) { baseChance = setup.calculateTheftChance(v.currentCrimeLocation); } /* Get the trait value modifier (penalties for high-value traits - ORIGINAL penalties) */ var modifier = setup.getTraitValueModifier(traitName, bodyPartValue); /* Calculate final chance */ var finalChance = baseChance + modifier; /* Determine minimum chance */ var minChance = 0; /* Default minimum is 0% */ /* ===== SKILL TREE: Steal Min Chance ===== */ var skillTreeMinChance = setup.skillTree.getEffect("stealMinChance"); if (skillTreeMinChance > 0) { minChance = Math.max(minChance, skillTreeMinChance); } return Math.max(minChance, Math.min(95, finalChance)); }>> <<set setup.canSeeAllTraits = function() { var v = State.variables; /* Can see all traits if: have Sunfish trait, trait scanner, the Crowd's Eye, or Naiad */ return v.skills.includes("Sunfish") || v.traitScanner === true || v.currentArtifact === "The Crowd's Eye" || (v.physicalTraits && v.physicalTraits.includes("Naiad")); }>> <<set setup.jailTraitGain = [ "Punctual", "Underweight", "Weak", "Disciplined", "Honest", "Calm", "Patient", "Paranoid", "Overthinker", "Stubborn", "Submissive", "Cowardly", "Dull", "Obsessive", "Unskilled", "Unlucky", "Unreliable" ]>> <<set setup.jailTraitLoss = [ "Sly", "Deceitful", "Crafty", "Cunning", "Stealthy", "Fast", "Quick", "Cruel", "Cold" ]>> <<set setup.processJailTraitChange = function() { var v = State.variables; var temp = State.temporary; if (!temp.jailTraitsGained) temp.jailTraitsGained = []; if (!temp.jailTraitsLost) temp.jailTraitsLost = []; if (!temp.jailTraitsReplaced) temp.jailTraitsReplaced = []; if (!temp.daysServedTotal) temp.daysServedTotal = 0; temp.daysServedTotal = v.jailSystem.daysServed; /* Calculate chance based on days served (increases each day) */ var baseChance = Math.min(15 + (v.jailSystem.daysServed * 5), 60); /* Chance to LOSE negative traits */ if (random(1, 100) <= baseChance) { var lossableTraits = setup.jailTraitLoss.filter(function(trait) { return v.physicalTraits.includes(trait) || v.mentalTraits.includes(trait); }); if (lossableTraits.length > 0) { var traitToLose = lossableTraits[random(0, lossableTraits.length - 1)]; /* Remove from appropriate array */ if (v.physicalTraits.includes(traitToLose)) { v.physicalTraits.delete(traitToLose); } else if (v.mentalTraits.includes(traitToLose)) { v.mentalTraits.delete(traitToLose); } temp.jailTraitsLost.push(traitToLose); } } /* Chance to GAIN or REPLACE traits */ if (random(1, 100) <= baseChance) { var gainableMentalTraits = setup.jailTraitGain.filter(function(trait) { return !v.mentalTraits.includes(trait) && !v.physicalTraits.includes(trait); }); var gainablePhysicalTraits = setup.jailTraitGain.filter(function(trait) { return !v.physicalTraits.includes(trait) && !v.mentalTraits.includes(trait) && (trait === "Underweight" || trait === "Weak"); }); /* Combine all gainable traits */ var allGainable = gainableMentalTraits.concat(gainablePhysicalTraits); if (allGainable.length > 0) { var newTrait = allGainable[random(0, allGainable.length - 1)]; /* Check if it conflicts with existing trait (for mutually exclusive pairs) */ var conflictingTrait = setup.getConflictingTrait(newTrait, v.mentalTraits.concat(v.physicalTraits)); if (conflictingTrait) { /* REPLACE the conflicting trait */ if (v.physicalTraits.includes(conflictingTrait)) { v.physicalTraits.delete(conflictingTrait); } else if (v.mentalTraits.includes(conflictingTrait)) { v.mentalTraits.delete(conflictingTrait); } /* Add the new trait to appropriate array */ if (["Underweight", "Weak"].includes(newTrait)) { v.physicalTraits.push(newTrait); } else { v.mentalTraits.push(newTrait); } temp.jailTraitsReplaced.push({old: conflictingTrait, new: newTrait}); } else { /* GAIN the trait (no conflict) */ if (["Underweight", "Weak"].includes(newTrait)) { v.physicalTraits.push(newTrait); } else { v.mentalTraits.push(newTrait); } temp.jailTraitsGained.push(newTrait); } } } }>> <<set setup.canTradeCriminalJob = function() { var v = State.variables; /* Cannot trade Criminal job if you have crimes committed */ if (!v.jobs || v.jobs.length === 0) return true; return !v.jobs.includes("Criminal") || v.crimeSystem.crimesCommitted === 0; }>>
<<widget "crimeOption">> <<set _currentLoc = $args[0]>> <<set _canSteal = setup.canPlayerSteal()>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin: 25px 0; border: 3px solid #e74c3c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">🦹 Criminal Activity</h2> <<if !_canSteal.canSteal>> <div style="background: #3a3a3a; padding: 15px; border-radius: 8px; border-left: 4px solid #95a5a6;"> <p style="color: #bdc3c7; margin: 0; font-style: italic;">_canSteal.reason</p> </div> <<else>> <<set _locationData = setup.crimeLocations[_currentLoc]>> <<set _breakdown = setup.getTheftStatBreakdown(_currentLoc)>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 0 0 10px 0;">Scout this area for potential targets to steal traits from.</p> <div style="background: #2a2a2a; padding: 10px; border-radius: 5px; margin-bottom: 10px;"> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><b>Target Frequency:</b> <span style="color: #51cf66;">_locationData.targetFrequency%</span></p> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><b>Patrol Risk:</b> <span style="color: #ff6b6b;">_locationData.patrolFrequency%</span></p> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><b>Your Success Rate:</b> <span style="color: <<if _breakdown.total >= 70>>#2ecc71<<elseif _breakdown.total >= 40>>#f39c12<<else>>#e74c3c<</if>>;">_breakdown.total%</span></p> <<if _breakdown.wellRestedBonus > 0>> <p style="color: #51cf66; font-size: 12px; margin: 3px 0 3px 15px;">😴 Well Rested: +<<print _breakdown.wellRestedBonus>>%</p> <</if>> <<if _breakdown.exhaustionPenalty < 0>> <p style="color: #ff6b6b; font-size: 12px; margin: 3px 0 3px 15px;">Exhaustion: <<print _breakdown.exhaustionPenalty>>%</p> <</if>> <<if _breakdown.werefoxBonus > 0>> <p style="color: #ff9800; font-size: 12px; margin: 3px 0 3px 15px;">✓ Werefox: +<<print _breakdown.werefoxBonus>>%</p> <</if>> </div> <<if $crimeSystem.heatLevel >= 50>> <p style="color: #ff6b6b; font-size: 13px; margin: 10px 0; font-weight: bold;">⚠️ High heat level! Police are actively searching this area.</p> <</if>> <<if $traitScanner || $currentArtifact === "The Crowd's Eye">> <p style="color: #3498db; font-size: 13px; margin: 5px 0;">✓ Trait Scanner active - you can see all traits</p> <<elseif $physicalTraits.includes("Sunfish") || $mentalTraits.includes("Sunfish")>> <p style="color: #3498db; font-size: 13px; margin: 5px 0;">✓ Sunfish perception - you can see all traits</p> <<else>> <p style="color: #888; font-size: 13px; margin: 5px 0;">⚠️ Without a scanner, you can only see physical appearance</p> <</if>> </div> <<if $job && $job !== "Unemployed" && $job !== "Criminal">> <<link "<div style='background: #e74c3c; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🎯 Scout for Targets</div>">> <<popover 'noclick'>> <div style="padding: 25px; background: #1a1a1a; border-radius: 10px; max-width: 500px;"> <h2 style="color: #ff6b6b; margin-top: 0; text-align: center;">⚠️ WARNING</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border-left: 4px solid #ff6b6b; margin-bottom: 20px;"> <p style="color: #fff; margin: 0 0 10px 0; font-weight: bold;">You are currently employed as: <span style="color: #51cf66;">$job</span></p> <p style="color: #ff6b6b; margin: 0; font-size: 15px;">If you are <b>caught stealing</b> by police, you will:</p> <ul style="color: #ccc; margin: 10px 0;"> <li>Lose your current job immediately</li> <li>Be forced into the "Criminal" career path</li> <li>Face fines and possible jail time</li> <li>Gain a criminal record</li> </ul> </div> <p style="color: #aaa; text-align: center; margin-bottom: 20px; font-style: italic;">Are you sure you want to risk your employment?</p> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='background: #e74c3c; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; text-align: center;'>Yes, Take the Risk</div>">> <<set $currentCrimeLocation = _currentLoc>> <<run Dialog.close()>> <<goto "ScoutForTarget">> <</link>> <<link "<div style='background: #95a5a6; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; text-align: center;'>No, Stay Safe</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> <<else>> <<link "<div style='background: #e74c3c; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🎯 Scout for Targets</div>">> <<set $currentCrimeLocation = _currentLoc>> <<goto "ScoutForTarget">> <</link>> <</if>> <</if>> </div> <</widget>>
<<nobr>> /* Advance time for searching */ <<run advanceTime(random(10, 30))>> <<set _location = setup.crimeLocations[$currentCrimeLocation]>> <<set _targetChance = _location.targetFrequency>> /* Apply night bonus/penalty */ <<if $timeOfDay === "Night" || $timeOfDay === "Late Night">> <<set _targetChance += _location.nightBonus>> <</if>> /* 3% chance to encounter an officer */ <<set _officerEncounter = random(1, 100) <= 3>> <<if _officerEncounter>> /* Encountered an officer! */ <<goto "OfficerEncounterScout">> <<else>> <<set _foundTarget = random(1, 100) <= _targetChance>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #e74c3c; text-align: center; margin: 10px 0; font-size: 28px;">🔍 Scouting for Targets</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">_location.name</h2> <<if _foundTarget>> <<set $currentTarget = setup.generateTheftTarget($currentCrimeLocation)>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #2ecc71;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0; font-size: 18px;">🎯 Target Found</h3> <p style="margin: 5px 0; font-size: 15px;"><b>Name:</b> $currentTarget.name</p> <p style="margin: 5px 0; font-size: 15px;"><b>Age:</b> $currentTarget.appearance.age</p> <div style="background: #1a1a1a; padding: 10px; border-radius: 5px; margin-top: 10px;"> <h4 style="color: #3498db; margin: 0 0 8px 0; font-size: 15px;">Physical Attributes:</h4> <p style="margin: 3px 0; font-size: 14px;"><b>Chest:</b> $currentTarget.bodyParts.chest</p> <p style="margin: 3px 0; font-size: 14px;"><b>Butt:</b> $currentTarget.bodyParts.butt</p> <p style="margin: 3px 0; font-size: 14px;"><b>Hair Color:</b> $currentTarget.appearance.hairColor</p> <p style="margin: 3px 0; font-size: 14px;"><b>Hair Length:</b> $currentTarget.appearance.hairLength</p> <p style="margin: 3px 0; font-size: 14px;"><b>Skin Tone:</b> $currentTarget.appearance.skinTone</p> <p style="margin: 3px 0; font-size: 14px;"><b>Gender:</b> $currentTarget.bodyParts.gender</p> <p style="margin: 3px 0; font-size: 14px;"><b>Genitals:</b> $currentTarget.bodyParts.genitals</p> </div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h4 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Visible Physical Traits:</h4> <<if $currentTarget.physicalTraits.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 5px;"> <<for _trait range $currentTarget.physicalTraits>> <div style="background: #2a2a2a; padding: 8px 10px; border-radius: 3px; border-left: 2px solid #e74c3c; font-size: 14px;"> _trait </div> <</for>> </div> <<else>> <p style="color: #888; font-style: italic; margin: 0; font-size: 14px;">No notable physical traits</p> <</if>> <<if setup.canSeeAllTraits()>> <div style="background: #1e3a5f; padding: 12px; border-radius: 5px; margin-top: 10px; border: 2px solid #3498db;"> <h4 style="color: #3498db; margin: 0 0 10px 0; font-size: 16px;">🔍 Scanner Data - Mental Traits:</h4> <<if $currentTarget.mentalTraits.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 5px;"> <<for _trait range $currentTarget.mentalTraits>> <div style="background: #2c4a6f; padding: 8px 10px; border-radius: 3px; border-left: 2px solid #3498db; font-size: 14px;"> _trait </div> <</for>> </div> <<else>> <p style="color: #888; font-style: italic; margin: 0; font-size: 14px;">No notable mental traits</p> <</if>> <h4 style="color: #3498db; margin: 10px 0 10px 0; font-size: 16px;">🔍 Scanner Data - Skills:</h4> <<if $currentTarget.skills.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 5px;"> <<for _skill range $currentTarget.skills>> <div style="background: #2c4a6f; padding: 8px 10px; border-radius: 3px; border-left: 2px solid #3498db; font-size: 14px;"> _skill </div> <</for>> </div> <<else>> <p style="color: #888; font-style: italic; margin: 0; font-size: 14px;">No notable skills</p> <</if>> </div> <<else>> <p style="color: #888; font-size: 14px; margin: 10px 0 0 0; font-style: italic; text-align: center;">⚠️ Mental traits and skills hidden - Trait Scanner required</p> <</if>> </div> <div style="text-align: center; margin: 15px 0;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3); font-size: 16px;'>🎯 Attempt Theft</div>">> <<goto "SelectTraitToSteal">> <</link>> </div> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: #95a5a6; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-size: 15px;'>Look for Another Target</div>">> <<goto "ScoutForTarget">> <</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 15px;"> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 15px;">You spend time searching the area, but find no suitable targets...</p> <p style="color: #888; font-size: 14px; margin: 0; font-style: italic;">Target chance was _targetChance%</p> </div> <div style="text-align: center; margin: 15px 0;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>Keep Searching</div>">> <<goto "ScoutForTarget">> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-size: 15px;'>← Give Up and Leave</div>">> <<goto "CrimeHub">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set _baseChance = setup.calculateTheftChance($currentCrimeLocation)>> /* ===== Determine minimum chance ===== */ <<set _minChance = 0>> <<set _skillTreeMinChance = setup.skillTree.getEffect("stealMinChance")>> <<if _skillTreeMinChance > 0>> <<set _minChance = Math.max(_minChance, _skillTreeMinChance)>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #e74c3c; text-align: center; margin: 10px 0; font-size: 28px;">🎯 Select Trait to Steal</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Target: $currentTarget.name</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #667eea;"> <p style="color: #ccc; margin: 0 0 5px 0; font-size: 15px;"><b>Base Success Rate:</b> <span style="color: <<if _baseChance >= 50>>#2ecc71<<elseif _baseChance >= 25>>#f39c12<<else>>#ff6b6b<</if>>;">_baseChance%</span></p> <p style="color: #888; margin: 0; font-size: 13px; font-style: italic;">Trait/size value affects final odds</p> <<if _minChance > 0>> <p style="color: #9C27B0; margin: 5px 0 0 0; font-size: 13px;">⭐ Minimum chance: _minChance%</p> <</if>> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 0; font-size: 15px; text-align: center;"> Choose ONE thing to steal. You can swap body parts or conflicting traits. </p> </div> <!-- BODY PARTS SECTION --> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #3498db; margin: 0 0 12px 0; font-size: 18px;">Physical Attributes (Swappable):</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px;"> <!-- Chest --> <<set _targetChestValue = setup.getTraitValue('bodyPart', 'chest', $currentTarget.bodyParts.chest)>> <<set _chestModifier = setup.getTraitValueModifier('chest', _targetChestValue)>> <<set _chestFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _chestModifier))>> <<set _sameChest = ($bodyParts.chest === $currentTarget.bodyParts.chest)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameChest>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Chest Size</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.bodyParts.chest</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $bodyParts.chest</p> <<if !_sameChest>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _targetChestValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _chestFinalChance >= 70>>#2ecc71<<elseif _chestFinalChance >= 50>>#51cf66<<elseif _chestFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_chestFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameChest>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Size</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Chest</div>">> <<set $selectedTrait = "chest">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Butt --> <<set _targetButtValue = setup.getTraitValue('bodyPart', 'butt', $currentTarget.bodyParts.butt)>> <<set _buttModifier = setup.getTraitValueModifier('butt', _targetButtValue)>> <<set _buttFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _buttModifier))>> <<set _sameButt = ($bodyParts.butt === $currentTarget.bodyParts.butt)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameButt>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Butt Size</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.bodyParts.butt</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $bodyParts.butt</p> <<if !_sameButt>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _targetButtValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _buttFinalChance >= 70>>#2ecc71<<elseif _buttFinalChance >= 50>>#51cf66<<elseif _buttFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_buttFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameButt>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Size</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Butt</div>">> <<set $selectedTrait = "butt">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Hair Color --> <<set _hairColorValue = setup.getTraitValue('bodyPart', 'hairColor')>> <<set _hairColorModifier = setup.getTraitValueModifier('hairColor', _hairColorValue)>> <<set _hairFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _hairColorModifier))>> <<set _sameHairColor = ($appearance.hairColor === $currentTarget.appearance.hairColor)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameHairColor>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Hair Color</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.appearance.hairColor</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $appearance.hairColor</p> <<if !_sameHairColor>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _hairColorValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _hairFinalChance >= 70>>#2ecc71<<elseif _hairFinalChance >= 50>>#51cf66<<elseif _hairFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_hairFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameHairColor>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Color</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Hair Color</div>">> <<set $selectedTrait = "hairColor">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Hair Length --> <<set _hairLengthValue = setup.getTraitValue('bodyPart', 'hairLength')>> <<set _hairLengthModifier = setup.getTraitValueModifier('hairLength', _hairLengthValue)>> <<set _hairLengthFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _hairLengthModifier))>> <<set _sameHairLength = ($appearance.hairLength === $currentTarget.appearance.hairLength)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameHairLength>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Hair Length</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.appearance.hairLength</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $appearance.hairLength</p> <<if !_sameHairLength>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _hairLengthValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _hairLengthFinalChance >= 70>>#2ecc71<<elseif _hairLengthFinalChance >= 50>>#51cf66<<elseif _hairLengthFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_hairLengthFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameHairLength>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Length</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Hair Length</div>">> <<set $selectedTrait = "hairLength">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Skin Tone --> <<set _skinToneValue = setup.getTraitValue('bodyPart', 'skinTone')>> <<set _skinToneModifier = setup.getTraitValueModifier('skinTone', _skinToneValue)>> <<set _skinToneFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _skinToneModifier))>> <<set _sameSkinTone = ($appearance.skinTone === $currentTarget.appearance.skinTone)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameSkinTone>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Skin Tone</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.appearance.skinTone</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $appearance.skinTone</p> <<if !_sameSkinTone>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _skinToneValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _skinToneFinalChance >= 70>>#2ecc71<<elseif _skinToneFinalChance >= 50>>#51cf66<<elseif _skinToneFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_skinToneFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameSkinTone>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Tone</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Skin Tone</div>">> <<set $selectedTrait = "skinTone">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Gender --> <<set _genderValue = setup.getTraitValue('bodyPart', 'gender')>> <<set _genderModifier = setup.getTraitValueModifier('gender', _genderValue)>> <<set _genderFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _genderModifier))>> <<set _sameGender = ($bodyParts.gender === $currentTarget.bodyParts.gender)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameGender>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Gender</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.bodyParts.gender</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $bodyParts.gender</p> <<if !_sameGender>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _genderValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _genderFinalChance >= 70>>#2ecc71<<elseif _genderFinalChance >= 50>>#51cf66<<elseif _genderFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_genderFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameGender>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Gender</div> <<elseif $currentTarget.bodyParts.gender === "male" && setup.isMaleGenderBlocked()>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 13px; font-weight: bold;'>Incompatible with your <<print $activeTransformation>> transformation</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Gender</div>">> <<set $selectedTrait = "gender">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Genitals --> <<set _genitalsValue = setup.getTraitValue('bodyPart', 'genitals', $currentTarget.bodyParts.genitals)>> <<set _genitalsModifier = setup.getTraitValueModifier('genitals', _genitalsValue)>> <<set _genitalsFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _genitalsModifier))>> <<set _sameGenitals = ($bodyParts.genitals === $currentTarget.bodyParts.genitals)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameGenitals>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Genitals</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.bodyParts.genitals</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> $bodyParts.genitals</p> <<if !_sameGenitals>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _genitalsValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _genitalsFinalChance >= 70>>#2ecc71<<elseif _genitalsFinalChance >= 50>>#51cf66<<elseif _genitalsFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_genitalsFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<set _targetGenIsPenis = ($currentTarget.bodyParts.genitals === "penis" || $currentTarget.bodyParts.genitals === "big penis" || $currentTarget.bodyParts.genitals === "small penis")>> <<if _sameGenitals>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same</div> <<elseif _targetGenIsPenis && setup.isFutanariBlocked()>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 13px; font-weight: bold;'>Incompatible with your <<print $activeTransformation>> transformation</div> <<elseif $currentTarget.bodyParts.genitals === "both" && setup.isFutanariBlocked()>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 13px; font-weight: bold;'>Incompatible with your <<print $activeTransformation>> transformation</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Genitals</div>">> <<set $selectedTrait = "genitals">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <!-- Age --> <<set _ageValue = setup.getTraitValue('bodyPart', 'age')>> <<set _ageModifier = setup.getTraitValueModifier('age', _ageValue)>> <<set _ageFinalChance = Math.max(_minChance, Math.min(95, _baseChance + _ageModifier))>> <<set _sameAge = ($appearance.age === $currentTarget.appearance.age)>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _sameAge>>#95a5a6<<else>>#3498db<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;">Age</p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Target's:</b> $currentTarget.appearance.age</p> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Yours:</b> <<print $appearance.age || "Adult">></p> <<if !_sameAge>> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> _ageValue</p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _ageFinalChance >= 70>>#2ecc71<<elseif _ageFinalChance >= 50>>#51cf66<<elseif _ageFinalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;">_ageFinalChance%</span></p> <<else>> <p style="margin: 0; font-size: 13px; color: #888; font-style: italic;">Already the same</p> <</if>> </div> <<if _sameAge>> <div style='background: #95a5a6; color: #666; padding: 8px 12px; border-radius: 4px; text-align: center; font-size: 14px; font-weight: bold;'>Already Same Age</div> <<else>> <<link "<div style='background: #3498db; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Swap Age</div>">> <<set $selectedTrait = "age">> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> </div> </div> <!-- TRAITS SECTION --> <<set _allTraits = []>> <<set _allTraits = _allTraits.concat($currentTarget.physicalTraits)>> <<if $traitScanner || $physicalTraits.includes("Sunfish") || $mentalTraits.includes("Sunfish") || $currentArtifact === "The Crowd's Eye">> <<set _allTraits = _allTraits.concat($currentTarget.mentalTraits)>> <<set _allTraits = _allTraits.concat($currentTarget.skills)>> <</if>> <<if _allTraits.length > 0>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 12px 0; font-size: 18px;">Available Traits & Skills:</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px;"> <<for _i = 0; _i < _allTraits.length; _i++>> <<set _trait = _allTraits[_i]>> /* Skip hair length traits since hair length is a body part option */ <<set _isHairLengthTrait = (_trait === "Long Hair" || _trait === "Short Hair")>> /* Check if player already has this exact trait */ <<set _playerHasExact = $physicalTraits.includes(_trait) || $mentalTraits.includes(_trait) || $skills.includes(_trait)>> /* Check if trait is blocked by current transformation */ <<set _blockedByTransform = setup.isTraitBlockedByTransformation && (setup.isTraitBlockedByTransformation(_trait, "physical") || setup.isTraitBlockedByTransformation(_trait, "mental"))>> /* Only show if player doesn't already have it, it's not a hair length trait, it's not blacklisted, and not blocked by transformation */ <<if !_playerHasExact && !_isHairLengthTrait && !setup.unstealableTraits.includes(_trait) && !_blockedByTransform>> /* Check for conflicts with player's traits */ <<set _playerAllTraits = $physicalTraits.concat($mentalTraits)>> <<set _conflict = setup.getConflictingTrait(_trait, _playerAllTraits)>> /* Get trait value and success chance */ <<set _traitModifier = setup.getTraitValueModifier(_trait)>> <<set _finalChance = Math.max(_minChance, Math.min(95, _baseChance + _traitModifier))>> <<set _traitValue = setup.getTraitValue('physical', _trait)>> <<if _traitValue === 15>> <<set _traitValue = setup.getTraitValue('mental', _trait)>> <</if>> <<if _traitValue === 15>> <<set _traitValue = setup.getTraitValue('skill', _trait)>> <</if>> /* Check for theft bonuses */ <<set _bonusPercent = 0>> <<if setup.theftBonusTraits && setup.theftBonusTraits[_trait]>> <<set _bonusPercent = setup.theftBonusTraits[_trait]>> <<elseif setup.theftBonusSkills && setup.theftBonusSkills[_trait]>> <<set _bonusPercent = setup.theftBonusSkills[_trait]>> <</if>> /* CRITICAL: Capture ALL variables used in this iteration */ <<capture _trait, _conflict, _traitValue, _finalChance, _bonusPercent>> <div style="background: #2a2a2a; padding: 12px; border-radius: 5px; border-left: 3px solid <<if _conflict>>#f39c12<<else>>#e74c3c<</if>>;"> <p style="margin: 0 0 8px 0; font-weight: bold; font-size: 15px; color: #fff;"> <<print _trait>> <<if _bonusPercent > 0>> <span style="color: #2ecc71; font-size: 12px;">(+<<print _bonusPercent>>% crime)</span> <</if>> </p> <div style="background: #1a1a1a; padding: 6px; border-radius: 3px; margin-bottom: 8px;"> <p style="margin: 0 0 3px 0; font-size: 13px; color: #aaa;"><b>Value:</b> <span style="color: <<if _traitValue < 0>>#ff6b6b<<elseif _traitValue <= 10>>#95a5a6<<elseif _traitValue <= 25>>#f39c12<<else>>#2ecc71<</if>>;"><<print _traitValue>></span></p> <p style="margin: 0; font-size: 14px; font-weight: bold;"><b>Success:</b> <span style="color: <<if _finalChance >= 70>>#2ecc71<<elseif _finalChance >= 50>>#51cf66<<elseif _finalChance >= 30>>#f39c12<<else>>#ff6b6b<</if>>;"><<print _finalChance>>%</span></p> </div> <<if _conflict>> <p style="margin: 0 0 8px 0; font-size: 13px; color: #f39c12;"> ⚠️ Will replace your: <b><<print _conflict>></b> </p> <<set _swapButtonText = "Swap for " + _conflict>> <<link "<div style='background: #f39c12; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>_swapButtonText</div>">> <<set $selectedTrait = _trait>> <<set $swappingTrait = _conflict>> <<goto "AttemptTraitTheft">> <</link>> <<else>> <<link "<div style='background: #e74c3c; color: white; padding: 8px 12px; border-radius: 4px; text-align: center; cursor: pointer; font-size: 14px; font-weight: bold;'>Steal This</div>">> <<set $selectedTrait = _trait>> <<set $swappingTrait = null>> <<goto "AttemptTraitTheft">> <</link>> <</if>> </div> <</capture>> <</if>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 15px;"> <p style="color: #888; margin: 0; font-style: italic; font-size: 15px;">No additional traits available to steal from this target.</p> </div> <</if>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #95a5a6; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-size: 15px;'>← Back to Target</div>">> <<goto "ScoutForTarget">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.resetOjouRefinement()>> <<set _successChance = setup.calculateTheftChance($currentCrimeLocation)>> /* Check if stealing body part or trait */ <<set _isBodyPart = ["chest", "butt", "hairColor", "gender", "genitals", "ageCategory"].includes($selectedTrait)>> <<if _isBodyPart>> /* Get body part value based on type */ <<if $selectedTrait === "chest">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'chest', $currentTarget.bodyParts.chest)>> <<elseif $selectedTrait === "butt">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'butt', $currentTarget.bodyParts.butt)>> <<elseif $selectedTrait === "hairColor">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'hairColor')>> <<elseif $selectedTrait === "hairLength">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'hairLength')>> <<elseif $selectedTrait === "skinTone">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'skinTone')>> <<elseif $selectedTrait === "gender">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'gender')>> <<elseif $selectedTrait === "genitals">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'genitals', $currentTarget.bodyParts.genitals)>> <<elseif $selectedTrait === "age" || $selectedTrait === "ageCategory">> <<set _bodyPartValue = setup.getTraitValue('bodyPart', 'age')>> <<else>> <<set _bodyPartValue = 15>> <</if>> <<set _traitValueModifier = setup.getTraitValueModifier($selectedTrait, _bodyPartValue)>> <<else>> /* Regular trait - get modifier */ <<set _traitValueModifier = setup.getTraitValueModifier($selectedTrait)>> <</if>> <<set _successChance += _traitValueModifier>> /* ===== Determine minimum chance ===== */ <<set _minChance = 0>> /* ===== SKILL TREE: Steal Min Chance ===== */ <<set _skillTreeMinChance = setup.skillTree.getEffect("stealMinChance")>> <<if _skillTreeMinChance > 0>> <<set _minChance = Math.max(_minChance, _skillTreeMinChance)>> <</if>> <<set _successChance = Math.max(_minChance, Math.min(95, _successChance))>> <<set _roll = random(1, 100)>> <<set _success = _roll <= _successChance>> <<run advanceTime(random(15, 45))>> <<if _success>> <<set _witnessed = setup.checkWitnesses($currentCrimeLocation)>> <<set _policeShown = false>> <<if _witnessed>> <<set $crimeSystem.witnessedCrimes += 1>> <<set _policeShown = setup.checkOfficerPatrol($currentCrimeLocation)>> <</if>> <<if _policeShown>> <<goto "CaughtByPolice">> <<else>> <<goto "TraitTheftSuccess">> <</if>> <<else>> <<set $crimeSystem.failedThefts += 1>> <<set $crimeSystem.totalThefts += 1>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 10)>> <<set _policeShown = setup.checkOfficerPatrol($currentCrimeLocation)>> <<if _policeShown>> <<goto "CaughtByPolice">> <</if>> <</if>> <<if !_isBodyPart>> <<set _traitValue = setup.getTraitValue('physical', $selectedTrait)>> <<if _traitValue === 15>> <<set _traitValue = setup.getTraitValue('mental', $selectedTrait)>> <</if>> <<if _traitValue === 15>> <<set _traitValue = setup.getTraitValue('skill', $selectedTrait)>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #e74c3c; text-align: center; margin: 10px 0; font-size: 28px;">🎯 Theft Failed</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Target: $currentTarget.name</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #e74c3c;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 18px;">Attempt Details</h3> <<if _isBodyPart>> <p style="margin: 5px 0; font-size: 15px;"><b>Attempted to Steal:</b> <<if $selectedTrait === "chest">>Chest Size <<elseif $selectedTrait === "butt">>Butt Size <<elseif $selectedTrait === "hairColor">>Hair Color <<elseif $selectedTrait === "gender">>Gender <<elseif $selectedTrait === "genitals">>Genitals <<elseif $selectedTrait === "ageCategory">>Age Category <</if>> </p> <<else>> <p style="margin: 5px 0; font-size: 15px;"><b>Attempted to Steal:</b> $selectedTrait</p> <</if>> <<if $swappingTrait>> <p style="margin: 5px 0; font-size: 15px; color: #f39c12;"><b>Swapping for:</b> $swappingTrait</p> <</if>> <<if !_isBodyPart && _traitValue !== undefined>> <p style="margin: 5px 0; font-size: 15px;"><b>Trait Value:</b> <span style="color: <<if _traitValue < 0>>#ff6b6b<<elseif _traitValue <= 10>>#95a5a6<<elseif _traitValue <= 25>>#f39c12<<else>>#2ecc71<</if>>;">_traitValue</span></p> <p style="margin: 5px 0; font-size: 15px;"><b>Difficulty Modifier:</b> <span style="color: <<if _traitValueModifier > 0>>#2ecc71<<elseif _traitValueModifier < 0>>#ff6b6b<<else>>#95a5a6<</if>>;"><<if _traitValueModifier > 0>>+<</if>>_traitValueModifier% <<if _traitValue < 0>>(Easier)<<elseif _traitValue <= 10>>(Normal)<<elseif _traitValue <= 25>>(Hard)<<elseif _traitValue <= 50>>(Very Hard)<<else>>(Extremely Hard)<</if>></span></p> <</if>> <p style="margin: 5px 0; font-size: 15px;"><b>Success Chance:</b> <span style="color: <<if _successChance >= 50>>#2ecc71<<elseif _successChance >= 25>>#f39c12<<else>>#ff6b6b<</if>>;">_successChance%</span> <<if _minChance > 0>> <span style="color: #9C27B0; font-size: 13px;">(min: _minChance%)</span> <</if>> </p> <p style="margin: 5px 0; font-size: 15px;"><b>Your Roll:</b> _roll</p> </div> <div style="background: linear-gradient(135deg, #c0392b 0%, #e74c3c 100%); color: white; padding: 12px; border-radius: 5px; margin-bottom: 15px; font-weight: bold; text-align: center; font-size: 15px;"> ✗ ATTEMPT FAILED! </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 15px;">Your attempt failed! The target noticed something was off and moved away before you could complete the theft.</p> <<if !_isBodyPart && _traitValue !== undefined && _traitValue > 25>> <p style="color: #f39c12; margin: 0; font-size: 14px; font-style: italic;">The trait was too valuable and well-protected to steal easily...</p> <</if>> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #ff6b6b;"> <p style="color: #ff6b6b; margin: 0; font-size: 15px;"><b>Heat Level:</b> +10% (Now: $crimeSystem.heatLevel%)</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>← Leave the Area</div>">> <<goto "CrimeHub">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* Apply the theft */ <<set $crimeSystem.successfulThefts += 1>> <<set $crimeSystem.totalThefts += 1>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 5)>> /* Achievement for stealing a trait successfully */ <<run setup.achievements.unlock("steal_trait_success")>> /* ===== SKILL TREE: Steal Money Bonus ===== */ <<set _stealMoneyBonus = setup.skillTree.getEffect("stealMoneyBonus")>> <<if _stealMoneyBonus > 0>> <<set $money += _stealMoneyBonus>> <</if>> <<set _isBodyPart = ["chest", "butt", "hairColor", "hairLength", "skinTone", "age", "gender", "genitals"].includes($selectedTrait)>> <<if _isBodyPart>> /* Swapping body parts */ <<if $selectedTrait === "chest">> <<set _temp = $bodyParts.chest>> <<set $bodyParts.chest = $currentTarget.bodyParts.chest>> <<set $currentTarget.bodyParts.chest = _temp>> <<set _swappedFrom = _temp>> <<set _swappedTo = $bodyParts.chest>> <<set _displayName = "Chest Size">> <<elseif $selectedTrait === "butt">> <<set _temp = $bodyParts.butt>> <<set $bodyParts.butt = $currentTarget.bodyParts.butt>> <<set $currentTarget.bodyParts.butt = _temp>> <<set _swappedFrom = _temp>> <<set _swappedTo = $bodyParts.butt>> <<set _displayName = "Butt Size">> <<elseif $selectedTrait === "hairColor">> <<set _temp = $appearance.hairColor>> <<set $appearance.hairColor = $currentTarget.appearance.hairColor>> <<set $currentTarget.appearance.hairColor = _temp>> <<set _swappedFrom = _temp>> <<set _swappedTo = $appearance.hairColor>> <<set _displayName = "Hair Color">> <<elseif $selectedTrait === "hairLength">> /* Swap hair length value only (no traits involved) */ <<set _temp = $appearance.hairLength>> <<set $appearance.hairLength = $currentTarget.appearance.hairLength>> <<set $currentTarget.appearance.hairLength = _temp>> <<set _swappedFrom = _temp>> <<set _swappedTo = $appearance.hairLength>> <<set _displayName = "Hair Length">> <<elseif $selectedTrait === "skinTone">> <<set _temp = $appearance.skinTone>> <<set $appearance.skinTone = $currentTarget.appearance.skinTone>> <<set $currentTarget.appearance.skinTone = _temp>> <<set _swappedFrom = _temp>> <<set _swappedTo = $appearance.skinTone>> <<set _displayName = "Skin Tone">> <<elseif $selectedTrait === "age">> /* Swap age value */ <<set _temp = $appearance.age || "Adult">> <<set _targetAge = $currentTarget.appearance.age || "Adult">> <<set $appearance.age = _targetAge>> <<set $currentTarget.appearance.age = _temp>> /* Swap age traits (Mature / Youthful) */ <<set _playerHadMature = $physicalTraits.includes("Mature")>> <<set _playerHadYouthful = $physicalTraits.includes("Youthful")>> <<set _targetHadMature = $currentTarget.physicalTraits.includes("Mature")>> <<set _targetHadYouthful = $currentTarget.physicalTraits.includes("Youthful")>> /* Remove old traits from both */ <<run $physicalTraits.delete("Mature")>> <<run $physicalTraits.delete("Youthful")>> <<run $currentTarget.physicalTraits.delete("Mature")>> <<run $currentTarget.physicalTraits.delete("Youthful")>> /* Add swapped traits */ <<if _targetHadMature>> <<run $physicalTraits.push("Mature")>> <</if>> <<if _targetHadYouthful>> <<run $physicalTraits.push("Youthful")>> <</if>> <<if _playerHadMature>> <<run $currentTarget.physicalTraits.push("Mature")>> <</if>> <<if _playerHadYouthful>> <<run $currentTarget.physicalTraits.push("Youthful")>> <</if>> <<set _swappedFrom = _temp>> <<set _swappedTo = $appearance.age>> <<set _displayName = "Age">> <<elseif $selectedTrait === "gender">> /* Block gender swap to male for all TFs except Himbo */ <<if $currentTarget.bodyParts.gender === "male" && setup.isMaleGenderBlocked()>> <<set _swappedFrom = $bodyParts.gender>> <<set _swappedTo = $bodyParts.gender>> <<set _displayName = "Gender (blocked by transformation)">> <<else>> <<set _temp = $bodyParts.gender>> <<set $bodyParts.gender = $currentTarget.bodyParts.gender>> <<set $currentTarget.bodyParts.gender = _temp>> /* CRITICAL: Also update $gender variable for job compatibility */ <<set $gender = $bodyParts.gender>> /* Update gender-mismatch traits for both player and target */ <<run setup.updateGenderMismatchTraits()>> <<run setup.updateGenderMismatchTraits($currentTarget)>> <<set _swappedFrom = _temp>> <<set _swappedTo = $bodyParts.gender>> <<set _displayName = "Gender">> <</if>> <<elseif $selectedTrait === "genitals">> /* Block genital swap to male genitals or both for blocked transformations */ <<set _targetGenIsPenis = ($currentTarget.bodyParts.genitals === "penis" || $currentTarget.bodyParts.genitals === "big penis" || $currentTarget.bodyParts.genitals === "small penis" || $currentTarget.bodyParts.genitals === "both")>> <<if _targetGenIsPenis && setup.isFutanariBlocked()>> <<set _swappedFrom = $bodyParts.genitals>> <<set _swappedTo = $bodyParts.genitals>> <<set _displayName = "Genitals (blocked by transformation)">> <<else>> <<set _temp = $bodyParts.genitals>> <<set $bodyParts.genitals = $currentTarget.bodyParts.genitals>> <<set $currentTarget.bodyParts.genitals = _temp>> /* Update gender-mismatch traits for both player and target */ <<run setup.updateGenderMismatchTraits()>> <<run setup.updateGenderMismatchTraits($currentTarget)>> /* Check Futanari consistency after genital swap */ <<run setup.checkFutanariConsistency()>> <<run setup.checkFutanariConsistency($currentTarget)>> <<set _swappedFrom = _temp>> <<set _swappedTo = $bodyParts.genitals>> <<set _displayName = "Genitals">> <</if>> <</if>> <<else>> /* Regular trait theft */ <<if $swappingTrait>> /* Swapping traits */ <<if $physicalTraits.includes($swappingTrait)>> <<set _idx = $physicalTraits.indexOf($swappingTrait)>> <<run $physicalTraits.splice(_idx, 1)>> <<elseif $mentalTraits.includes($swappingTrait)>> <<set _idx = $mentalTraits.indexOf($swappingTrait)>> <<run $mentalTraits.splice(_idx, 1)>> <</if>> <</if>> /* Add the stolen trait with conflict checking */ <<set _allPlayerTraits = $physicalTraits.concat($mentalTraits)>> <<set _conflictTrait = setup.getConflictingTrait($selectedTrait, _allPlayerTraits)>> <<if _conflictTrait>> <!-- Remove conflicting trait first --> <<if $physicalTraits.includes(_conflictTrait)>> <<run $physicalTraits.delete(_conflictTrait)>> <<elseif $mentalTraits.includes(_conflictTrait)>> <<run $mentalTraits.delete(_conflictTrait)>> <</if>> <<set _replacedConflict = _conflictTrait>> <</if>> <<if $currentTarget.physicalTraits.includes($selectedTrait)>> <<run $physicalTraits.push($selectedTrait)>> <<elseif $currentTarget.mentalTraits.includes($selectedTrait)>> <<run $mentalTraits.push($selectedTrait)>> <<elseif $currentTarget.skills.includes($selectedTrait)>> <<run $skills.push($selectedTrait)>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #2ecc71; text-align: center; margin: 10px 0; font-size: 28px;">✓ SUCCESS!</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Theft Completed</h2> <div style="background: #1a4d1a; border: 2px solid #2ecc71; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0; font-size: 18px;">Successful Theft!</h3> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;">You successfully stole from $currentTarget.name!</p> <div style="background: rgba(0,0,0,0.3); padding: 12px; border-radius: 5px; margin: 10px 0;"> <<if _isBodyPart>> <p style="color: #2ecc71; margin: 0; font-size: 16px; font-weight: bold;">✓ Swapped <<print _displayName>></p> <p style="color: #888; margin: 8px 0 0 0; font-size: 14px;"><<print _swappedFrom>> → <<print _swappedTo>></p> <<else>> <p style="color: #2ecc71; margin: 0; font-size: 16px; font-weight: bold;">✓ Gained: $selectedTrait</p> <<if $swappingTrait>> <p style="color: #f39c12; margin: 8px 0 0 0; font-size: 16px; font-weight: bold;">↔ Lost: $swappingTrait</p> <</if>> <</if>> </div> <p style="color: #ff6b6b; margin: 10px 0 0 0; font-size: 14px;"><b>Heat Level:</b> +5% (Now: $crimeSystem.heatLevel%)</p> <!-- ===== SKILL TREE: Steal Money Bonus Display ===== --> <<if _stealMoneyBonus > 0>> <p style="color: #9C27B0; margin: 10px 0 0 0; font-size: 14px;"><b>⭐ Skill Tree Bonus:</b> +$<<print _stealMoneyBonus>> cash</p> <</if>> </div> <!-- TRANSFORMATION DESCRIPTIONS SECTION --> <div style="background: #2a2a2a; padding: 20px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0; font-size: 18px;">🔄 Transformation</h3> <<if _isBodyPart>> <!-- Body Part Transformations --> <<if $selectedTrait === "chest">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getChestTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <<elseif $selectedTrait === "butt">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getButtTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <<elseif $selectedTrait === "gender">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getGenderTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <<elseif $selectedTrait === "genitals">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getGenitalTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <!-- Check for special trait acquisition --> <<if $physicalTraits.includes("Cuntboy")>> <div style="background: #3a2030; border: 2px solid #9b59b6; padding: 12px; margin-top: 10px; border-radius: 6px;"> <p style="color: #9b59b6; margin: 0; font-weight: bold; font-size: 14px;"> ✨ You've gained the "Cuntboy" trait - a male with a vagina! </p> </div> <<elseif $physicalTraits.includes("Dickgirl")>> <div style="background: #3a2030; border: 2px solid #9b59b6; padding: 12px; margin-top: 10px; border-radius: 6px;"> <p style="color: #9b59b6; margin: 0; font-weight: bold; font-size: 14px;"> ✨ You've gained the "Dickgirl" trait - a female with a penis! </p> </div> <<elseif $physicalTraits.includes("Futanari")>> <div style="background: #3a2030; border: 2px solid #e84393; padding: 12px; margin-top: 10px; border-radius: 6px;"> <p style="color: #e84393; margin: 0; font-weight: bold; font-size: 14px;"> ✨ You've gained the "<<print setup.getFutaDisplayName()>>" trait - you have both male and female genitalia! </p> <p style="color: #ccc; margin: 10px 0 0 0; font-size: 13px; line-height: 1.6;"> <<print setup.getFutaFlavorText("post_swap_gain")>> </p> </div> <</if>> <<elseif $selectedTrait === "age">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getAgeTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <<elseif $selectedTrait === "hairColor">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getHairColorTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <<elseif $selectedTrait === "hairLength">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getHairLengthTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <<elseif $selectedTrait === "skinTone">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getSkinToneTransformationText(_swappedFrom, _swappedTo)>> </p> </div> <</if>> <<else>> <!-- Regular Trait Theft --> <<if $currentTarget.physicalTraits.includes($selectedTrait)>> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<if $swappingTrait && setup.getConflictingTrait($selectedTrait, [$swappingTrait]) === $swappingTrait>> <<print setup.getMutuallyExclusiveSwapText($swappingTrait, $selectedTrait)>> <<else>> <<print setup.getPhysicalTraitChangeText($selectedTrait, true)>> <</if>> </p> </div> <!-- Special transformations --> <<if $selectedTrait === "Were-Creature">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-top: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getWereCreatureTransformationText(true, "wolf")>> </p> </div> <<elseif $selectedTrait === "Definitely not a Vampire">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-top: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getVampireTransformationText(true)>> </p> </div> <<elseif $selectedTrait === "Sunfish">> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-top: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getSunfishTransformationText(true)>> </p> </div> <</if>> <!-- Lost trait description if swapping --> <<if $swappingTrait>> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-top: 10px; border: 2px solid #f39c12;"> <p style="color: #f39c12; font-size: 14px; font-weight: bold; margin: 0 0 8px 0;">Lost Trait:</p> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getPhysicalTraitChangeText($swappingTrait, false)>> </p> </div> <</if>> <<elseif $currentTarget.mentalTraits.includes($selectedTrait)>> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<if $swappingTrait && setup.getConflictingTrait($selectedTrait, [$swappingTrait]) === $swappingTrait>> <<print setup.getMutuallyExclusiveSwapText($swappingTrait, $selectedTrait)>> <<else>> <<print setup.getMentalTraitChangeText($selectedTrait, true)>> <</if>> </p> </div> <!-- Lost trait description if swapping --> <<if $swappingTrait>> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-top: 10px; border: 2px solid #f39c12;"> <p style="color: #f39c12; font-size: 14px; font-weight: bold; margin: 0 0 8px 0;">Lost Trait:</p> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getMentalTraitChangeText($swappingTrait, false)>> </p> </div> <</if>> <<elseif $currentTarget.skills.includes($selectedTrait)>> <div style="background: #1a1a1a; padding: 15px; border-radius: 6px; margin-bottom: 10px;"> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"> <<print setup.getSkillGainText($selectedTrait)>> </p> </div> <</if>> <</if>> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Crime Statistics</h3> <p style="margin: 5px 0; font-size: 15px;"><b>Total Thefts:</b> $crimeSystem.totalThefts</p> <p style="margin: 5px 0; font-size: 15px;"><b>Success Rate:</b> <<print Math.round(($crimeSystem.successfulThefts / $crimeSystem.totalThefts) * 100)>>%</p> </div> <<if $crimeSystem.heatLevel >= 80>> <div style="background: #4d1a1a; padding: 12px; border-radius: 5px; border-left: 4px solid #ff6b6b; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px; font-weight: bold;">⚠️ WARNING: Heat level critically high! Police are actively searching for you.</p> </div> <</if>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>Leave the Area</div>">> <<goto "CrimeHub">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$jailSystem>> <<set $jailSystem = { inJail: false, daysToServe: 0, daysServed: 0, canPayFine: false, fineAmount: 0, previousJob: "" }>> <</if>> /* Check arrest type */ <<set _atStation = $arrestedAtStation || false>> <<set _arrestType = $arrestType || "crime">> <<set $arrestedAtStation = false>> <<set $arrestType = "">> /* Store previous job and become Criminal IMMEDIATELY when caught */ <<if $jobs && $jobs.length > 0 && !$jobs.includes("Criminal")>> <<set $jailSystem.previousJob = $jobs[0]>> <<elseif !$jailSystem.previousJob>> <<set $jailSystem.previousJob = "Unemployed">> <</if>> <<if !$jobs.includes("Criminal")>> <<set $jobs = ["Criminal"]>> <</if>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 25)>> <<set $crimeSystem.activeWarrant = true>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #ff6b6b; text-align: center; margin: 10px 0; font-size: 28px;">🚔 CAUGHT!</h1> <<if _arrestType === "streaming">> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Tracked Through Your Stream</h2> <<elseif _arrestType === "adultStreaming">> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Identified on Adult Platform</h2> <<elseif _arrestType === "jobApplication">> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Background Check Failed</h2> <<elseif _atStation>> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Arrested at Police Station</h2> <<else>> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Police Officer on Scene</h2> <</if>> <div style="background: #4d1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <<if _arrestType === "streaming">> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> "POLICE! OPEN UP! We have you surrounded!" </p> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> You're just about to start your stream when you hear pounding on your apartment door. Before you can react, police burst in with a battering ram. "We traced your IP address from your streaming activity. You're wanted for multiple crimes!" Officers swarm your apartment, cutting off any escape routes. Your hands are cuffed behind your back as they read you your rights. </p> <<elseif _arrestType === "adultStreaming">> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> "THIS IS THE POLICE! We have a warrant for your arrest!" </p> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> As you set up your webcam for an adult stream, your apartment door explodes inward. A SWAT team floods in, weapons drawn. "Freeze! We've been monitoring your online activity and traced your location through the streaming platform!" There's nowhere to run as officers surround you from all sides. You're tackled to the ground and restrained before you can even think about escaping. </p> <<elseif _arrestType === "jobApplication">> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> "Don't move! You're under arrest!" </p> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> Hours after submitting your job application, you hear a knock at your door. Thinking it might be about the job, you open it - only to find yourself face-to-face with armed police officers. "The cafe ran your background check and immediately flagged you as a wanted criminal. We've had this place surrounded since you got home." Officers rush in from the stairwell and fire escape, blocking every exit. You're handcuffed without a chance to resist. </p> <<elseif _atStation>> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> "Hold it right there! You have an outstanding warrant!" </p> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> You walked right into the police station with a criminal record. Officers immediately recognize you and move to arrest you. There's no escape from here. </p> <<else>> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> "Freeze! You're under arrest for attempted theft!" </p> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> A police officer appears and has caught you in the act. You have two choices: surrender peacefully or try to escape. </p> <</if>> </div> <<if $jailSystem.previousJob && $jailSystem.previousJob !== "Unemployed" && $jailSystem.previousJob !== "Criminal">> <div style="background: #3a2020; border: 2px solid #ff6b6b; padding: 12px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px; font-weight: bold;"> ✗ You've lost your job as $jailSystem.previousJob and are now a Criminal! </p> </div> <</if>> <<set _canResist = !_atStation && _arrestType === "crime">> <<set _escapeChance = setup.calculateEscapeChance()>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Your Options:</h3> <div style="background: #1a1a1a; padding: 12px; border-radius: 5px; margin-bottom: 10px; border-left: 3px solid #95a5a6;"> <h4 style="color: #95a5a6; margin: 0 0 8px 0; font-size: 15px;">1. Surrender Peacefully</h4> <p style="color: #ccc; margin: 0 0 8px 0; font-size: 14px;">Accept arrest and face reduced penalties.</p> <ul style="color: #aaa; font-size: 13px; margin: 5px 0; padding-left: 20px;"> <li>Pay fine: $2,500</li> <li>Must serve time or pay fine at jail</li> <li>Heat +25%</li> </ul> </div> <<if _canResist>> <div style="background: #1a1a1a; padding: 12px; border-radius: 5px; border-left: 3px solid #e74c3c;"> <h4 style="color: #e74c3c; margin: 0 0 8px 0; font-size: 15px;">2. Resist Arrest (Escape Chance: _escapeChance%)</h4> <p style="color: #ccc; margin: 0 0 8px 0; font-size: 14px;">Try to fight or run away from the officer.</p> <p style="color: #2ecc71; font-size: 13px; margin: 5px 0;"><b>If successful:</b> Escape with +15% heat (must still visit jail later)</p> <p style="color: #ff6b6b; font-size: 13px; margin: 5px 0;"><b>If caught:</b></p> <ul style="color: #aaa; font-size: 13px; margin: 5px 0; padding-left: 20px;"> <li>Pay fine: $5,000</li> <li>Sent directly to jail</li> <li>Heat +40%</li> </ul> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 5px; border-left: 3px solid #666; opacity: 0.5;"> <h4 style="color: #666; margin: 0 0 8px 0; font-size: 15px;">2. Resist Arrest (UNAVAILABLE)</h4> <<if _arrestType === "streaming" || _arrestType === "adultStreaming" || _arrestType === "jobApplication">> <p style="color: #888; margin: 0 0 8px 0; font-size: 14px;">They've surrounded your apartment - there's no way out.</p> <p style="color: #666; font-size: 12px; margin: 0; font-style: italic;">Police have blocked all exits - resistance is futile</p> <<else>> <p style="color: #888; margin: 0 0 8px 0; font-size: 14px;">You can't escape from inside the police station.</p> <p style="color: #666; font-size: 12px; margin: 0; font-style: italic;">Surrounded by officers - escape is impossible</p> <</if>> </div> <</if>> </div> <div style="text-align: center; margin: 15px 0;"> <<link "<div style='display: inline-block; background: #95a5a6; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3); font-size: 16px;'>Surrender Peacefully</div>">> <<goto "SurrenderArrest">> <</link>> </div> <<if _canResist>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3); font-size: 16px;'>Resist Arrest</div>">> <<goto "ResistArrest">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<if !$jailSystem>> <<set $jailSystem = { inJail: false, daysToServe: 0, daysServed: 0, canPayFine: false, fineAmount: 0, previousJob: "" }>> <</if>> /* Reset consecutive escapes counter */ <<if !$crimeSystem.consecutiveEscapes>> <<set $crimeSystem.consecutiveEscapes = 0>> <</if>> <<set $crimeSystem.consecutiveEscapes = 0>> <<set $crimeSystem.surrenderCount += 1>> <<set $crimeSystem.arrestCount += 1>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 25)>> /* Store previous job before becoming Criminal */ <<if $jobs && $jobs.length > 0 && !$jobs.includes("Criminal")>> <<set $jailSystem.previousJob = $jobs[0]>> <<if $jobs[0] !== "Unemployed">> <<set _lostJob = true>> <<set _previousJobName = $jobs[0]>> <<else>> <<set _lostJob = false>> <</if>> <<elseif !$jailSystem.previousJob>> <<set $jailSystem.previousJob = "Unemployed">> <<set _lostJob = false>> <</if>> <<set $jobs = ["Criminal"]>> <<set $crimeSystem.crimesCommitted = ($crimeSystem.crimesCommitted || 0) + 1>> /* Pay fine - take from cash first, remainder from bank (can go negative) */ <<set _fineOwed = 2500>> <<if $money >= _fineOwed>> <<set $money -= _fineOwed>> <<else>> <<set _fineOwed -= $money>> <<set $money = 0>> <<if $bankAccount && $bankAccount.hasAccount>> <<set $bankAccount.balance -= _fineOwed>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #95a5a6; text-align: center; margin: 10px 0; font-size: 28px;">⚖️ Arrested</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Surrendered Peacefully</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #95a5a6;"> <p style="color: #ccc; margin: 0 0 12px 0; font-size: 15px;"> You put your hands up and allow the officer to arrest you. The process is professional and without incident. </p> <div style="background: #1a1a1a; padding: 12px; border-radius: 5px; margin: 10px 0;"> <h4 style="color: #ff6b6b; margin: 0 0 10px 0; font-size: 16px;">Consequences:</h4> <<if _lostJob>> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Lost job: _previousJobName</p> <p style="color: #f39c12; margin: 5px 0; font-size: 15px;">→ Forced into Criminal career</p> <<else>> <p style="color: #f39c12; margin: 5px 0; font-size: 15px;">→ Forced into Criminal career</p> <</if>> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Fine paid: $2,500</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Crimes committed: +1</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Must serve jail time or pay fine</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Heat: +25% (Now: $crimeSystem.heatLevel%)</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Escape streak reset!</p> </div> <p style="color: #888; margin: 12px 0 0 0; font-size: 14px; font-style: italic;"> You're being taken into custody. Time to face the consequences. </p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #e74c3c;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Criminal Record Updated</h3> <p style="margin: 5px 0; font-size: 15px;"><b>Times Arrested:</b> $crimeSystem.arrestCount</p> <p style="margin: 5px 0; font-size: 15px;"><b>Times Surrendered:</b> $crimeSystem.surrenderCount</p> <p style="margin: 5px 0; font-size: 15px;"><b>Heat Level:</b> $crimeSystem.heatLevel/100</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>Go to Jail</div>">> <<goto "Jail">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _escapeChance = setup.calculateEscapeChance()>> <<set _roll = random(1, 100)>> <<set _escaped = _roll <= _escapeChance>> <<set $crimeSystem.resistedArrestCount += 1>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #e74c3c; text-align: center; margin: 10px 0; font-size: 28px;">🏃 Resisting Arrest!</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Attempting Escape</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="margin: 5px 0; font-size: 15px;"><b>Escape Chance:</b> _escapeChance%</p> <p style="margin: 5px 0; font-size: 15px;"><b>Your Roll:</b> _roll</p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #e74c3c;"> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> You make a break for it, adrenaline pumping through your veins as you try to outrun the officer... </p> </div> <<if _escaped>> <<goto "EscapeSuccess">> <<else>> <<goto "EscapeFailed">> <</if>> </div> <</nobr>>
<<nobr>> <<if !$jailSystem>> <<set $jailSystem = { inJail: false, daysToServe: 0, daysServed: 0, canPayFine: false, fineAmount: 0, previousJob: "" }>> <</if>> <<if !$crimeSystem>> <<set $crimeSystem = { warnings: 0, witnessedCrimes: 0, totalThefts: 0, successfulThefts: 0, failedThefts: 0, arrestCount: 0, resistedArrestCount: 0, surrenderCount: 0, lastCrimeLocation: "", lastCrimeTime: "", heatLevel: 0, activeWarrant: false, lastHeatDecayDay: 0, crimesCommitted: 0, consecutiveEscapes: 0 }>> <</if>> /* Reset consecutive escapes counter */ <<set $crimeSystem.consecutiveEscapes = 0>> /* Update crime statistics */ <<set $crimeSystem.arrestCount += 1>> <<set $crimeSystem.resistedArrestCount += 1>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 40)>> <<set $crimeSystem.crimesCommitted = ($crimeSystem.crimesCommitted || 0) + 2>> /* Store previous job before becoming Criminal */ <<set _lostJob = false>> <<set _previousJobName = "">> <<if $jobs && Array.isArray($jobs) && $jobs.length > 0>> <<if !$jobs.includes("Criminal")>> <<set $jailSystem.previousJob = $jobs[0]>> <<if $jobs[0] !== "Unemployed">> <<set _lostJob = true>> <<set _previousJobName = $jobs[0]>> <</if>> <<set $jobs = ["Criminal"]>> <</if>> <<else>> <<set $jobs = ["Criminal"]>> <<set $jailSystem.previousJob = "Unemployed">> <</if>> /* Pay harsher fine - take from cash first, remainder from bank (can go negative) */ <<set _fineOwed = 5000>> <<if $money >= _fineOwed>> <<set $money -= _fineOwed>> <<else>> <<set _fineOwed -= $money>> <<set $money = 0>> <<if $bankAccount && $bankAccount.hasAccount>> <<set $bankAccount.balance -= _fineOwed>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #ff6b6b; text-align: center; margin: 10px 0; font-size: 28px;">✗ CAUGHT!</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Escape Failed</h2> <div style="background: #4d1a1a; border: 2px solid #e74c3c; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 18px;">Subdued and Arrested</h3> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> The officer catches up to you and tackles you to the ground. You're arrested and charged with resisting arrest in addition to attempted theft. </p> <div style="background: rgba(0,0,0,0.3); padding: 12px; border-radius: 5px; margin: 10px 0;"> <h4 style="color: #ff6b6b; margin: 0 0 10px 0; font-size: 16px;">HARSH Consequences:</h4> <<if _lostJob>> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Lost job: _previousJobName</p> <p style="color: #f39c12; margin: 5px 0; font-size: 15px;">→ Forced into Criminal career</p> <<else>> <p style="color: #f39c12; margin: 5px 0; font-size: 15px;">→ Forced into Criminal career</p> <</if>> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Fine paid: $5,000</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Crimes committed: +2</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Must serve jail time or pay fine</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Heat: +40% (Now: $crimeSystem.heatLevel%)</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Escape streak reset!</p> </div> <p style="color: #888; margin: 12px 0 0 0; font-size: 14px; font-style: italic;"> You must now go to the jail to serve your sentence or pay the fine. </p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Criminal Record</h3> <p style="margin: 5px 0; font-size: 15px;"><b>Times Arrested:</b> $crimeSystem.arrestCount</p> <p style="margin: 5px 0; font-size: 15px;"><b>Resisted Arrest:</b> $crimeSystem.resistedArrestCount times</p> <p style="margin: 5px 0; font-size: 15px;"><b>Total Crimes:</b> $crimeSystem.crimesCommitted</p> <p style="margin: 5px 0; font-size: 15px;"><b>Heat Level:</b> $crimeSystem.heatLevel/100</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>Continue</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$jailSystem>> <<set $jailSystem = { inJail: false, daysToServe: 0, daysServed: 0, canPayFine: false, fineAmount: 0, previousJob: "" }>> <</if>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 15)>> /* Increment consecutive escapes counter */ <<if !$crimeSystem.consecutiveEscapes>> <<set $crimeSystem.consecutiveEscapes = 0>> <</if>> <<set $crimeSystem.consecutiveEscapes += 1>> /* Check for 5 escapes achievement */ <<if $crimeSystem.consecutiveEscapes >= 5>> <<run setup.achievements.unlock("evade_cops_5")>> <</if>> /* Store previous job and become Criminal */ <<if $jobs && $jobs.length > 0 && !$jobs.includes("Criminal")>> <<set $jailSystem.previousJob = $jobs[0]>> <<if $jobs[0] !== "Unemployed">> <<set _lostJob = true>> <<set _previousJobName = $jobs[0]>> <<else>> <<set _lostJob = false>> <</if>> <<elseif !$jailSystem.previousJob>> <<set $jailSystem.previousJob = "Unemployed">> <<set _lostJob = false>> <</if>> <<set $jobs = ["Criminal"]>> <<set $crimeSystem.crimesCommitted = ($crimeSystem.crimesCommitted || 0) + 1>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #2ecc71; text-align: center; margin: 10px 0; font-size: 28px;">✓ ESCAPED!</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Got Away Clean</h2> <div style="background: #1a4d1a; border: 2px solid #2ecc71; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0; font-size: 18px;">Successfully Escaped!</h3> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> You manage to lose the officer in the chaos! Your heart is pounding, but you're free. </p> <div style="background: rgba(0,0,0,0.3); padding: 12px; border-radius: 5px; margin: 10px 0;"> <<if _lostJob>> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;">✗ Lost job: _previousJobName</p> <p style="color: #f39c12; margin: 5px 0; font-size: 15px;">→ Now a Criminal (wanted)</p> <<else>> <p style="color: #f39c12; margin: 5px 0; font-size: 15px;">→ Now a Criminal (wanted)</p> <</if>> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;"><b>Crimes Committed:</b> +1</p> <p style="color: #ff6b6b; margin: 5px 0; font-size: 15px;"><b>Heat Level:</b> +15% (Now: $crimeSystem.heatLevel%)</p> <p style="color: #2ecc71; margin: 5px 0; font-size: 15px;"><b>Consecutive Escapes:</b> $crimeSystem.consecutiveEscapes</p> </div> <p style="color: #f39c12; margin: 12px 0 0 0; font-size: 14px; font-style: italic;"> ⚠️ You must visit the Jail to serve time or pay your fine before you can change jobs! </p> </div> <<if $crimeSystem.heatLevel >= 80>> <div style="background: #4d1a1a; padding: 12px; border-radius: 5px; border-left: 4px solid #ff6b6b; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px; font-weight: bold;">⚠️ CRITICAL: You're now a high-priority target for law enforcement!</p> </div> <</if>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #e74c3c;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Criminal Record Updated</h3> <p style="margin: 5px 0; font-size: 15px;"><b>Crimes Committed:</b> $crimeSystem.crimesCommitted</p> <p style="margin: 5px 0; font-size: 15px;"><b>Heat Level:</b> $crimeSystem.heatLevel/100</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>Get Out of Here</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _scannerChance = setup.attemptScannerTheft()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #3498db; text-align: center; margin: 10px 0; font-size: 28px;">👮 Officer Spotted!</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Patrol Officer Nearby</h2> <div style="background: #1e3a5f; border: 2px solid #3498db; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #fff; margin: 0 0 12px 0; font-size: 15px;"> You spot a police officer on patrol. They haven't noticed you yet, but you can see a <b>Trait Scanner</b> clipped to their belt... </p> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> This is an extremely risky move. The scanner would let you see all traits when stealing, but getting caught means immediate arrest. </p> </div> <<if !$traitScanner>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 16px;">Attempt to Steal Scanner</h3> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 15px;"><b>Success Chance:</b> <span style="color: <<if _scannerChance >= 30>>#2ecc71<<elseif _scannerChance >= 10>>#f39c12<<else>>#ff6b6b<</if>>;">_scannerChance%</span></p> <<if _scannerChance <= 5>> <div style="background: #4d1a1a; padding: 12px; border-radius: 5px; border-left: 4px solid #ff6b6b; margin-bottom: 10px;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px; font-weight: bold;">⚠️ NEARLY IMPOSSIBLE: You lack the skills and traits needed for this. You will almost certainly be caught!</p> </div> <<elseif _scannerChance <= 15>> <div style="background: #4d2a1a; padding: 12px; border-radius: 5px; border-left: 4px solid #f39c12; margin-bottom: 10px;"> <p style="color: #f39c12; margin: 0; font-size: 14px; font-weight: bold;">⚠️ VERY DIFFICULT: You have minimal chance of success. High risk of arrest!</p> </div> <</if>> <div style="background: #1a1a1a; padding: 10px; border-radius: 5px; margin: 10px 0;"> <p style="color: #aaa; margin: 0 0 8px 0; font-size: 14px;"><b>Bonuses:</b></p> <<set _totalDex = setup.getTotalStat("dexterity")>> <p style="color: #888; margin: 3px 0; font-size: 13px;">• Base Chance: 2%</p> <<if _totalDex >= 30>> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Dexterity ≥30: +10%</p> <<else>> <p style="color: #666; margin: 3px 0; font-size: 13px;">✗ Dexterity ≥30: +10%</p> <</if>> <<if _totalDex >= 50>> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Dexterity ≥50: +10%</p> <<else>> <p style="color: #666; margin: 3px 0; font-size: 13px;">✗ Dexterity ≥50: +10%</p> <</if>> <<if $skills.includes("Lock Picking")>> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Lock Picking skill: +10%</p> <<else>> <p style="color: #666; margin: 3px 0; font-size: 13px;">✗ Lock Picking skill: +10%</p> <</if>> <<if $skills.includes("Stealth")>> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Stealth skill: +10%</p> <<else>> <p style="color: #666; margin: 3px 0; font-size: 13px;">✗ Stealth skill: +10%</p> <</if>> <<if $physicalTraits.includes("Sly") || $mentalTraits.includes("Sly")>> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Sly trait: +5%</p> <<else>> <p style="color: #666; margin: 3px 0; font-size: 13px;">✗ Sly trait: +5%</p> <</if>> <<if $physicalTraits.includes("Quick Reflexes")>> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Quick Reflexes trait: +8%</p> <<else>> <p style="color: #666; margin: 3px 0; font-size: 13px;">✗ Quick Reflexes trait: +8%</p> <</if>> </div> <div style="text-align: center; margin: 15px 0;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3); font-size: 16px;'>🎯 Attempt Scanner Theft</div>">> <<goto "AttemptOfficerScannerTheft">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; text-align: center; margin-bottom: 15px;"> <p style="color: #3498db; margin: 0; font-size: 15px;"> You already have a Trait Scanner. No need to risk stealing another one. </p> </div> <</if>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #95a5a6; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-size: 15px;'>Avoid the Officer</div>">> <<goto "ScoutForTarget">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _scannerChance = setup.attemptScannerTheft()>> <<set _roll = random(1, 100)>> <<set _success = _roll <= _scannerChance>> /* Advance time */ <<run advanceTime(random(5, 15))>> <div style="background: #1a1a1a; min-height: 100vh; padding: 15px;"> <h1 style="color: #e74c3c; text-align: center; margin: 10px 0; font-size: 28px;">🎯 Scanner Theft Attempt</h1> <h2 style="color: #888; text-align: center; margin: 5px 0 15px 0; font-size: 20px;">Stealing from an Officer</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="margin: 5px 0; font-size: 15px;"><b>Success Chance:</b> _scannerChance%</p> <p style="margin: 5px 0; font-size: 15px;"><b>Your Roll:</b> _roll</p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #3498db;"> <p style="color: #ccc; margin: 0; font-size: 15px; font-style: italic;"> You wait for the right moment, then move in swiftly. Your fingers reach for the scanner on the officer's belt... </p> </div> <<if _success>> /* SUCCESS! Got the scanner */ <<set $traitScanner = true>> <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 15)>> <div style="background: #1a4d1a; border: 2px solid #2ecc71; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0; font-size: 18px;">✓ INCREDIBLE SUCCESS!</h3> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"> Against all odds, you managed to snatch the Trait Scanner! The officer doesn't even notice it's missing until you're long gone. </p> <div style="background: rgba(0,0,0,0.3); padding: 12px; border-radius: 5px; margin: 10px 0;"> <p style="color: #2ecc71; margin: 0; font-size: 16px; font-weight: bold;">✓ Acquired: Trait Scanner</p> <p style="color: #3498db; margin: 8px 0 0 0; font-size: 14px;">You can now see mental traits and skills on all targets!</p> </div> <p style="color: #ff6b6b; margin: 10px 0 0 0; font-size: 14px;"><b>Heat Level:</b> +15% (Now: $crimeSystem.heatLevel%)</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>Leave the Area</div>">> <<goto "CrimeHub">> <</link>> </div> <<else>> /* FAILED - Caught! */ <<set $crimeSystem.heatLevel = Math.min(100, $crimeSystem.heatLevel + 35)>> <<set $crimeSystem.activeWarrant = true>> <div style="background: #4d1a1a; border: 2px solid #e74c3c; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0; font-size: 18px;">✗ CAUGHT!</h3> <p style="color: #fff; margin: 0 0 10px 0; font-size: 15px;"> The officer's hand clamps down on your wrist before you can get away! </p> <p style="color: #ff6b6b; margin: 0; font-size: 15px;"> "Trying to steal from a cop? You just made a VERY big mistake!" </p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 15px;"> <p style="color: #ff6b6b; margin: 0 0 10px 0; font-size: 15px;"><b>Heat Level:</b> +35% (Now: $crimeSystem.heatLevel%)</p> <p style="color: #f39c12; margin: 0; font-size: 15px;"><b>Active Warrant Issued!</b></p> </div> <<goto "CaughtByPolice">> <</if>> </div> <</nobr>>
<<nobr>> /* Reset consecutive escapes counter */ <<if !$crimeSystem.consecutiveEscapes>> <<set $crimeSystem.consecutiveEscapes = 0>> <</if>> <<set $crimeSystem.consecutiveEscapes = 0>> <<set _restoredJob = $jailSystem.previousJob || "Unemployed">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #f39c12; text-align: center; margin: 15px 0;">💰 Fine Paid</h1> <div style="background: linear-gradient(135deg, #f39c12 0%, #f1c40f 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #f39c12;"> <h3 style="color: #000; margin: 0 0 15px 0; text-align: center; font-size: 22px;">✅ Criminal Record Cleared</h3> <p style="color: #000; margin: 0; text-align: center; font-size: 16px;"> You've paid your fine and are no longer classified as a Criminal. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #51cf66;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">Resolution Details:</h3> <p style="color: #ccc; margin: 5px 0; font-size: 15px;">✅ Fine Paid: $<<print $jailSystem.fineAmount>></p> <p style="color: #ccc; margin: 5px 0; font-size: 15px;">✅ Crimes Forgiven: <<print $crimeSystem.crimesCommitted>></p> <<if _restoredJob !== "Unemployed">> <p style="color: #51cf66; margin: 5px 0; font-size: 15px;">✅ Job Restored: _restoredJob</p> <<else>> <p style="color: #ccc; margin: 5px 0; font-size: 15px;">✅ Job Status: Unemployed (can get new job)</p> <</if>> <p style="color: #51cf66; margin: 15px 0 5px 0; font-size: 15px; font-weight: bold;">You can now trade for new jobs again!</p> <p style="color: #888; margin: 5px 0; font-size: 14px; font-style: italic;">Escape streak has been reset.</p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #667eea;"> <p style="color: #aaa; margin: 0; font-size: 14px; font-style: italic;"> The authorities process your payment and update your records. You're free to go. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px;'>Continue</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _traitsGained = State.temporary.jailTraitsGained || []>> <<set _traitsLost = State.temporary.jailTraitsLost || []>> <<set _traitsReplaced = State.temporary.jailTraitsReplaced || []>> <<set _restoredJob = $jailSystem.previousJob || "Unemployed">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center; margin: 15px 0;">🚪 Released from Jail</h1> <div style="background: linear-gradient(135deg, #51cf66 0%, #2ecc71 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #51cf66;"> <h3 style="color: #fff; margin: 0 0 15px 0; text-align: center; font-size: 22px;">✅ Sentence Completed</h3> <p style="color: #fff; margin: 0; text-align: center; font-size: 16px;"> You've served your time and are now free to leave. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #667eea;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">Time Served:</h3> <p style="color: #ccc; margin: 5px 0; font-size: 15px;">📅 Days in Jail: <<print State.temporary.daysServedTotal || $jailSystem.daysServed>></p> <<if _restoredJob !== "Unemployed">> <p style="color: #51cf66; margin: 5px 0; font-size: 15px;">✅ Job Restored: _restoredJob</p> <<else>> <p style="color: #ccc; margin: 5px 0; font-size: 15px;">✅ Job Status: Unemployed (can get new job)</p> <</if>> <p style="color: #51cf66; margin: 15px 0 5px 0; font-size: 15px; font-weight: bold;">You can now trade for new jobs again!</p> </div> <!-- Trait Changes During Incarceration --> <<if _traitsGained.length > 0 || _traitsLost.length > 0 || _traitsReplaced.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #e74c3c;"> <h3 style="color: #e74c3c; margin: 0 0 15px 0;">🔄 Prison Changed You:</h3> <<if _traitsGained.length > 0>> <div style="background: rgba(81, 207, 102, 0.2); padding: 12px; border-radius: 8px; margin-bottom: 10px; border-left: 3px solid #51cf66;"> <h4 style="color: #51cf66; margin: 0 0 8px 0; font-size: 16px;">Traits Gained:</h4> <<for _trait range _traitsGained>> <p style="color: #ccc; margin: 3px 0; font-size: 14px;">+ _trait</p> <</for>> </div> <</if>> <<if _traitsLost.length > 0>> <div style="background: rgba(255, 107, 107, 0.2); padding: 12px; border-radius: 8px; margin-bottom: 10px; border-left: 3px solid #ff6b6b;"> <h4 style="color: #ff6b6b; margin: 0 0 8px 0; font-size: 16px;">Traits Lost:</h4> <<for _trait range _traitsLost>> <p style="color: #ccc; margin: 3px 0; font-size: 14px;">- _trait</p> <</for>> </div> <</if>> <<if _traitsReplaced.length > 0>> <div style="background: rgba(243, 156, 18, 0.2); padding: 12px; border-radius: 8px; border-left: 3px solid #f39c12;"> <h4 style="color: #f39c12; margin: 0 0 8px 0; font-size: 16px;">Traits Replaced:</h4> <<for _replacement range _traitsReplaced>> <p style="color: #ccc; margin: 3px 0; font-size: 14px;">_replacement.old → _replacement.new</p> <</for>> </div> <</if>> </div> <</if>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border-left: 4px solid #888;"> <p style="color: #aaa; margin: 0; font-size: 14px; font-style: italic;"> The harsh reality of incarceration has left its mark. You walk out a different person than when you entered. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px;'>Continue</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* ---------------------------------- */ /* --- BROTHEL CLIENT GENERATION --- */ /* ---------------------------------- */ <<set setup.generateBrothelClients = function() { var v = State.variables; var clients = []; var numClients = 3 + (v.brothelLevel || 1); var maleNames = ["Marcus", "David", "James", "Ryan", "Alex", "Victor", "Dominic", "Xavier", "Gabriel", "Adrian", "Richard", "Michael", "Steven", "Robert", "Jonathan", "Daniel", "Timothy", "Nathan", "Benjamin", "Samuel", "William", "Christopher", "Nicholas", "Matthew", "Andrew", "Derek", "Kyle", "Brandon", "Trevor", "Damien", "Frank", "George", "Henry", "Charles", "Edward", "Tyler", "Justin", "Jason", "Kevin", "Brian", "Alexander", "Maximilian", "Sebastian", "Frederick", "Augustus", "Ethan", "Lucas", "Oliver", "Liam", "Noah", "Jackson", "Aiden", "Carter", "Mason", "Logan", "Caleb", "Dylan"]; var femaleNames = ["Sarah", "Emma", "Lisa", "Jennifer", "Michelle", "Dominique", "Veronica", "Scarlett", "Natasha", "Isabella", "Victoria", "Catherine", "Amanda", "Diane", "Rebecca", "Lily", "Grace", "Hannah", "Sophia", "Emily", "Rose", "Jasmine", "Elizabeth", "Charlotte", "Olivia", "Raven", "Jade", "Amber", "Crystal", "Trinity", "Margaret", "Patricia", "Barbara", "Dorothy", "Helen", "Ashley", "Brittany", "Jessica", "Stephanie", "Nicole", "Anastasia", "Valentina", "Gabriella", "Seraphina", "Cassandra", "Ava", "Mia", "Abigail", "Madison", "Chloe", "Ella", "Aria", "Zoey", "Luna"]; var hairColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]; var hairLengths = ["short", "long"]; var positiveVoices = ["Smooth Voice", "Warm Tone", "Gentle Voice", "Silky Voice", "Charismatic Voice", "Charming Tone", "Melodic Voice", "Soothing Tone"]; var neutralVoices = ["Deep Voice", "Soft-Spoken", "Calm Voice", "Steady Voice"]; var negativeVoices = ["Raspy Voice", "Sharp Voice", "Monotone", "Nasally Tone"]; var positiveTraits = ["Confident", "Charming", "Friendly", "Funny", "Kind", "Polite", "Warm", "Outgoing", "Energetic", "Flirty", "Seductive", "Alluring"]; var dominantTraits = ["Dominant", "Aggressive", "Arrogant", "Bitchy", "Confident", "Assertive"]; var submissiveTraits = ["Submissive", "Shy", "Nervous", "Passive", "Awkward"]; var neutralTraits = ["Quiet", "Introverted", "Serious", "Reserved", "Calm", "Analytical"]; var negativeTraits = ["Rude", "Cold", "Impatient", "Demanding", "Selfish", "Moody"]; var stereotypes = ["Jock", "Nerd", "Geek", "Prep", "Goth", "Diva"]; var maxDifficulty = "medium"; if (v.brothelLevel >= 5) { maxDifficulty = "very hard"; } else if (v.brothelLevel >= 3) { maxDifficulty = "hard"; } for (var i = 0; i < numClients; i++) { var gender = random(1, 100) <= 50 ? "male" : "female"; var hasPenis = gender === "male"; var hasVagina = gender === "female"; if (random(1, 100) <= 5) { if (gender === "male") { hasVagina = true; hasPenis = false; } else { hasPenis = true; hasVagina = true; } } var name = gender === "male" ? maleNames[random(0, maleNames.length - 1)] : femaleNames[random(0, femaleNames.length - 1)]; var age = random(21, 55); var hairColor = hairColors[random(0, hairColors.length - 1)]; var hairLength = hairLengths[random(0, hairLengths.length - 1)]; var chestSize = "flat"; if (gender === "female") { var chestSizes = ["small", "medium", "large", "huge"]; chestSize = chestSizes[random(0, chestSizes.length - 1)]; } else if (random(1, 100) <= 10) { chestSize = "small"; } var voiceType = random(1, 100); var voice; if (voiceType <= 50) { voice = positiveVoices[random(0, positiveVoices.length - 1)]; } else if (voiceType <= 80) { voice = neutralVoices[random(0, neutralVoices.length - 1)]; } else { voice = negativeVoices[random(0, negativeVoices.length - 1)]; } var mentalTraits = []; var numTraits = random(1, 3); var personalityType = random(1, 100); var traitPool = []; if (personalityType <= 20) { traitPool = dominantTraits; } else if (personalityType <= 40) { traitPool = submissiveTraits; } else if (personalityType <= 60) { traitPool = positiveTraits; } else if (personalityType <= 80) { traitPool = neutralTraits; } else { traitPool = negativeTraits; } for (var t = 0; t < numTraits; t++) { var trait = traitPool[random(0, traitPool.length - 1)]; if (mentalTraits.indexOf(trait) === -1) { mentalTraits.push(trait); } } var stereotype = null; if (random(1, 100) <= 20) { stereotype = stereotypes[random(0, stereotypes.length - 1)]; } var preferences = []; var dislikes = []; var requiredPlayerTraits = []; var bonusPlayerTraits = []; var penaltyPlayerTraits = []; var preferredChestSize = null; var preferredGenitals = null; if (mentalTraits.indexOf("Dominant") !== -1 || mentalTraits.indexOf("Aggressive") !== -1 || mentalTraits.indexOf("Arrogant") !== -1) { preferences.push("submission", "rough", "dirtyTalk"); dislikes.push("domination"); requiredPlayerTraits.push("Submissive"); bonusPlayerTraits.push("Shy", "Passive", "Obedient"); penaltyPlayerTraits.push("Dominant", "Arrogant", "Stubborn"); if (mentalTraits.indexOf("Bitchy") !== -1 || mentalTraits.indexOf("Arrogant") !== -1) { bonusPlayerTraits.push("Bitchy"); } } if (mentalTraits.indexOf("Submissive") !== -1 || mentalTraits.indexOf("Shy") !== -1 || mentalTraits.indexOf("Passive") !== -1) { preferences.push("domination", "dirtyTalk"); dislikes.push("submission"); requiredPlayerTraits.push("Dominant"); bonusPlayerTraits.push("Confident", "Aggressive", "Arrogant"); penaltyPlayerTraits.push("Submissive", "Shy", "Passive"); } if (mentalTraits.indexOf("Friendly") !== -1 || mentalTraits.indexOf("Kind") !== -1 || mentalTraits.indexOf("Warm") !== -1) { preferences.push("sensual", "teasing"); dislikes.push("rough"); bonusPlayerTraits.push("Kind", "Friendly", "Warm", "Gentle"); } if (mentalTraits.indexOf("Flirty") !== -1 || mentalTraits.indexOf("Seductive") !== -1) { preferences.push("teasing", "dirtyTalk", "roleplay"); bonusPlayerTraits.push("Flirty", "Seductive", "Alluring"); } if (mentalTraits.indexOf("Energetic") !== -1 || mentalTraits.indexOf("Outgoing") !== -1) { preferences.push("rough", "stamina", "rhythm"); bonusPlayerTraits.push("Energetic", "High Stamina"); } if (mentalTraits.indexOf("Rude") !== -1 || mentalTraits.indexOf("Cold") !== -1 || mentalTraits.indexOf("Impatient") !== -1) { preferences.push("professional", "quick"); dislikes.push("teasing"); bonusPlayerTraits.push("Efficient", "Direct"); penaltyPlayerTraits.push("Talkative", "Slow"); } if (mentalTraits.indexOf("Quiet") !== -1 || mentalTraits.indexOf("Introverted") !== -1) { preferences.push("sensual", "gentle"); dislikes.push("dirtyTalk"); bonusPlayerTraits.push("Quiet", "Gentle", "Patient"); penaltyPlayerTraits.push("Loud", "Talkative"); } if (stereotype === "Jock") { preferences.push("rough", "stamina", "athletic"); bonusPlayerTraits.push("Athletic Build", "Fit", "Energetic"); } else if (stereotype === "Nerd" || stereotype === "Geek") { preferences.push("roleplay"); bonusPlayerTraits.push("Intelligent", "Nerdy", "Geeky"); } else if (stereotype === "Goth") { preferences.push("rough", "fetishPlay", "dark"); bonusPlayerTraits.push("Goth", "Dark", "Mysterious"); } else if (stereotype === "Prep") { preferences.push("sensual", "clean", "fashionable"); bonusPlayerTraits.push("Fashionable", "Attractive", "Preppy"); } else if (stereotype === "Diva") { preferences.push("worship", "submission"); dislikes.push("domination"); bonusPlayerTraits.push("Submissive", "Obedient"); penaltyPlayerTraits.push("Arrogant", "Dominant"); } var chestPref = random(1, 100); if (chestPref <= 25) { preferredChestSize = "small"; } else if (chestPref <= 50) { preferredChestSize = "medium"; } else if (chestPref <= 75) { preferredChestSize = "large"; } else { preferredChestSize = "huge"; } var breastActivityPref = random(1, 100); if (breastActivityPref <= 30) { preferences.push("titPlay", "nipplePlay"); if (random(1, 100) <= 60) { bonusPlayerTraits.push("large_tits", "huge_tits", "giant_tits", "gigantic_tits"); } } if (hasPenis && hasVagina) { preferredGenitals = "futanari"; preferences.push("penisPlay", "vaginal"); } else if (hasPenis) { preferredGenitals = "vagina"; preferences.push("vaginal", "anal", "oralGiving"); var tightnessPref = random(1, 100); if (tightnessPref <= 40) { bonusPlayerTraits.push("tight_vagina"); } else if (tightnessPref <= 70) { bonusPlayerTraits.push("normal_vagina"); } else { bonusPlayerTraits.push("loose_vagina"); } } else if (hasVagina) { preferredGenitals = "penis"; preferences.push("vaginal", "anal", "oralReceiving"); if (random(1, 100) <= 30) { bonusPlayerTraits.push("player_has_penis"); } } var difficulty = "medium"; var basePay = 0; if (mentalTraits.indexOf("Rude") !== -1 || mentalTraits.indexOf("Demanding") !== -1 || mentalTraits.indexOf("Arrogant") !== -1) { difficulty = "hard"; } if (mentalTraits.indexOf("Shy") !== -1 || mentalTraits.indexOf("Nervous") !== -1 || mentalTraits.indexOf("Kind") !== -1) { difficulty = "easy"; } if (stereotype === "Diva") { difficulty = "very hard"; } if (random(1, 100) <= 10 && v.brothelLevel >= 5) { difficulty = "very hard"; mentalTraits.push("Wealthy"); mentalTraits.push("Demanding"); } if (maxDifficulty === "medium" && (difficulty === "hard" || difficulty === "very hard")) { difficulty = "medium"; } else if (maxDifficulty === "hard" && difficulty === "very hard") { difficulty = "hard"; } if (difficulty === "easy") { basePay = random(50, 100); } else if (difficulty === "medium") { basePay = random(100, 200); } else if (difficulty === "hard") { basePay = random(200, 350); } else if (difficulty === "very hard") { basePay = random(350, 700); } var description = setup.buildClientDescription(gender, age, hairColor, hairLength, chestSize, voice, mentalTraits, stereotype, hasPenis, hasVagina); clients.push({ name: name, gender: gender, age: age, hairColor: hairColor, hairLength: hairLength, chestSize: chestSize, voice: voice, mentalTraits: mentalTraits, stereotype: stereotype, hasPenis: hasPenis, hasVagina: hasVagina, description: description, basePay: basePay, preferences: preferences, dislikes: dislikes, difficulty: difficulty, requiredPlayerTraits: requiredPlayerTraits, bonusPlayerTraits: bonusPlayerTraits, penaltyPlayerTraits: penaltyPlayerTraits, preferredChestSize: preferredChestSize, preferredGenitals: preferredGenitals }); } return clients; }; setup.buildClientDescription = function(gender, age, hairColor, hairLength, chestSize, voice, mentalTraits, stereotype, hasPenis, hasVagina) { var desc = ""; var pronoun = gender === "male" ? "he" : "she"; var possessive = gender === "male" ? "his" : "her"; if (age < 25) { desc += "A young " + gender + " "; } else if (age < 35) { desc += "A " + gender + " in " + possessive + " late twenties "; } else if (age < 45) { desc += "A mature " + gender + " "; } else { desc += "An older " + gender + " "; } desc += "with " + hairLength + " " + hairColor.toLowerCase() + " hair. "; if (chestSize !== "flat") { if (gender === "female") { desc += "You notice " + possessive + " " + chestSize + " breasts. "; } else { desc += "Unusually, " + pronoun + " has noticeable chest development. "; } } desc += "Their " + voice.toLowerCase() + " catches your attention. "; if (mentalTraits.length > 0) { var trait = mentalTraits[random(0, mentalTraits.length - 1)]; if (trait === "Dominant" || trait === "Aggressive") { desc += "They carry themselves with dominant energy. "; } else if (trait === "Submissive" || trait === "Shy") { desc += "They seem shy and uncertain. "; } else if (trait === "Friendly" || trait === "Kind") { desc += "They have a warm, friendly demeanor. "; } else if (trait === "Arrogant" || trait === "Bitchy") { desc += "They radiate arrogance. "; } else if (trait === "Flirty" || trait === "Seductive") { desc += "They're already giving you flirtatious looks. "; } } if (hasPenis && hasVagina && gender === "female") { desc += "There's something... unusual about this client."; } else if (hasVagina && gender === "male") { desc += "Something seems different about this client."; } return desc; }; setup.calculateClientSatisfaction = function(client, choices, skills) { var satisfaction = 50; var v = State.variables; var difficulty = client.difficulty; /* Dominatrix override: if player is Dominatrix and performs domination, clients ignore their preferences and always respond positively */ var isDominatrix = v.mentalTraits && v.mentalTraits.includes("Dominatrix"); var performsDomination = choices && choices.indexOf("domination") !== -1; var dominatrixOverride = isDominatrix && performsDomination; /* If Dominatrix override is active, give massive satisfaction boost */ if (dominatrixOverride) { satisfaction = 85; } var bonusMultiplier = 1.0; var penaltyMultiplier = 1.0; if (difficulty === "easy") { bonusMultiplier = 0.8; penaltyMultiplier = 0.6; } else if (difficulty === "medium") { bonusMultiplier = 1.0; penaltyMultiplier = 1.0; } else if (difficulty === "hard") { bonusMultiplier = 1.3; penaltyMultiplier = 1.4; } else if (difficulty === "very hard") { bonusMultiplier = 1.6; penaltyMultiplier = 2.0; } if (client.requiredPlayerTraits && client.requiredPlayerTraits.length > 0) { for (var i = 0; i < client.requiredPlayerTraits.length; i++) { var trait = client.requiredPlayerTraits[i]; if (v.mentalTraits.indexOf(trait) !== -1) { satisfaction += Math.floor(20 * bonusMultiplier); } else { satisfaction -= Math.floor(30 * penaltyMultiplier); } } } if (client.bonusPlayerTraits && client.bonusPlayerTraits.length > 0) { for (var i = 0; i < client.bonusPlayerTraits.length; i++) { var trait = client.bonusPlayerTraits[i]; if (trait === "tight_vagina" && v.vaginaTightness === "tight") { satisfaction += Math.floor(15 * bonusMultiplier); } else if (trait === "normal_vagina" && v.vaginaTightness === "normal") { satisfaction += Math.floor(10 * bonusMultiplier); } else if (trait === "loose_vagina" && v.vaginaTightness === "loose") { satisfaction += Math.floor(15 * bonusMultiplier); } else if (trait === "player_has_penis" && v.bodyParts.genitals && v.bodyParts.genitals.toLowerCase().indexOf("penis") !== -1) { satisfaction += Math.floor(20 * bonusMultiplier); } else if (v.mentalTraits.indexOf(trait) !== -1 || v.physicalTraits.indexOf(trait) !== -1) { satisfaction += Math.floor(8 * bonusMultiplier); } } } if (client.penaltyPlayerTraits && client.penaltyPlayerTraits.length > 0) { for (var i = 0; i < client.penaltyPlayerTraits.length; i++) { var trait = client.penaltyPlayerTraits[i]; if (v.mentalTraits.indexOf(trait) !== -1 || v.physicalTraits.indexOf(trait) !== -1) { satisfaction -= Math.floor(10 * penaltyMultiplier); } } } if (client.preferredChestSize) { var playerChest = v.bodyParts.chest.toLowerCase(); var preferredChest = client.preferredChestSize.toLowerCase(); if (playerChest === preferredChest) { satisfaction += Math.floor(12 * bonusMultiplier); } else if (playerChest.indexOf(preferredChest) !== -1 || preferredChest.indexOf(playerChest) !== -1) { satisfaction += Math.floor(5 * bonusMultiplier); } else { satisfaction -= Math.floor(8 * penaltyMultiplier); } } if (choices.indexOf("titWorship") !== -1 || choices.indexOf("titfuck") !== -1) { var playerChest = v.bodyParts.chest.toLowerCase(); if (client.preferredChestSize) { var preferredChest = client.preferredChestSize.toLowerCase(); if (playerChest === preferredChest) { satisfaction += Math.floor(15 * bonusMultiplier); } else if (playerChest.indexOf(preferredChest) !== -1 || preferredChest.indexOf(playerChest) !== -1) { satisfaction += Math.floor(8 * bonusMultiplier); } } if (choices.indexOf("titfuck") !== -1) { if (playerChest.indexOf("huge") !== -1 || playerChest.indexOf("giant") !== -1 || playerChest.indexOf("gigantic") !== -1) { satisfaction += Math.floor(12 * bonusMultiplier); } else if (playerChest.indexOf("large") !== -1) { satisfaction += Math.floor(8 * bonusMultiplier); } } } for (var i = 0; i < choices.length; i++) { if (client.preferences.indexOf(choices[i]) !== -1) { satisfaction += Math.floor(10 * bonusMultiplier); } if (client.dislikes.indexOf(choices[i]) !== -1 && !dominatrixOverride) { satisfaction -= Math.floor(15 * penaltyMultiplier); } } var preferenceMatches = 0; var preferenceTotal = client.preferences.length; for (var i = 0; i < choices.length; i++) { if (client.preferences.indexOf(choices[i]) !== -1) { preferenceMatches++; } } /* Dominatrix override: skip preference match rate penalty */ if (preferenceTotal > 0 && !dominatrixOverride) { var matchRate = preferenceMatches / preferenceTotal; if (matchRate >= 0.75) { satisfaction += Math.floor(25 * bonusMultiplier); } else if (matchRate >= 0.5) { satisfaction += Math.floor(15 * bonusMultiplier); } else if (matchRate >= 0.25) { satisfaction += Math.floor(5 * bonusMultiplier); } else { satisfaction -= Math.floor(15 * penaltyMultiplier); } } else if (preferenceTotal > 0 && dominatrixOverride) { /* Dominatrix always gets bonus as if matching 75%+ preferences */ satisfaction += Math.floor(25 * bonusMultiplier); } if (v.sexualSkills) { for (var i = 0; i < choices.length; i++) { var skillKey = choices[i]; if (v.sexualSkills[skillKey]) { var level = v.sexualSkills[skillKey].level; var skillBonus = Math.floor(level / 2); satisfaction += Math.floor(skillBonus * bonusMultiplier); } } } var charisma = setup.getTotalStat("charisma"); var charismaBonus = Math.floor(charisma / 10); satisfaction += Math.floor(charismaBonus * bonusMultiplier); /* Cheshire Cat: guaranteed brothel success */ if (v.physicalTraits && v.physicalTraits.includes("Cheshire Cat")) { satisfaction = 100; } if (satisfaction > 100) satisfaction = 100; if (satisfaction < 0) satisfaction = 0; return satisfaction; }; setup.addBrothelLevelExp = function(expAmount) { var v = State.variables; if (!v.brothelLevelExp) v.brothelLevelExp = 0; if (!v.brothelMaxExp) v.brothelMaxExp = 100; if (!v.brothelLevel) v.brothelLevel = 1; if (v.brothelLevel >= 5) { return; } /* Trophy Wife 2x brothel XP bonus */ if (v.physicalTraits && v.physicalTraits.includes("Trophy Wife")) { expAmount = expAmount * 2; } /* Slut 2x brothel XP bonus */ if (v.physicalTraits && v.physicalTraits.includes("Slut")) { expAmount = expAmount * 2; } v.brothelLevelExp += expAmount; while (v.brothelLevelExp >= v.brothelMaxExp && v.brothelLevel < 5) { v.brothelLevelExp -= v.brothelMaxExp; v.brothelLevel++; v.brothelMaxExp = Math.floor(v.brothelMaxExp * 1.5); if (!v.brothelLevelUpMessages) { v.brothelLevelUpMessages = []; } var levelUpMsg = "Brothel Level Up! You are now Level " + v.brothelLevel; v.brothelLevelUpMessages.push(levelUpMsg); if (v.brothelLevel >= 5) { setup.achievements.unlock("brothel_max_level"); } } if (v.brothelLevel >= 5) { v.brothelLevel = 5; v.brothelLevelExp = 0; } }; setup.monitorSexuallySkilled = function() { var v = State.variables; if (v.sexualSkills && (!v.skills || v.skills.indexOf("Sexually Skilled") === -1) && (!v.physicalTraits || (v.physicalTraits.indexOf("Pyrow") === -1 && v.physicalTraits.indexOf("Raiju") === -1 && (v.physicalTraits.indexOf("Succubus") === -1 && v.physicalTraits.indexOf("Voluptuous Succubus") === -1) && v.physicalTraits.indexOf("Slut") === -1))) { setup.resetSexualSkills(); if (v.jobs && v.jobs.indexOf("Brothel Worker") !== -1) { v.jobs.splice(v.jobs.indexOf("Brothel Worker"), 1); } } } >> <</nobr>>
<<nobr>> <<set $lastLocation = "Brothel">> <!-- Generate available clients --> <<set _availableClients = setup.generateBrothelClients()>> <!-- Oni: drop clients that require a Submissive player. Retry up to 5 times. --> <<if setup.oniBuffs && setup.oniBuffs.isOni()>> <<set _oniFiltered = setup.oniBuffs.filterBrothelClients(_availableClients)>> <<for _oniRetries = 0; _oniRetries < 5 && (!_oniFiltered || _oniFiltered.length === 0); _oniRetries++>> <<set _availableClients = setup.generateBrothelClients()>> <<set _oniFiltered = setup.oniBuffs.filterBrothelClients(_availableClients)>> <</for>> <<set _availableClients = _oniFiltered || []>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💼 Available Clients</h1> <<if setup.oniBuffs && setup.oniBuffs.isOni() && (!_availableClients || _availableClients.length === 0)>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 16px; margin: 0; text-align: center;">One look at you and tonight's clients pale. They came hoping for someone they could push around, not a horned predator with eyes that promise to break them. The booker apologises and tells you to come back tomorrow.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Brothel</div>">><<goto "Brothel">><</link>> </div> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 16px; margin: 0; text-align: center;"> Choose a client carefully. Their preferences and your skills will determine your success. </p> </div> <!-- Client Cards --> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<for _client range _availableClients>> <<capture _client>> <div style="background: #2a2a2a; border: 3px solid #e91e63; border-radius: 12px; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <!-- Client Header --> <div style="border-bottom: 2px solid #e91e63; padding-bottom: 10px; margin-bottom: 15px;"> <h3 style="color: #e91e63; margin: 0 0 5px 0;"> <<print _client.name>> <<if _client.type === "mystery">><span style="color: #ffc107;">⚠️</span><</if>> <<if _client.type === "vip">><span style="color: #FFD700;">👑</span><</if>> </h3> <div style="color: #aaa; font-size: 14px;"> <<print _client.gender.toUpperFirst()>>, <<print _client.age>> years old </div> </div> <!-- Description --> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; margin-bottom: 15px; border-left: 3px solid #e91e63;"> <p style="color: #ccc; margin: 0; font-size: 14px; font-style: italic;"> "<<print _client.description>>" </p> </div> <!-- Payment --> <div style="margin-bottom: 15px;"> <strong style="color: #51cf66;">Base Payment:</strong> <span style="color: #51cf66; font-size: 18px; font-weight: bold;">$<<print _client.basePay>></span> </div> <!-- Difficulty --> <div style="margin-bottom: 15px;"> <strong style="color: #aaa;">Difficulty:</strong> <<if _client.difficulty === "easy">> <span style="color: #51cf66;">Easy ⭐</span> <<elseif _client.difficulty === "medium">> <span style="color: #ffc107;">Medium ⭐⭐</span> <<elseif _client.difficulty === "hard">> <span style="color: #ff9800;">Hard ⭐⭐⭐</span> <<elseif _client.difficulty === "very hard">> <span style="color: #ff6b6b;">Very Hard ⭐⭐⭐⭐</span> <<else>> <span style="color: #9b59b6;">??? ⚠️</span> <</if>> </div> <!-- Hints about preferences (vague) --> <<if _client.type !== "mystery">> <div style="background: #1a1a1a; padding: 10px; border-radius: 8px; margin-bottom: 15px;"> <div style="color: #667eea; font-size: 13px; font-weight: bold; margin-bottom: 5px;">Vibes:</div> <<if _client.preferences.includes("sensual")>> <span style="color: #ccc; font-size: 12px;">• Seeks intimacy and connection</span><br> <</if>> <<if _client.preferences.includes("rough") || _client.preferences.includes("domination")>> <span style="color: #ccc; font-size: 12px;">• Wants intensity</span><br> <</if>> <<if _client.preferences.includes("submission")>> <span style="color: #ccc; font-size: 12px;">• Needs to be controlled</span><br> <</if>> <<if _client.preferences.includes("roleplay") || _client.preferences.includes("fetishPlay")>> <span style="color: #ccc; font-size: 12px;">• Has specific fantasies</span><br> <</if>> <<if _client.preferences.includes("oralGiving") || _client.preferences.includes("oralReceiving")>> <span style="color: #ccc; font-size: 12px;">• Appreciates oral attention</span><br> <</if>> </div> <</if>> <!-- Required/Penalty Traits Warning --> <<if _client.requiredTraits && _client.requiredTraits.length > 0>> <<set _hasRequired = false>> <<for _trait range _client.requiredTraits>> <<if $mentalTraits.includes(_trait)>> <<set _hasRequired = true>> <</if>> <</for>> <<if !_hasRequired>> <div style="background: #ff6b6b; padding: 8px; border-radius: 6px; margin-bottom: 10px;"> <span style="color: white; font-size: 12px; font-weight: bold;">⚠️ May be difficult without certain traits</span> </div> <</if>> <</if>> <!-- Select Button --> <<link "<div style='background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Select This Client</div>">> <<set $currentBrothelClient = _client>> <<goto "BrothelSession">> <</link>> </div> <</capture>> <</for>> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #007FFF; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Lounge</div>">> <<goto "Brothel">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "Brothel">> <!-- Initialize session variables --> <<if !$brothelSessionStage>> <<set $brothelSessionStage = 1>> <<set $brothelSessionChoices = []>> <<set $brothelSessionSkillsUsed = []>> <</if>> <<set _client = $currentBrothelClient>> <!-- Check player personality traits --> <<set _isDominant = $mentalTraits.includes("Dominant") || $mentalTraits.includes("Aggressive") || $mentalTraits.includes("Arrogant") || $physicalTraits.includes("Dominatrix")>> <<set _isSubmissive = $mentalTraits.includes("Submissive") || $mentalTraits.includes("Shy") || $mentalTraits.includes("Passive")>> <<set _isConfident = $mentalTraits.includes("Confident") || $mentalTraits.includes("Charming")>> <<set _isBitchy = $mentalTraits.includes("Bitchy") || $mentalTraits.includes("Arrogant") || $mentalTraits.includes("Rude") || $physicalTraits.includes("Gyaru")>> <<set _isKind = $mentalTraits.includes("Kind") || $mentalTraits.includes("Friendly") || $mentalTraits.includes("Warm")>> <<set _isFlirty = $mentalTraits.includes("Flirty") || $mentalTraits.includes("Seductive") || $mentalTraits.includes("Alluring") || $physicalTraits.includes("Dominatrix")>> <<set _isAwkward = $mentalTraits.includes("Awkward") || $mentalTraits.includes("Shy")>> <<set _isProfessional = $mentalTraits.includes("Efficient") || $mentalTraits.includes("Direct") || $mentalTraits.includes("Hardworking")>> <<set _isEnergetic = $mentalTraits.includes("Energetic") || $mentalTraits.includes("Outgoing")>> <<set _isCerberus = $activeTransformation === "Cerberus">> <<if _isCerberus>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Session with <<print _client.name>></h1> <!-- Client Details Display --> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #667eea;"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; font-size: 13px; color: #ccc;"> <div><strong style="color: #667eea;">Age:</strong> <<print _client.age>></div> <div><strong style="color: #667eea;">Hair:</strong> <<print _client.hairLength.toUpperFirst()>> <<print _client.hairColor>></div> <<if _client.chestSize !== "flat">> <div><strong style="color: #667eea;">Chest:</strong> <<print _client.chestSize.toUpperFirst()>></div> <</if>> <div><strong style="color: #667eea;">Voice:</strong> <<print _client.voice>></div> <<if _client.mentalTraits.length > 0>> <div><strong style="color: #667eea;">Traits:</strong> <<print _client.mentalTraits.join(", ")>></div> <</if>> <<if _client.stereotype>> <div><strong style="color: #667eea;">Type:</strong> <<print _client.stereotype>></div> <</if>> </div> </div> <!-- Stage 1: First Impression --> <<if $brothelSessionStage === 1>> <<if _isCerberus>> /* Cerberus three-head Stage 1: all three heads share one body and arrive together. */ <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> <<print _client.description>> </p> </div> <div style="padding: 15px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2a 100%); border-radius: 12px; margin-bottom: 20px; border: 2px solid #e040fb;"> <p style="color: #f3e5f5; font-size: 16px; line-height: 1.8; margin: 0; font-style: italic;"> <<if _client.gender === "male">> As you step into the light, <<print _client.name>>'s breath catches in his throat. Three heads rise from your shoulders on three sinuous necks, each one watching him with its own pair of eyes. "What the..." He grips the edge of the bed, gaze darting between the three faces. "You're... there's three of you?" His pulse hammers visibly at his throat, equal parts alarm and arousal as <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>></span>, <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>></span>, and <span @style="'color: ' + _cRight + ';'"><<print _nRight>></span> all fix him with hungry attention. "Okay," he breathes, cock already stirring. "This is the wildest thing that has ever happened to me." <<else>> As you step into the light, <<print _client.name>> freezes. Three heads rise from your shoulders on three graceful necks, each one studying her with its own pair of eyes. "Oh my..." Her hand flies to her mouth, eyes flicking between the three faces. "There are three of you. On one body." Her cheeks flush hot as <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>></span>, <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>></span>, and <span @style="'color: ' + _cRight + ';'"><<print _nRight>></span> all turn toward her at once. "I... I had no idea I wanted this until right now," she admits, pressing her thighs together. <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">Choose Your Approach</h2> <p style="color: #ccc; margin: 0 0 20px 0;">Three heads, three instincts. How do you all greet <<print _client.name>>?</p> <div style="display: grid; gap: 15px;"> /* Sensual approach (three heads) */ <<set _optSensual = '<div style="background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #e91e63;">Sensual & Welcoming</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + (_pCenter.flirty ? '"Come here, gorgeous," ' + _nCenter + ' purrs, drawing them in with a sultry smile.' : _pCenter.kind ? _nCenter + ' smiles warmly. "Relax. You're in good hands."' : _pCenter.dominant ? _nCenter + ' meets their eyes, voice low and sure. "Closer."' : _nCenter + ' offers a soft, inviting look.') + '</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + (_pLeft.flirty ? _nLeft + ' leans in and breathes against their neck, "Mmm, you smell delicious."' : _pLeft.dominant ? _nLeft + ' tilts their chin up with a single finger. "Eyes on me."' : _pLeft.awkward ? _nLeft + ' ducks shyly, managing only a soft, "H-hi..."' : _pLeft.kind ? _nLeft + ' nuzzles in gently. "Let us take care of you."' : _nLeft + ' trails a slow, warm touch down their arm.') + '</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + (_pRight.flirty ? _nRight + ' smirks and traces their lip. "We'll make this unforgettable."' : _pRight.submissive ? _nRight + ' hangs back, cheeks pink, watching eagerly from behind.' : _pRight.energetic ? _nRight + ' beams. "Ooh, this is going to be so good!"' : _pRight.kind ? _nRight + ' offers a tender, reassuring smile.' : _nRight + ' presses close, sharing in the welcome.') + '</span></div>'>> <<link _optSensual>> <<set $brothelSessionChoices.push("sensual")>> <<set $brothelSessionSkillsUsed.push("sensual")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> /* Teasing approach (three heads) */ <<set _optTeasing = '<div style="background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #9b59b6;">Playful & Teasing</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + (_pCenter.flirty ? _nCenter + ' winks. "Think you can keep up with all three of us?"' : _pCenter.bitchy ? _nCenter + ' smirks coolly. "Beg a little first."' : _pCenter.confident ? _nCenter + ' grins, utterly in command of the game.' : _nCenter + ' flashes a coy, playful smile.') + '</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + (_pLeft.bitchy ? _nLeft + ' clicks their tongue. "Patience. You'll get what you earn."' : _pLeft.flirty ? _nLeft + ' nips playfully at their earlobe and pulls back, laughing.' : _pLeft.energetic ? _nLeft + ' bounces with delight. "Catch us if you can!"' : _pLeft.awkward ? _nLeft + ' tries a tease, fumbles it, and giggles nervously.' : _nLeft + ' darts in and away, teasing with light touches.') + '</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + (_pRight.energetic ? _nRight + ' circles them giddily. "Your turn, your turn!"' : _pRight.flirty ? _nRight + ' drags a fingertip just shy of where they want it.' : _pRight.submissive ? _nRight + ' peeks out shyly, too flustered to tease but loving every second.' : _nRight + ' joins the game with a knowing grin.') + '</span></div>'>> <<link _optTeasing>> <<set $brothelSessionChoices.push("teasing")>> <<set $brothelSessionSkillsUsed.push("teasing")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> /* Dominant approach (three heads) */ <<set _optDom = '<div style="background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ff6b6b;">Dominant & Commanding</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + (_pCenter.dominant ? _nCenter + ''s voice drops to iron. "You'll do exactly as we say."' : _pCenter.bitchy ? _nCenter + ' looks down at them. "Try to keep up."' : _pCenter.submissive ? _nCenter + ' tries to sound stern and only half manages it.' : _nCenter + ' squares up, taking charge.') + '</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + (_pLeft.dominant ? _nLeft + ' bares her teeth in a grin and shoves them back onto the bed. "On your back."' : _pLeft.bitchy ? _nLeft + ' snaps, "Quiet. We give the orders here."' : _pLeft.submissive ? _nLeft + ' hesitates, clearly happier following than leading.' : _pLeft.awkward ? _nLeft + ' tries a command and it comes out as more of a squeak.' : _nLeft + ' pins them with a hard, dominant stare.') + '</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + (_pRight.dominant ? _nRight + ' growls low. "Don't move until we tell you to."' : _pRight.submissive ? _nRight + ' shrinks back, content to let the others dominate.' : _pRight.confident ? _nRight + ' smiles with cool authority, fully in control.' : _nRight + ' adds her weight to the show of dominance.') + '</span></div>'>> <<link _optDom>> <<set $brothelSessionChoices.push("domination")>> <<set $brothelSessionSkillsUsed.push("domination")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> /* Submissive approach (three heads) */ <<set _optSub = '<div style="background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #51cf66;">Submissive & Eager</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + (_pCenter.submissive ? _nCenter + ' lowers her eyes. "However you want us. Please."' : _pCenter.kind ? _nCenter + ' smiles softly. "We just want to make you happy."' : _pCenter.dominant ? _nCenter + ' bites back her pride and tries, awkwardly, to yield.' : _nCenter + ' bows her head, eager to please.') + '</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + (_pLeft.submissive ? _nLeft + ' nuzzles into their palm, practically melting at a touch.' : _pLeft.awkward ? _nLeft + ' whispers, "T-tell us what to do?" and blushes furiously.' : _pLeft.kind ? _nLeft + ' presses close, all gentle devotion.' : _pLeft.dominant ? _nLeft + ' struggles to stay submissive, instinct fighting it.' : _nLeft + ' waits obediently for direction.') + '</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + (_pRight.submissive ? _nRight + ' trembles eagerly. "Yes... anything you want."' : _pRight.energetic ? _nRight + ' wriggles with eager, puppyish enthusiasm.' : _pRight.awkward ? _nRight + ' hides half behind the others, peeking out hopefully.' : _nRight + ' dips low, ready to serve.') + '</span></div>'>> <<link _optSub>> <<set $brothelSessionChoices.push("submission")>> <<set $brothelSessionSkillsUsed.push("submission")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> /* Professional approach (three heads) */ <<set _optPro = '<div style="background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ffc107;">Professional & Direct</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + (_pCenter.professional ? _nCenter + ' gets straight to it. "Let's discuss what you came for."' : _pCenter.bitchy ? _nCenter + ' checks the time. "We don't have all night."' : _pCenter.confident ? _nCenter + ' takes smooth, businesslike charge.' : _nCenter + ' keeps things efficient and clear.') + '</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + (_pLeft.professional ? _nLeft + ' nods crisply. "Tell us your preferences and we'll deliver."' : _pLeft.bitchy ? _nLeft + ' folds in coolly, all business.' : _pLeft.awkward ? _nLeft + ' fumbles through the formalities but tries to stay on task.' : _nLeft + ' focuses, ready to work.') + '</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + (_pRight.professional ? _nRight + ' adds, "We aim to make every minute count."' : _pRight.energetic ? _nRight + ', eager, has to be reined in to keep things professional.' : _pRight.submissive ? _nRight + ' defers quietly, following the others' lead.' : _nRight + ' keeps a composed, professional air.') + '</span></div>'>> <<link _optPro>> <<set $brothelSessionChoices.push("professional")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> </div> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> <<print _client.description>> </p> </div> <<if setup.getFutaVariant()>> <div style="padding: 15px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2a 100%); border-radius: 12px; margin-bottom: 20px; border: 2px solid #e040fb;"> <p style="color: #f3e5f5; font-size: 16px; line-height: 1.8; margin: 0; font-style: italic;"> <<if _client.gender === "male">> As you position yourself, <<print _client.name>>'s eyes travel down your body and widen with surprise. His gaze locks onto the unmistakable outline of your dual anatomy beneath your clothes—the swell of your hips and the telltale bulge that most women lack. "Wait... you're..." He swallows hard, pupils dilating with fascination. "Holy shit. I've never been with someone like you before." His breathing quickens, cock visibly stiffening as the realization hits him. "That's... incredibly hot." <<else>> <<print _client.name>>'s fingers brush against your body, then pause. Her eyes widen as she traces the shape of your dual anatomy through the fabric—the wet heat between your thighs and the hardening length pressing against your clothes. "Oh my god," she breathes, cheeks flushing. "You have both? That's..." She bites her lip, squeezing her thighs together. "I've always fantasized about someone like you. This is going to be amazing." <</if>> </p> </div> <</if>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">Choose Your Approach</h2> <p style="color: #ccc; margin: 0 0 20px 0;">How do you greet <<print _client.name>>?</p> <div style="display: grid; gap: 15px;"> <!-- Sensual approach --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>Sensual & Welcoming</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isFlirty>>Seductive touches, sultry smile<<elseif _isKind>>Gentle touches, warm embrace<<elseif _isConfident>>Confident allure, magnetic presence<<elseif _isAwkward>>Tentative but sweet approach<<else>>Soft touches, intimate eye contact<</if>></span></div>">> <<set $brothelSessionChoices.push("sensual")>> <<set $brothelSessionSkillsUsed.push("sensual")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> <!-- Teasing approach --> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>Playful & Teasing</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isFlirty>>Expert seduction, knowing exactly what you're doing<<elseif _isBitchy>>Bratty teasing, making them work for it<<elseif _isEnergetic>>Bubbly playfulness, infectious energy<<elseif _isAwkward>>Clumsy but endearing flirtation<<else>>Flirty banter, coy smiles<</if>></span></div>">> <<set $brothelSessionChoices.push("teasing")>> <<set $brothelSessionSkillsUsed.push("teasing")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> <!-- Dominant approach --> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>Dominant & Commanding</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isDominant>>Natural authority, commanding presence<<elseif _isBitchy>>Demanding control, expect obedience<<elseif _isConfident>>Confident dominance, in charge<<elseif _isSubmissive>>Trying to be dominant (awkward)<<else>>Take control, establish authority<</if>></span></div>">> <<set $brothelSessionChoices.push("domination")>> <<set $brothelSessionSkillsUsed.push("domination")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> <!-- Submissive approach --> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>Submissive & Eager</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isSubmissive>>Natural submission, eager to please<<elseif _isAwkward>>Nervous but willing<<elseif _isKind>>Gentle submission, wanting to serve<<elseif _isDominant>>Reluctant submission (unnatural for you)<<else>>Show willingness to please<</if>></span></div>">> <<set $brothelSessionChoices.push("submission")>> <<set $brothelSessionSkillsUsed.push("submission")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> <!-- Professional approach --> <<link "<div style='background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ffc107;'>Professional & Direct</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isProfessional>>Efficient, no-nonsense approach<<elseif _isBitchy>>Cold professionalism, no time to waste<<elseif _isConfident>>Smooth professional, in control<<else>>Businesslike, get to the point<</if>></span></div>">> <<set $brothelSessionChoices.push("professional")>> <<set $brothelSessionStage = 2>> <<goto "BrothelSession">> <</link>> </div> </div> <</if>> <!-- Stage 2: Service Selection --> <<elseif $brothelSessionStage === 2>> <<if _isCerberus>> /* Cerberus three-head Stage 2: all three heads react to the chosen approach, then offer the same services. */ <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: #f3e5f5; font-size: 16px; line-height: 1.8; margin: 0; font-style: italic;"> <<if $brothelSessionChoices.includes("sensual")>> Three pairs of lips, three sets of warm breath, all of it turned on <<print _client.name>> at once.<br> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.flirty>>"There you go," <<print _nCenter>> purrs, sliding warm against <<print _client.name>>. "Let us spoil you."<<elseif _pCenter.kind>><<print _nCenter>> presses a soft kiss to <<print _client.name>>'s jaw. "Just relax for us."<<else>><<print _nCenter>> trails her lips along warm skin, drawing <<print _client.name>> in.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.flirty>><<print _nLeft>> nuzzles in close. "Mmm, you taste as good as you look."<<elseif _pLeft.awkward>><<print _nLeft>> fumbles a tender touch, blushing. "Is, is this okay?"<<elseif _pLeft.dominant>><<print _nLeft>> tilts <<print _client.name>>'s chin up. "Eyes on us."<<else>><<print _nLeft>> strokes down <<print _client.name>>'s side, slow and warm.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> presses shyly to the other side, breath quickening.<<elseif _pRight.energetic>><<print _nRight>> practically vibrates. "This is going to be amazing!"<<elseif _pRight.kind>><<print _nRight>> murmurs reassurance against <<print _client.name>>'s shoulder.<<else>><<print _nRight>> joins the others, sharing in the slow attention.<</if>></span> <<elseif $brothelSessionChoices.includes("teasing")>> Three heads turned the teasing into a game with no escape.<br> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.flirty>><<print _nCenter>> pulls back just out of reach. "Patience, gorgeous."<<elseif _pCenter.bitchy>><<print _nCenter>> smirks. "Beg a little and maybe we'll stop teasing."<<else>><<print _nCenter>> flashes a coy grin, drawing it out.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.flirty>><<print _nLeft>> nips at <<print _client.name>>'s ear and pulls away laughing.<<elseif _pLeft.energetic>><<print _nLeft>> darts in and back. "Catch us if you can!"<<else>><<print _nLeft>> ghosts a touch just shy of where <<print _client.name>> wants it.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> peeks out, too flustered to tease but loving it.<<elseif _pRight.energetic>><<print _nRight>> circles giddily. "Your turn, your turn!"<<else>><<print _nRight>> adds a knowing grin to the game.<</if>></span> <<elseif $brothelSessionChoices.includes("domination")>> <<if _client.mentalTraits.includes("Submissive") || _client.mentalTraits.includes("Shy")>> <<print _client.name>> melts under the weight of three commanding heads.<br> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>>'s voice drops to iron. "You'll do exactly as we say."<<else>><<print _nCenter>> takes firm charge, holding <<print _client.name>> still.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> bares her teeth in a grin. "On your back."<<elseif _pLeft.submissive>><<print _nLeft>> hangs back, happier to follow the others' lead.<<else>><<print _nLeft>> pins <<print _client.name>> with a hard stare.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.dominant>><<print _nRight>> growls low. "Don't move until we tell you to."<<else>><<print _nRight>> adds her weight to the show of control.<</if>></span> <<else>> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> reads <<print _client.name>>'s hesitation and eases off.</span> <<print _client.name>> seems uncertain about the dominant approach. This might not be what they're looking for. <</if>> <<elseif $brothelSessionChoices.includes("submission")>> <<if _client.mentalTraits.includes("Dominant") || _client.mentalTraits.includes("Aggressive")>> All three heads bow low before <<print _client.name>>, eyes lifted in offering.<br> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.submissive>><<print _nCenter>> lowers her eyes. "However you want us. Please."<<else>><<print _nCenter>> dips her head, eager to please.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.submissive>><<print _nLeft>> nuzzles into <<print _client.name>>'s palm, melting at a touch.<<elseif _pLeft.awkward>><<print _nLeft>> whispers, "T-tell us what to do?" and blushes.<<else>><<print _nLeft>> waits obediently for direction.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> trembles eagerly. "Yes... anything you want."<<elseif _pRight.energetic>><<print _nRight>> wriggles with eager, puppyish devotion.<<else>><<print _nRight>> dips low, ready to serve.<</if>></span> <<else>> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> offers herself, but <<print _client.name>> falters.</span> <<print _client.name>> seems uncertain how to respond to your submissiveness. This might not be what they're looking for. <</if>> <<else>> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.professional>><<print _nCenter>> gets straight to it. "Let's discuss what you came for."<<else>><<print _nCenter>> keeps things efficient and clear.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> nods crisply, all business.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> adds, "We aim to make every minute count."</span><br> <<if _client.gender === "male">><<print _client.name>> nods, appreciating the efficiency.<<else>>"Good," <<print _client.name>> says. "No games. I like that."<</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">What Services Do You Offer?</h2> <p style="color: #ccc; margin: 0 0 20px 0;">Three heads, one body. Whatever you choose, all three will share in it.</p> <div style="display: grid; gap: 15px;"> <<if $bodyParts.genitals && ($bodyParts.genitals.toLowerCase().includes("penis") || $bodyParts.genitals === "both")>> <<set _optCock = '<div style="background: #1a1a1a; border: 2px solid #ff9800; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ff9800;">Use Your Cock</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' guides them into position.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' purrs encouragement.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' watches hungrily.</span></div>'>> <<link _optCock>> <<set $brothelSessionChoices.push("penisPlay")>> <<set $brothelSessionSkillsUsed.push("vaginal")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<set _optOral = '<div style="background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #e91e63;">Focus on Oral</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' takes the first taste.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' waits her turn, lips parted.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' licks her lips eagerly.</span></div>'>> <<link _optOral>> <<set $brothelSessionChoices.push("oralGiving")>> <<set $brothelSessionSkillsUsed.push("oralGiving")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <<if $bodyParts.genitals && ($bodyParts.genitals.toLowerCase().includes("vagina") || $bodyParts.genitals === "both")>> <<set _optVag = '<div style="background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #9b59b6;">Full Vaginal Service</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' moans softly in anticipation.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' urges them on.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' trembles with want.</span></div>'>> <<link _optVag>> <<set $brothelSessionChoices.push("vaginal")>> <<set $brothelSessionSkillsUsed.push("vaginal")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<set _optAnal = '<div style="background: #1a1a1a; border: 2px solid #ff9800; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ff9800;">Anal Play</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' grins. "Feeling adventurous?"</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' licks her lips.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' breathes "Advanced..." with relish.</span></div>'>> <<link _optAnal>> <<set $brothelSessionChoices.push("anal")>> <<set $brothelSessionSkillsUsed.push("anal")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <<set _optHands = '<div style="background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #51cf66;">Hands Only</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' directs every stroke.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' watches your fingers work.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' hums approval.</span></div>'>> <<link _optHands>> <<set $brothelSessionChoices.push("handjobs")>> <<set $brothelSessionSkillsUsed.push("handjobs")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <<if _client.preferences.includes("roleplay")>> <<set _optRP = '<div style="background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ffc107;">Roleplay Scenario</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' slips into character.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' plays along with a grin.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' improvises gleefully.</span></div>'>> <<link _optRP>> <<set $brothelSessionChoices.push("roleplay")>> <<set $brothelSessionSkillsUsed.push("roleplay")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<set _playerChestSize = $bodyParts.chest.toLowerCase()>> <<if _playerChestSize !== "flat" && _playerChestSize !== "flat masculine">> <<set _optTit = '<div style="background: #1a1a1a; border: 2px solid #ff69b4; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ff69b4;">Tit Worship & Nipple Play</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' arches your shared chest forward.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' sighs at the attention.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' shivers with every touch.</span></div>'>> <<link _optTit>> <<set $brothelSessionChoices.push("titWorship")>> <<set $brothelSessionSkillsUsed.push("titWorship")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<if _playerChestSize.includes("medium") || _playerChestSize.includes("large") || _playerChestSize.includes("huge") || _playerChestSize.includes("giant") || _playerChestSize.includes("gigantic")>> <<set _optTF = '<div style="background: #1a1a1a; border: 2px solid #ff1493; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ff1493;">Titfuck Service</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' presses your tits together for them.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' watches them slide between.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' grins. "Requires Medium+, and you've got it."</span></div>'>> <<link _optTF>> <<set $brothelSessionChoices.push("titfuck")>> <<set $brothelSessionSkillsUsed.push("titfuck")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> </div> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> <<if $brothelSessionChoices.includes("sensual")>> <<if _client.gender === "male">> <<if _isFlirty>> You press your body against <<print _client.name>>, your breasts pushing into his chest. "Mmm... hello handsome," you purr, running your fingers down his arm. He shivers under your expert touch. <<elseif _isKind>> You take <<print _client.name>>'s hand gently, giving him a warm smile. "Welcome," you say softly, leading him to the bed. Your touch is tender as you caress his arm. <<else>> <<print _client.name>>'s body relaxes under your gentle touch. You trail your fingers along his arm, feeling him shiver. "Mmm... that feels nice," she murmurs. <</if>> <<else>> <<if _isFlirty>> You pull <<print _client.name>> close, your hands exploring her curves boldly. "Mmm, you're gorgeous," you purr directly into her ear. She gasps as your fingers trace her waist. <<elseif _isKind>> You embrace <<print _client.name>> warmly, holding her with genuine care. "You're safe with me," you whisper softly. She relaxes into your arms. <<else>> <<print _client.name>> melts into your embrace as you pull her close. Your hand slides down her side, feeling her curves. "Oh... yes," she breathes. <</if>> <</if>> <<elseif $brothelSessionChoices.includes("teasing")>> <<if _client.gender === "male">> You flash <<print _client.name>> a playful smile, trailing your hand across his chest before pulling away. "You're quite the tease," he says with a nervous laugh. <<else>> <<print _client.name>>'s breath catches as you lean in close, only to pull away at the last moment. "You like to play games," she says with a smile. <</if>> <<elseif $brothelSessionChoices.includes("domination")>> <<if _client.mentalTraits.includes("Submissive") || _client.mentalTraits.includes("Shy")>> <<if _client.gender === "male">> You grab <<print _client.name>>'s wrist firmly, pulling him toward the bed. His eyes widen with interest. "Yes... that's exactly what I need," he breathes. <<else>> Your hand wraps around <<print _client.name>>'s throat gently but firmly. She gasps, her pupils dilating. "Yes... fuck, yes," she moans. <</if>> <<else>> <<print _client.name>> seems uncertain about your dominant approach. This might not be what they're looking for. <</if>> <<elseif $brothelSessionChoices.includes("submission")>> <<if _client.mentalTraits.includes("Dominant") || _client.mentalTraits.includes("Aggressive")>> <<if _client.gender === "male">> You kneel before <<print _client.name>>, eyes downcast. "I'm here to serve you," you whisper. A smile crosses his face. "Good girl," he growls. <<else>> You lower yourself before <<print _client.name>>, showing your submission. Her eyes light up with predatory hunger. "Perfect," sshe purrs. <</if>> <<else>> <<print _client.name>> seems uncertain how to respond to your submissiveness. This might not be what they're looking for. <</if>> <<else>> <<if _client.gender === "male">> <<print _client.name>> nods appreciatively at your professional approach. "I appreciate the efficiency. Let's not waste time," he says. <<else>> "Good," <<print _client.name>> says with approval. "No games. I like that." <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">What Services Do You Offer?</h2> <div style="display: grid; gap: 15px;"> <<if $bodyParts.genitals && ($bodyParts.genitals.toLowerCase().includes("penis") || $bodyParts.genitals === "both")>> <<link "<div style='background: #1a1a1a; border: 2px solid #ff9800; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff9800;'>Use Your Cock</strong><br><span style='color: #aaa; font-size: 14px;'>Penetrate them with your penis</span></div>">> <<set $brothelSessionChoices.push("penisPlay")>> <<set $brothelSessionSkillsUsed.push("vaginal")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>Focus on Oral</strong><br><span style='color: #aaa; font-size: 14px;'>Skilled mouth work, building pleasure slowly</span></div>">> <<set $brothelSessionChoices.push("oralGiving")>> <<set $brothelSessionSkillsUsed.push("oralGiving")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <<if $bodyParts.genitals && ($bodyParts.genitals.toLowerCase().includes("vagina") || $bodyParts.genitals === "both")>> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>Full Vaginal Service</strong><br><span style='color: #aaa; font-size: 14px;'>Let them fuck your pussy</span></div>">> <<set $brothelSessionChoices.push("vaginal")>> <<set $brothelSessionSkillsUsed.push("vaginal")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<link "<div style='background: #1a1a1a; border: 2px solid #ff9800; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff9800;'>Anal Play</strong><br><span style='color: #aaa; font-size: 14px;'>Offer your ass (Advanced)</span></div>">> <<set $brothelSessionChoices.push("anal")>> <<set $brothelSessionSkillsUsed.push("anal")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>Hands Only</strong><br><span style='color: #aaa; font-size: 14px;'>Sensual manual stimulation</span></div>">> <<set $brothelSessionChoices.push("handjobs")>> <<set $brothelSessionSkillsUsed.push("handjobs")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <<if _client.preferences.includes("roleplay")>> <<link "<div style='background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ffc107;'>Roleplay Scenario</strong><br><span style='color: #aaa; font-size: 14px;'>Act out a fantasy together</span></div>">> <<set $brothelSessionChoices.push("roleplay")>> <<set $brothelSessionSkillsUsed.push("roleplay")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <!-- Tit-Based Services (size dependent) --> <<set _playerChestSize = $bodyParts.chest.toLowerCase()>> <<if _playerChestSize !== "flat" && _playerChestSize !== "flat masculine">> <<link "<div style='background: #1a1a1a; border: 2px solid #ff69b4; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff69b4;'>Tit Worship & Nipple Play</strong><br><span style='color: #aaa; font-size: 14px;'>Let them worship your breasts</span></div>">> <<set $brothelSessionChoices.push("titWorship")>> <<set $brothelSessionSkillsUsed.push("titWorship")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> <<if _playerChestSize.includes("medium") || _playerChestSize.includes("large") || _playerChestSize.includes("huge") || _playerChestSize.includes("giant") || _playerChestSize.includes("gigantic")>> <<link "<div style='background: #1a1a1a; border: 2px solid #ff1493; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff1493;'>Titfuck Service</strong><br><span style='color: #aaa; font-size: 14px;'>Slide their cock between your tits (Requires Medium+)</span></div>">> <<set $brothelSessionChoices.push("titfuck")>> <<set $brothelSessionSkillsUsed.push("titfuck")>> <<set $brothelSessionStage = 3>> <<goto "BrothelSession">> <</link>> <</if>> </div> </div> <</if>> <!-- Stage 3: The Action --> <<elseif $brothelSessionStage === 3>> <<if _isCerberus>> /* Cerberus three-head Stage 3: shared image logic, then all three heads narrate the chosen service in their colors, then the same four enhancement options. */ <!-- Brothel Service Image --> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _playerTraits = { isDominant: _isDominant, isSubmissive: _isSubmissive, isConfident: _isConfident, isBitchy: _isBitchy, isKind: _isKind, isFlirty: _isFlirty, isAwkward: _isAwkward, isProfessional: _isProfessional, isEnergetic: _isEnergetic, chestSize: $bodyParts.chest.toLowerCase(), hasVagina: $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("vagina"), hasPenis: $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("penis"), vaginaTight: (typeof $vaginaTightness !== "undefined" && $vaginaTightness === "tight") }>> <<set _serviceType = "">> <<if $brothelSessionChoices.includes("oralGiving")>><<set _serviceType = "oralGiving">> <<elseif $brothelSessionChoices.includes("vaginal")>><<set _serviceType = "vaginal">> <<elseif $brothelSessionChoices.includes("anal")>><<set _serviceType = "anal">> <<elseif $brothelSessionChoices.includes("handjobs")>><<set _serviceType = "handjobs">> <<elseif $brothelSessionChoices.includes("roleplay")>><<set _serviceType = "roleplay">> <<elseif $brothelSessionChoices.includes("titWorship")>><<set _serviceType = "titWorship">> <<elseif $brothelSessionChoices.includes("titfuck")>><<set _serviceType = "titfuck">> <<elseif $brothelSessionChoices.includes("penisPlay")>><<set _serviceType = "penisPlay">> <</if>> <<set _brothelImagePath = setup.getBrothelImage(_serviceType, _client, _playerTraits, $brothelSessionChoices)>> <<if _brothelImagePath>> <div style="text-align: center; margin: 20px 0;"> <img @src="_brothelImagePath" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Brothel Session" onerror="this.style.display='none';"> </div> <</if>> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 16px; margin: 0; line-height: 1.6;"> <<if $brothelSessionChoices.includes("oralGiving")>> Three mouths take turns on <<print _client.name>>, never once leaving them untended.<br> <<if _client.hasPenis>> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> wraps her lips around the head, swirling her tongue slow and deliberate.</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.energetic>><<print _nLeft>> dives down the shaft greedily. "My turn, my turn!"<<elseif _pLeft.flirty>><<print _nLeft>> laps along the underside. "Mmm, you taste so good."<<else>><<print _nLeft>> mouths along the shaft, sharing the work.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> nuzzles lower, lavishing attention with shy devotion.<<else>><<print _nRight>> tends the base, tongue working in slow circles.<</if>></span><br> "Fuck... don't stop, any of you!" <<print _client.name>> pants, hips jerking. <<else>> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> spreads them open and presses her tongue flat to their clit.</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.energetic>><<print _nLeft>> darts in to taste their wetness eagerly.<<else>><<print _nLeft>> laps lower, drinking them in.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> suckles their clit while the others work below.</span><br> "Oh fuck... oh FUCK!" <<print _client.name>> cries, thighs trembling around three muzzles. <</if>> <<elseif $brothelSessionChoices.includes("vaginal")>> You climb onto the bed, spreading your legs as <<print _client.name>> settles between your thighs. Three heads watch them, breath quickening as one.<br> <<if _client.hasPenis>> Their cock presses to your entrance and pushes inside.<br> <<if $vaginaTightness === "tight">> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> throws back with a gasp. "So... so full..."</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> snarls, "Harder. We can take it."<<else>><<print _nLeft>> pants alongside, sharing every clenching wave.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> whimpers as your shared body grips them tight.</span> <<else>> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> moans as they fill you. "Mmm... yes."</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.energetic>><<print _nLeft>> urges them on. "Faster! Don't hold back!"<<else>><<print _nLeft>> matches their rhythm with low moans.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> trembles, drinking in every thrust.</span> <</if>> <br>Their hips slam against your shared body. "Yes! Fuck yes!" all three heads cry at once. <</if>> <<elseif $brothelSessionChoices.includes("anal")>> You raise your shared body onto hands and knees, ass lifted, three heads turned to watch <<print _client.name>> slick themselves with lube.<br> <<if _client.hasPenis>> They press the head of their cock to your tight hole and ease inside.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> sucks in a sharp breath. "Ahh... slow..."</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> growls, "Deeper. We can take more."<<else>><<print _nLeft>> pants through the stretch, sharing the burn.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> moans, "Oh god... more, I can take more!"</span> <<else>> They work their fingers into your ass, stretching you open.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> pants. "Good... really good."</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> urges another finger. "More."</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> whines softly as they scissor you wider.</span> <</if>> <<elseif $brothelSessionChoices.includes("handjobs")>> You coat your hands with oil, three heads watching them glisten.<br> <<if _client.hasPenis>> Both slick hands wrap around <<print _client.name>>'s cock and begin to stroke.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> directs the rhythm, eyes locked on their face.</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.flirty>><<print _nLeft>> purrs, "Look how close you are already."<<else>><<print _nLeft>> watches your fingers glide and twist.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> hums encouragement as they buck into your grip.</span><br> "Fuck... I'm close already," <<print _client.name>> pants. <<else>> Your oiled fingers find <<print _client.name>>'s clit and circle slowly.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> guides two fingers into their wet heat.</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> coaxes, "That's it, let go for us."</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> watches their hips chase your thumb. "Right there!" they cry.</span> <</if>> <<elseif $brothelSessionChoices.includes("roleplay")>> Three heads slip into character together, each playing a different part of <<print _client.name>>'s fantasy.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> sets the scene, voice dropping into the role.</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.energetic>><<print _nLeft>> throws herself into the part with gleeful improvisation.<<else>><<print _nLeft>> plays along, feeding the fantasy.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> adds a third voice, and the scene turns physical.</span><br> "Yes... that's perfect," <<print _client.name>> breathes, fully immersed. <<elseif $brothelSessionChoices.includes("titWorship")>> <<set _chestSize = $bodyParts.chest.toLowerCase()>> You strip off your top, baring your <<if _chestSize.includes("small")>>small, perky tits, nipples already hard. <<elseif _chestSize.includes("medium")>>medium tits, the perfect handful. <<elseif _chestSize.includes("large")>>large tits that bounce heavily. <<elseif _chestSize.includes("huge") || _chestSize.includes("giant") || _chestSize.includes("gigantic")>>massive tits, the enormous mounds jiggling. <</if>><br> <<print _client.name>>'s hands cup your breasts as three heads arch your shared chest into their grip.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> moans as they suck a nipple hard.</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> gasps when their mouth switches sides.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> shivers as their hands never stop kneading.</span> <<elseif $brothelSessionChoices.includes("titfuck")>> <<set _chestSize = $bodyParts.chest.toLowerCase()>> <<if _client.hasPenis>> <<print _client.name>>'s cock springs free, already rock hard. You push them down and wrap your tits around their shaft, three heads leaning in over their lap.<br> <<if _chestSize.includes("medium")>>Your medium tits slide up and down, pressed tight for pressure. <<elseif _chestSize.includes("large")>>Your large tits envelop their cock completely, soft flesh massaging the whole shaft. <<else>>Your massive tits swallow their cock whole, bouncing vigorously. <</if>><br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> ducks to suck the tip each time it emerges from your cleavage.</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> watches their cock throb between your tits. "Oh fuck," they groan.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> urges you faster, breath hot against their skin.</span> <<else>> <<print _client.name>> has no cock, so you guide their hands to your breasts instead.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> presses your soft flesh into their eager palms.</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> sighs at their kneading grip.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> shivers as they squeeze.</span> <</if>> <<elseif $brothelSessionChoices.includes("penisPlay")>> <<if _client.hasVagina>> You guide <<print _client.name>> onto the bed and spread their legs wide. Your cock throbs as three heads watch you push slowly into their wet heat.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> sets the pace, eyes on their arching back.</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> growls, "Take all of us."<<else>><<print _nLeft>> groans as their walls clench around you.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> pants with every stroke. "Yes... harder!" they cry.</span> <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">How Do You Enhance the Experience?</h2> <p style="color: #ccc; margin: 0 0 20px 0;">Three heads, one body, all chasing the same finish.</p> <div style="display: grid; gap: 15px;"> <<set _optDirty = '<div style="background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #e91e63;">Talk Dirty</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' whispers filth in their ear.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' growls something filthier.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' purrs the worst of all.</span></div>'>> <<link _optDirty>> <<set $brothelSessionChoices.push("dirtyTalk")>> <<set $brothelSessionSkillsUsed.push("dirtyTalk")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> <<set _optSensual = '<div style="background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #9b59b6;">Slow & Sensual</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' slows the pace, savoring every breath.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' murmurs softly, drawing it out.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' breathes warm and unhurried.</span></div>'>> <<link _optSensual>> <<set $brothelSessionChoices.push("sensual")>> <<set $brothelSessionSkillsUsed.push("sensual")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> <<set _optRough = '<div style="background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #ff6b6b;">Rough & Intense</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' snarls and drives the pace harder.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' bares her teeth, hungry for more.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' growls, urging it rougher.</span></div>'>> <<link _optRough>> <<set $brothelSessionChoices.push("rough")>> <<set $brothelSessionSkillsUsed.push("rough")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> <<set _optTease = '<div style="background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #51cf66;">Tease & Deny</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' pulls back, making them beg.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' laughs and denies them release.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' teases just out of reach.</span></div>'>> <<link _optTease>> <<set $brothelSessionChoices.push("teasing")>> <<set $brothelSessionSkillsUsed.push("teasing")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> </div> </div> <<else>> <!-- Brothel Service Image --> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _playerTraits = { isDominant: _isDominant, isSubmissive: _isSubmissive, isConfident: _isConfident, isBitchy: _isBitchy, isKind: _isKind, isFlirty: _isFlirty, isAwkward: _isAwkward, isProfessional: _isProfessional, isEnergetic: _isEnergetic, chestSize: $bodyParts.chest.toLowerCase(), hasVagina: $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("vagina"), hasPenis: $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("penis"), vaginaTight: (typeof $vaginaTightness !== "undefined" && $vaginaTightness === "tight") }>> <<set _serviceType = "">> <<if $brothelSessionChoices.includes("oralGiving")>><<set _serviceType = "oralGiving">> <<elseif $brothelSessionChoices.includes("vaginal")>><<set _serviceType = "vaginal">> <<elseif $brothelSessionChoices.includes("anal")>><<set _serviceType = "anal">> <<elseif $brothelSessionChoices.includes("handjobs")>><<set _serviceType = "handjobs">> <<elseif $brothelSessionChoices.includes("roleplay")>><<set _serviceType = "roleplay">> <<elseif $brothelSessionChoices.includes("titWorship")>><<set _serviceType = "titWorship">> <<elseif $brothelSessionChoices.includes("titfuck")>><<set _serviceType = "titfuck">> <<elseif $brothelSessionChoices.includes("penisPlay")>><<set _serviceType = "penisPlay">> <</if>> <<set _brothelImagePath = setup.getBrothelImage(_serviceType, _client, _playerTraits, $brothelSessionChoices)>> <<if _brothelImagePath>> <div style="text-align: center; margin: 20px 0;"> <img @src="_brothelImagePath" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Brothel Session" onerror="this.style.display='none';"> </div> <</if>> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 16px; margin: 0; line-height: 1.6;"> <<if $brothelSessionChoices.includes("oralGiving")>> You guide <<print _client.name>> to the bed and position yourself between their legs. <<if _client.hasPenis>> Their cock stands hard and ready. You wrap your hand around the base, feeling it pulse. "Fuck..." they groan as your tongue swirls around the head. You work your mouth up and down, taking them deeper each time. Saliva drips down their shaft as you increase the pace. "Don't stop... fuck, don't stop!" they pant. <<else>> Their pussy is already glistening with arousal. You spread their lips gently, exposing their clit. "Please," they whimper. Your tongue makes contact and they gasp. You work your tongue in circles, occasionally dipping lower to taste their wetness. "Fuck... oh fuck!" they cry. <</if>> <<elseif $brothelSessionChoices.includes("vaginal")>> You climb onto the bed, spreading your legs invitingly. <<print _client.name>> positions themselves between your thighs. <<if _client.hasPenis>> Their cock presses against your entrance. "Ready?" You nod eagerly. They push inside. <<if $vaginaTightness === "tight">> "Ohh!" you gasp as they stretch you. The fullness is intense. "So... so full..." "Fuck, you're gripping me so tight," they groan, working deeper. <<else>> "Mmm..." you moan as they fill you. The sensation sends pleasure through you. "God, your pussy feels amazing," they groan, beginning to thrust. <</if>> Their hips slam against yours rhythmically. "Yes! Fuck yes!" you cry out. <</if>> <<elseif $brothelSessionChoices.includes("anal")>> You position yourself on hands and knees, ass raised invitingly. <<print _client.name>> applies lube generously. <<if _client.hasPenis>> "Relax," they murmur, pressing the head of their cock against your tight hole. You breathe deeply as they begin to push inside. "Ahh!" you gasp at the intense sensation. They start to thrust, slowly at first. "Oh god!" you moan, the fullness overwhelming. Each stroke hits deeper. "More... I can take more!" <<else>> They work their fingers into your ass, stretching you carefully. "How does that feel?" "Good... really good," you pant. They add another finger, scissoring them to open you further. <</if>> <<elseif $brothelSessionChoices.includes("handjobs")>> You coat your hands with oil, watching it glisten on your skin. <<if _client.hasPenis>> Wrapping both hands around <<print _client.name>>'s cock, you begin to stroke. "Mmm..." they moan immediately. Your slick hands glide up and down their shaft. "That feels incredible," they breathe. Their hips buck into your grip. "Fuck... fuck I'm close already," they pant. <<else>> Your oiled fingers find <<print _client.name>>'s clit, rubbing in slow circles. "Ohh..." they gasp. You slide lower, two fingers pushing into their wet pussy while your thumb continues working their clit. "Yes! Right there!" they cry. <</if>> <<elseif $brothelSessionChoices.includes("roleplay")>> You slip into character, transforming into whatever fantasy <<print _client.name>> desires. The scene unfolds with increasing intensity. "Yes... that's perfect," they breathe, fully immersed in the scenario. The roleplay becomes more physical, more intimate. <<elseif $brothelSessionChoices.includes("titWorship")>> <<set _chestSize = $bodyParts.chest.toLowerCase()>> You strip off your top, revealing your <<if _chestSize.includes("small")>> small, perky tits. Your nipples are already hard. <<elseif _chestSize.includes("medium")>> medium-sized tits. They're the perfect handful. <<elseif _chestSize.includes("large")>> large tits. They bounce heavily as you move. <<elseif _chestSize.includes("huge") || _chestSize.includes("giant") || _chestSize.includes("gigantic")>> massive tits. The enormous mounds jiggle with every movement. <</if>> <<print _client.name>>'s eyes go wide. Their hands immediately cup your breasts, squeezing and kneading. Their mouth finds your nipple, sucking hard. "Ahh!" you moan. They switch to your other nipple, licking and sucking. Their hands never stop groping your tits. <<elseif $brothelSessionChoices.includes("titfuck")>> <<set _chestSize = $bodyParts.chest.toLowerCase()>> <<if _client.hasPenis>> <<print _client.name>> pulls out their cock - it's already rock hard. You push them onto the bed and kneel between their legs. You spit on their cock, the saliva making everything slick. Then you wrap your tits around their shaft and start moving. <<if _chestSize.includes("medium")>> Your medium tits slide up and down their cock. You press them together tightly to create enough pressure. "Oh fuck," they groan. <<elseif _chestSize.includes("large")>> Your large tits envelope their cock completely. You bounce them up and down, the soft flesh massaging their entire shaft. "Holy shit!" they moan. <<else>> Your massive tits completely swallow their cock. There's so much soft tit-flesh that they can barely feel where their cock ends. You bounce your tits vigorously. "Oh my god! Your tits are so fucking huge!" they gasp. <</if>> Their cock is throbbing between your tits. You lean down and suck the tip each time it emerges from your cleavage. <<else>> You realize <<print _client.name>> doesn't have a cock. Instead, you guide their hands to your breasts for worship. They knead and squeeze your soft flesh eagerly. <</if>> <<elseif $brothelSessionChoices.includes("penisPlay")>> <<if _client.hasVagina>> You guide <<print _client.name>> to the bed, spreading their legs wide. Your cock throbs with anticipation as you position yourself. You push forward slowly, watching your shaft disappear into their wet heat. "Ohhh fuck!" they cry out, back arching. The tight warmth envelops you as you begin to thrust. "Yes... yes... harder!" Their walls clench around you with each stroke. <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">How Do You Enhance the Experience?</h2> <div style="display: grid; gap: 15px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>Talk Dirty</strong><br><span style='color: #aaa; font-size: 14px;'>Whisper filthy things in their ear</span></div>">> <<set $brothelSessionChoices.push("dirtyTalk")>> <<set $brothelSessionSkillsUsed.push("dirtyTalk")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>Slow & Sensual</strong><br><span style='color: #aaa; font-size: 14px;'>Take your time, savor every moment</span></div>">> <<set $brothelSessionChoices.push("sensual")>> <<set $brothelSessionSkillsUsed.push("sensual")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>Rough & Intense</strong><br><span style='color: #aaa; font-size: 14px;'>Increase the intensity and pace</span></div>">> <<set $brothelSessionChoices.push("rough")>> <<set $brothelSessionSkillsUsed.push("rough")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>Tease & Deny</strong><br><span style='color: #aaa; font-size: 14px;'>Build anticipation, make them beg</span></div>">> <<set $brothelSessionChoices.push("teasing")>> <<set $brothelSessionSkillsUsed.push("teasing")>> <<set $brothelSessionStage = 4>> <<goto "BrothelSession">> <</link>> </div> </div> <</if>> <!-- Stage 4: Building to Climax --> <<elseif $brothelSessionStage === 4>> <<if _isCerberus>> /* Cerberus three-head Stage 4: all three heads build toward climax per persona in their colors, then the same three finale options goto BrothelSessionResults. */ <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 16px; margin: 0; line-height: 1.6;"> <<if $brothelSessionChoices.includes("dirtyTalk")>> Three mouths lean in close, breath hot against <<print _client.name>>'s skin as the filth pours from every head at once.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> purrs in their ear. "You like that, don't you?"</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> snarls, "Tell us how good it feels. Now."<<else>><<print _nLeft>> growls something filthier still.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> whispers the worst of all, lips brushing their throat.</span><br> "So good... oh god it's so fucking good!" they cry, breathing ragged. "Please... please let me cum!" <<elseif $brothelSessionChoices.includes("sensual")>> Three heads slow everything down together, each touch deliberate. <<print _client.name>> whimpers at the change in pace.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> soothes, "Shh. Trust us."</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> murmurs softly, drawing the build out longer.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> breathes warm and unhurried against their neck.</span><br> The slow build has them trembling, every nerve on fire. "I... I've never felt anything like this," they breathe. <<elseif $brothelSessionChoices.includes("rough")>> Three heads snarl as one, the pace turning frantic, almost violent. Skin slaps against skin loudly.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> growls, "Is this what you wanted?"</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> bares her teeth, driving it harder.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> urges it rougher with a hungry snarl.</span><br> "Yes! Fuck yes!" they scream. "Harder! Fucking destroy me!" <<elseif $brothelSessionChoices.includes("teasing")>> Just as <<print _client.name>> gets close, all three heads pull back at once. "No! Please!" they whimper desperately.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> smiles wickedly. "Not yet."</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> laughs and denies them release again.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> teases just out of reach, edge after edge.</span><br> "Please... please I need to cum so badly," they beg, body trembling, hypersensitive to every touch. <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">The Finale</h2> <p style="color: #ccc; margin: 0 0 20px 0;">Three heads, one body, all racing toward the same release.</p> <div style="display: grid; gap: 15px;"> <<set _optStrong = '<div style="background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #e91e63;">Finish Strong</strong><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' pushes them over the edge.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' growls them through it.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' moans as they shatter.</span></div>'>> <<link _optStrong>> <<set $brothelSessionChoices.push("strong_finish")>> <<set $brothelSessionStage = 5>> <<goto "BrothelSessionResults">> <</link>> <<set _optMultiple = '<div style="background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #9b59b6;">Multiple Orgasms</strong> <span style="color: #aaa; font-size: 14px;">(Requires Stamina)</span><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' refuses to stop at just one.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' drives them into another wave.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' coaxes one more from them.</span></div>'>> <<link _optMultiple>> <<set $brothelSessionChoices.push("multiple")>> <<set $brothelSessionSkillsUsed.push("stamina")>> <<set $brothelSessionStage = 5>> <<goto "BrothelSessionResults">> <</link>> <<set _optSimul = '<div style="background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;">' + '<strong style="color: #51cf66;">Simultaneous Climax</strong> <span style="color: #aaa; font-size: 14px;">(Advanced)</span><br>' + '<span style="color: ' + _cCenter + '; font-size: 14px;">' + _nCenter + ' times it perfectly together.</span><br>' + '<span style="color: ' + _cLeft + '; font-size: 14px;">' + _nLeft + ' crests at the very same moment.</span><br>' + '<span style="color: ' + _cRight + '; font-size: 14px;">' + _nRight + ' falls with them in unison.</span></div>'>> <<link _optSimul>> <<set $brothelSessionChoices.push("simultaneous")>> <<set $brothelSessionSkillsUsed.push("rhythm")>> <<set $brothelSessionStage = 5>> <<goto "BrothelSessionResults">> <</link>> </div> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 16px; margin: 0; line-height: 1.6;"> <<if $brothelSessionChoices.includes("dirtyTalk")>> You lean in close, your breath hot against <<print _client.name>>'s ear. "You like that, don't you?" you whisper. "Fuck yes," they gasp. "Tell me how good it feels," you demand. "So good... oh god it's so fucking good!" they cry out. Their breathing becomes ragged, desperate. "Please... please let me cum!" <<elseif $brothelSessionChoices.includes("sensual")>> You slow everything down deliberately, making each touch meaningful. <<print _client.name>> whimpers at the change in pace. "No... don't slow down..." "Shh," you soothe. "Trust me." Minutes pass like hours. The slow build has them trembling, every nerve ending on fire. "I... I've never felt anything like this," they breathe. <<elseif $brothelSessionChoices.includes("rough")>> You grab <<print _client.name>> roughly, fingers digging into their flesh. "Is this what you wanted?" you growl. "Yes! Fuck yes!" they scream. The pace becomes frantic, almost violent. Skin slaps against skin loudly. "Harder!" they beg. "Fucking destroy me!" <<elseif $brothelSessionChoices.includes("teasing")>> Just as <<print _client.name>> gets close, you pull back. "No! Please!" they whimper desperately. "Not yet," you say with a wicked smile. You bring them to the edge again and again, each time denying their release. "Please... please I need to cum so badly," they beg. Their body is trembling, hypersensitive to every touch. <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #667eea; margin: 0 0 15px 0;">The Finale</h2> <div style="display: grid; gap: 15px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>Finish Strong</strong><br><span style='color: #aaa; font-size: 14px;'>Give them an explosive climax</span></div>">> <<set $brothelSessionChoices.push("strong_finish")>> <<set $brothelSessionStage = 5>> <<goto "BrothelSessionResults">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>Multiple Orgasms</strong><br><span style='color: #aaa; font-size: 14px;'>Don't stop at just one (Requires Stamina)</span></div>">> <<set $brothelSessionChoices.push("multiple")>> <<set $brothelSessionSkillsUsed.push("stamina")>> <<set $brothelSessionStage = 5>> <<goto "BrothelSessionResults">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>Simultaneous Climax</strong><br><span style='color: #aaa; font-size: 14px;'>Perfectly timed together (Advanced)</span></div>">> <<set $brothelSessionChoices.push("simultaneous")>> <<set $brothelSessionSkillsUsed.push("rhythm")>> <<set $brothelSessionStage = 5>> <<goto "BrothelSessionResults">> <</link>> </div> </div> <</if>> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Brothel">> <<set _client = $currentBrothelClient>> <!-- Check player personality traits --> <<set _isDominant = $mentalTraits.includes("Dominant") || $mentalTraits.includes("Aggressive") || $mentalTraits.includes("Arrogant")>> <<set _isSubmissive = $mentalTraits.includes("Submissive") || $mentalTraits.includes("Shy") || $mentalTraits.includes("Passive")>> <<set _isConfident = $mentalTraits.includes("Confident") || $mentalTraits.includes("Charming")>> <<set _isBitchy = $mentalTraits.includes("Bitchy") || $mentalTraits.includes("Arrogant") || $mentalTraits.includes("Rude")>> <<set _isKind = $mentalTraits.includes("Kind") || $mentalTraits.includes("Friendly") || $mentalTraits.includes("Warm")>> <<set _isFlirty = $mentalTraits.includes("Flirty") || $mentalTraits.includes("Seductive") || $mentalTraits.includes("Alluring")>> <<set _isAwkward = $mentalTraits.includes("Awkward") || $mentalTraits.includes("Shy")>> <<set _isProfessional = $mentalTraits.includes("Efficient") || $mentalTraits.includes("Direct") || $mentalTraits.includes("Hardworking")>> <<set _isEnergetic = $mentalTraits.includes("Energetic") || $mentalTraits.includes("Outgoing")>> <!-- Cerberus three-head persona setup for the climax scene --> <<set _isCerberus = $activeTransformation === "Cerberus">> <<if _isCerberus>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <</if>> <!-- Calculate satisfaction --> <<set _satisfaction = setup.calculateClientSatisfaction(_client, $brothelSessionChoices, $brothelSessionSkillsUsed)>> <!-- Update vagina tightness if applicable --> <<if $brothelSessionChoices.includes("vaginal") && $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("vagina")>> <<run setup.updateVaginaTightness()>> <</if>> <!-- Add sexual skill experience (scaled by satisfaction) --> <<set _sexualExpGains = []>> <<if $sexualSkills>> <<set _baseExpGain = 15 + random(-5, 5)>> <<set _expMultiplier = Math.max(0.3, _satisfaction / 100)>> <<set _finalExpGain = Math.floor(_baseExpGain * _expMultiplier)>> <!-- ===== SKILL TREE: Apply brothel XP bonus ===== --> <<set _brothelXPBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _brothelXPBonus = setup.skillTree.getEffect("brothelXPBonus") || 0>> <</if>> <<set _finalExpGain = _finalExpGain + _brothelXPBonus>> <<for _i = 0; _i < $brothelSessionSkillsUsed.length; _i++>> <<set _skillKey = $brothelSessionSkillsUsed[_i]>> <<if $sexualSkills[_skillKey]>> <<run setup.addSexualSkillExp(_skillKey, _finalExpGain)>> <<run _sexualExpGains.push({skill: setup.getSexualSkillDisplayName(_skillKey), amount: _finalExpGain})>> <</if>> <</for>> <</if>> <!-- Calculate payment --> <<set _satisfactionMultiplier = _satisfaction / 100>> <<set _payment = Math.floor(_client.basePay * _satisfactionMultiplier)>> <<set _tip = 0>> <<if _satisfaction >= 90>> <<set _tip = Math.floor(_payment * 0.5)>> <<elseif _satisfaction >= 75>> <<set _tip = Math.floor(_payment * 0.25)>> <<elseif _satisfaction >= 60>> <<set _tip = Math.floor(_payment * 0.1)>> <</if>> <<set _totalEarnings = _payment + _tip>> <!-- ===== SKILL TREE: Apply brothel pay bonus ===== --> <<set _brothelPayBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _brothelPayBonus = setup.skillTree.getEffect("brothelPayBonus") || 0>> <</if>> <<set _skillTreePayBonus = 0>> <<if _brothelPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_totalEarnings * (_brothelPayBonus / 100))>> <<set _totalEarnings = _totalEarnings + _skillTreePayBonus>> <</if>> <!-- Dominatrix 3x cash bonus for dominant acts --> <<set _dominatrixActive = $physicalTraits.includes("Dominatrix") && $brothelSessionChoices.includes("domination")>> <<set _dominatrixBonus = 0>> <<if _dominatrixActive>> <<set _dominatrixBonus = _totalEarnings * 2>> <<set _totalEarnings = _totalEarnings * 3>> <</if>> <!-- Slut 2x cash bonus for all sexual jobs --> <<set _slutActive = $physicalTraits.includes("Slut")>> <<set _slutBonus = 0>> <<if _slutActive>> <<set _slutBonus = _totalEarnings>> <<set _totalEarnings = _totalEarnings * 2>> <</if>> <!-- Pyrow +25% brothel pay on clear weather days --> <<set _pyrowBrothelActive = $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowBrothelBonus = 0>> <<if _pyrowBrothelActive>> <<set _pyrowBrothelBonus = Math.floor(_totalEarnings * 0.25)>> <<set _totalEarnings += _pyrowBrothelBonus>> <</if>> <!-- Honeybee +50% brothel pay with lustful buff --> <<set _honeybeeBrothelActive = $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _honeybeeBrothelBonus = 0>> <<if _honeybeeBrothelActive>> <<set _honeybeeBrothelBonus = Math.floor(_totalEarnings * 0.5)>> <<set _totalEarnings += _honeybeeBrothelBonus>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) - applies to total after skill tree bonus --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preArtifactEarnings = _totalEarnings>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.floor(_preArtifactEarnings * 0.5)>> <<set _totalEarnings = _preArtifactEarnings + _pearlBonus>> <</if>> <<set _totalEarnings = Math.round(_totalEarnings * setup.baskingCharmCashMult())>> <<set $money += _totalEarnings>> <<set $brothelClients += 1>> <<set $brothelClientsToday += 1>> <<set $timeInMinutes += 60>> <!-- Achievement for working in brothel --> <<run setup.achievements.unlock("work_brothel")>> <!-- Track jobs worked for work_every_job achievement --> <<if !$jobsWorked>> <<set $jobsWorked = []>> <</if>> <<if !$jobsWorked.includes("Brothel Worker")>> <<run $jobsWorked.push("Brothel Worker")>> <</if>> <<run setup.checkWorkEveryJobAchievement()>> <!-- Add Brothel Level XP based on satisfaction --> <<set _brothelExpGain = Math.floor((_satisfaction / 100) * (15 + random(-3, 3)))>> <!-- ===== SKILL TREE: Apply brothel XP bonus to level XP ===== --> <<if _brothelXPBonus > 0>> <<set _brothelExpGain = _brothelExpGain + _brothelXPBonus>> <</if>> <<run setup.addBrothelLevelExp(_brothelExpGain)>> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Session Complete</h1> <!-- Climax Image --> <<if $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _playerTraits = { isDominant: _isDominant, isSubmissive: _isSubmissive, isConfident: _isConfident, isBitchy: _isBitchy, isKind: _isKind, isFlirty: _isFlirty, isAwkward: _isAwkward, isProfessional: _isProfessional, isEnergetic: _isEnergetic, chestSize: $bodyParts.chest.toLowerCase(), hasVagina: $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("vagina"), hasPenis: $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("penis"), vaginaTight: (typeof $vaginaTightness !== "undefined" && $vaginaTightness === "tight") }>> <<set _climaxImagePath = setup.getBrothelImage("climax", _client, _playerTraits, $brothelSessionChoices)>> <<if _climaxImagePath>> <div style="text-align: center; margin: 20px 0;"> <img @src="_climaxImagePath" style="max-width: 100%; width: 600px; border-radius: 15px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Climax" onerror="this.style.display='none';"> </div> <</if>> <</if>> <!-- THE CLIMAX SCENE --> <div style="padding: 25px; background: linear-gradient(135deg, #4a1942 0%, #2d1628 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 6px 12px rgba(233,30,99,0.4);"> <h2 style="color: white; margin: 0 0 15px 0; text-align: center;">The Finale</h2> <p style="color: white; font-size: 16px; margin: 0; line-height: 1.8;"> <<if _isCerberus>> <<if $brothelSessionChoices.includes("strong_finish")>> Three heads bear down as one, pushing <<print _client.name>> over the edge with merciless precision. Their whole body tenses, the orgasm crashing through them.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> moans as they shatter, "That's it... give it to us."</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> growls them through every clenching wave.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> pants in time with their cries.</span><br> "FUCK! YES! OH GOD!" they scream, completely lost in ecstasy. <<elseif $brothelSessionChoices.includes("multiple")>> Three heads refuse to stop at just one, driving <<print _client.name>> through wave after wave of pleasure.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> coaxes, "One more. We know you have it."</span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> snarls, "Again. Don't you dare stop."<<else>><<print _nLeft>> urges them into another climax.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> drinks in their shaking body.</span><br> "Again... oh god again!" they cry, body shaking uncontrollably as you coax another climax from them. <<elseif $brothelSessionChoices.includes("simultaneous")>> Your shared body moves in perfect synchronization with <<print _client.name>>, all of you building together toward the peak.<br> <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> gasps, "Together..."</span><br> <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> crests at the very same instant.</span><br> <span @style="'color: ' + _cRight + ';'"><<print _nRight>> falls with them. "Together!"</span><br> All four of you cry out in unison as the orgasm hits, perfectly timed. <</if>> <<else>> <<if $brothelSessionChoices.includes("strong_finish")>> You push <<print _client.name>> over the edge with expert precision. Their whole body tenses, muscles clenching as the orgasm crashes through them. "FUCK! YES! OH GOD!" they scream, completely lost in ecstasy. <<elseif $brothelSessionChoices.includes("multiple")>> You don't let up after the first orgasm, pushing <<print _client.name>> through wave after wave of pleasure. "Again... oh god again!" they cry, body shaking uncontrollably as you coax another climax from them. <<elseif $brothelSessionChoices.includes("simultaneous")>> Your bodies move in perfect synchronization, building together toward the peak. "Together..." you gasp. "Together!" You both cry out in unison as the orgasm hits, perfectly timed. <</if>> <</if>> <br><br> After catching your breath, you both clean up. <<print _client.name>> gets dressed with a satisfied smile. <<if _satisfaction >= 90>> "That was absolutely amazing. Best money I've ever spent," they say, handing you payment plus a generous tip. <<elseif _satisfaction >= 75>> "That was really good. You certainly know what you're doing," they say approvingly, including a nice tip. <<elseif _satisfaction >= 60>> "Not bad. Worth the money," they say, adding a small tip. <<elseif _satisfaction >= 40>> "It was... okay," they say with a shrug, paying exactly what was agreed. <<else>> "That didn't really do it for me," they admit with disappointment, paying the minimum. <</if>> </p> <<if setup.getFutaVariant()>> <p style="color: #e040fb; font-size: 15px; margin: 15px 0 0 0; font-style: italic;"> <<if _client.gender === "male">> <<print _client.name>> can't stop staring at your body as you both recover, eyes flickering between your cock and your dripping pussy. "That was unreal," he pants. "Having both... the way you used everything... I've never come that hard in my life." <<else>> <<print _client.name>> lies trembling beside you, fingers still idly tracing your dual anatomy with wonder. "God, that was incredible," sshe whispers. "The way you could fuck me and let me touch you at the same time... I want to book you again. Exclusively." <</if>> </p> <</if>> </div> <!-- ===== SKILL TREE: Get sex skill XP bonus for display ===== --> <<set _sexSkillXPBonus = 0>> <<if typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function">> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus") || 0>> <</if>> <!-- Sexual XP Gained Display --> <<if _sexualExpGains.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3);"> <h2 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if _sexSkillXPBonus > 0>> <span style="color: #CE93D8;">⭐ +<<print _sexSkillXPBonus>>%</span> <</if>> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 3x Bonus!</span> <</if>> <<if $physicalTraits && $physicalTraits.includes("Slut")>> <span style="color: #e6c4ff;">✓ Slut 3x</span> <<elseif $physicalTraits && $physicalTraits.includes("Trophy Wife")>> <span style="color: #ffd700;">✓ Trophy Wife 2x</span> <<elseif $physicalTraits && $physicalTraits.includes("Siren")>> <span style="color: #7dd3fc;">✓ Siren 1.5x</span> <</if>> </h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-top: 15px;"> <<for _xp range _sexualExpGains>> <div style="background: #1a1a1a; padding: 10px; border-radius: 8px; border: 2px solid #ff69b4; text-align: center;"> <p style="color: #ff69b4; font-size: 14px; font-weight: bold; margin: 0;"><<print _xp.skill>></p> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 5px 0 0 0;">+<<print _xp.amount>> XP</p> </div> <</for>> </div> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Results Summary --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #667eea;"> <h2 style="color: #667eea; margin: 0 0 15px 0;">Session Results</h2> <div style="display: grid; gap: 15px; font-size: 15px; color: #ccc;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #e91e63;"> <strong style="color: #e91e63;">Client Satisfaction:</strong> <<if _satisfaction >= 90>> <span style="color: #51cf66;"><<print _satisfaction>>% - Extremely Satisfied! 🔥</span> <<elseif _satisfaction >= 75>> <span style="color: #51cf66;"><<print _satisfaction>>% - Very Satisfied</span> <<elseif _satisfaction >= 60>> <span style="color: #ffc107;"><<print _satisfaction>>% - Satisfied</span> <<elseif _satisfaction >= 40>> <span style="color: #ff9800;"><<print _satisfaction>>% - Somewhat Satisfied</span> <<else>> <span style="color: #ff6b6b;"><<print _satisfaction>>% - Dissatisfied</span> <</if>> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66;"> <strong style="color: #51cf66;">Earnings:</strong> <div style="margin-top: 8px;"> Base Pay: <span style="color: #51cf66;">$<<print _payment>></span><br> <<if _tip > 0>> Tip: <span style="color: #51cf66;">$<<print _tip>></span><br> <</if>> <<if _skillTreePayBonus > 0>> Skill Tree Bonus: <span style="color: #CE93D8;">$<<print _skillTreePayBonus>> (+<<print _brothelPayBonus>>%)</span><br> <</if>> <<if _dominatrixActive>> ✓ Dominatrix Bonus: <span style="color: #e91e63;">$<<print _dominatrixBonus>> (3x for domination)</span><br> <</if>> <<if _slutActive>> ✓ Slut Bonus: <span style="color: #ff69b4;">$<<print _slutBonus>> (2x sexual job cash)</span><br> <</if>> <<if _pearlActive>> Subtotal: <span style="color: #51cf66;">$<<print _preArtifactEarnings>></span><br> Pearl Bonus: <span style="color: #7dd3fc;">$<<print _pearlBonus>> (+50%)</span><br> <</if>> <strong>Total: <span style="color: #51cf66;">$<<print _totalEarnings>></span></strong> </div> </div> <<if $brothelSessionChoices.includes("vaginal") && $bodyParts.genitals && $bodyParts.genitals.toLowerCase().includes("vagina")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ff9800;"> <strong style="color: #ff9800;">Vagina Status:</strong> <span style="color: #aaa;"> <<if $vaginaTightness === "tight">> Still tight (<<print $vaginalSexCount>> times used) <<elseif $vaginaTightness === "normal">> Normal (<<print $vaginalSexCount>> times used) <<else>> Loose (<<print $vaginalSexCount>> times used) <</if>> </span> </div> <</if>> </div> </div> <!-- Co-worker relationship bonus (25% chance per co-worker since sessions are 1 hour) --> <<set _coworkerBonuses = []>> <<set _coworkers = setup.getNPCsByJob("Brothel Worker")>> <<if _coworkers && _coworkers.length > 0>> <<for _i = 0; _i < _coworkers.length; _i++>> <<set _coworker = _coworkers[_i]>> <<set _coworkerName = _coworker.name>> <<if random(1, 100) <= 25>> <<set _relPoints = random(1, 3)>> <<run setup.meetNPC(_coworker)>> <<run setup.addRelationshipPoints(_coworkerName, _relPoints)>> <<run _coworkerBonuses.push({name: _coworkerName, points: _relPoints})>> <</if>> <</for>> <</if>> <<if _coworkerBonuses.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #667eea;"> <h2 style="color: #667eea; margin: 0 0 15px 0;">👥 Co-Worker Bonding</h2> <p style="color: #aaa; margin-bottom: 15px;">You chatted with your co-workers between sessions!</p> <<for _cwb range _coworkerBonuses>> <div style="background: #1a2a3a; padding: 12px 15px; border-radius: 8px; margin-bottom: 8px; border: 2px solid #51cf66; display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ddd;">💚 <<print _cwb.name>></span> <span style="color: #51cf66; font-weight: bold;">+<<print _cwb.points>> points</span> </div> <</for>> </div> <</if>> <!-- Return to Brothel --> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 40px; border-radius: 10px; font-size: 18px; font-weight: bold; cursor: pointer; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.3);'>Return to Brothel</div>">> <<set $brothelSessionStage = null>> <<set $brothelSessionChoices = []>> <<set $brothelSessionSkillsUsed = []>> <<set $currentBrothelClient = null>> <<goto "Brothel">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* ---------------------------------- */ /* --- SEXUAL SKILLS SYSTEM INIT --- */ /* ---------------------------------- */ <<set setup.initializeSexualSkills = function() { var v = State.variables; if ((!v.skills || v.skills.indexOf("Sexually Skilled") === -1) && (!v.physicalTraits || (v.physicalTraits.indexOf("Pyrow") === -1 && v.physicalTraits.indexOf("Raiju") === -1 && (v.physicalTraits.indexOf("Succubus") === -1 && v.physicalTraits.indexOf("Voluptuous Succubus") === -1) && v.physicalTraits.indexOf("Slut") === -1))) { v.sexualSkills = null; return; } /* Define all 20 skill keys */ var allSkillKeys = ["oralGiving", "oralReceiving", "vaginal", "anal", "handjobs", "fingering", "teasing", "titWorship", "titfuck", "dirtyTalk", "roleplay", "domination", "submission", "sensual", "rough", "stamina", "flexibility", "rhythm", "exhibitionism", "fetishPlay"]; /* Create fresh if missing, or repair if corrupted/incomplete */ if (!v.sexualSkills || typeof v.sexualSkills !== "object") { v.sexualSkills = {}; } /* Ensure every skill key exists as a proper object */ var defaultSkill = {level: 1, exp: 0, maxExp: 100, tradedAway: false}; for (var idx = 0; idx < allSkillKeys.length; idx++) { var sk = allSkillKeys[idx]; var existing = v.sexualSkills[sk]; if (!existing || typeof existing !== "object" || typeof existing.level === "undefined") { /* Missing or corrupted (e.g. a plain number from old bug) — reset to default */ v.sexualSkills[sk] = {level: defaultSkill.level, exp: defaultSkill.exp, maxExp: defaultSkill.maxExp, tradedAway: defaultSkill.tradedAway}; } } if (!v.vaginaTightness && v.bodyParts.genitals && v.bodyParts.genitals.toLowerCase().indexOf("vagina") !== -1) { v.vaginaTightness = "tight"; v.vaginalSexCount = 0; } }>> <<set setup.updateVaginaTightness = function() { var v = State.variables; if (!v.bodyParts.genitals || v.bodyParts.genitals.toLowerCase().indexOf("vagina") === -1) { return; } if (!v.vaginalSexCount) v.vaginalSexCount = 0; if (!v.vaginaTightness) v.vaginaTightness = "tight"; v.vaginalSexCount++; if (v.vaginaTightness === "tight" && v.vaginalSexCount >= 15) { v.vaginaTightness = "normal"; v.bodyParts.genitals = "vagina"; } else if (v.vaginaTightness === "normal" && v.vaginalSexCount >= 50) { v.vaginaTightness = "loose"; v.bodyParts.genitals = "loose vagina"; } }>> <<set setup.addSexualSkillExp = function(skillKey, expAmount) { var v = State.variables; if (!v.sexualSkills || !v.sexualSkills[skillKey]) { return; } var skill = v.sexualSkills[skillKey]; var maxLevel = skill.tradedAway ? 5 : 10; if (skill.level >= maxLevel) { return; } var sexSkillXPBonus = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus") || 0; } if (sexSkillXPBonus > 0) { expAmount = Math.floor(expAmount * (1 + sexSkillXPBonus / 100)); } if ((v.skills && v.skills.indexOf("Quick Learner") !== -1) || (v.physicalTraits && v.physicalTraits.indexOf("Werefox") !== -1)) { expAmount = Math.floor(expAmount * 1.1); } /* Trophy Wife 2x sexual XP bonus */ if (v.physicalTraits && v.physicalTraits.includes("Trophy Wife")) { expAmount = expAmount * 2; } /* Siren 1.5x sexual XP bonus */ if (v.physicalTraits && v.physicalTraits.includes("Siren")) { expAmount = Math.floor(expAmount * 1.5); } /* Slut 3x sexual skill XP bonus */ if (v.physicalTraits && v.physicalTraits.includes("Slut")) { expAmount = expAmount * 3; } /* Basking Charm 4x sexual skill XP bonus */ if (v.currentArtifact === "The Basking Charm" || (v.physicalTraits && v.physicalTraits.includes("Naiad"))) { expAmount = expAmount * 4; } skill.exp += expAmount; while (skill.exp >= skill.maxExp && skill.level < maxLevel) { skill.exp -= skill.maxExp; skill.level++; skill.maxExp = Math.floor(skill.maxExp * 1.5); if (typeof setup.achievements !== "undefined" && setup.achievements.unlock) { setup.achievements.unlock("sex_skill_levelup"); } if (skill.level === 10 && !skill.tradedAway) { setup.unlockSexualTrait(skillKey); setup.checkAllSexualSkillsMaxed(); } } if (skill.level >= maxLevel) { skill.level = maxLevel; skill.exp = 0; } }>> <<set setup.checkAllSexualSkillsMaxed = function() { var v = State.variables; if (!v.sexualSkills) { return false; } var allMaxed = true; var skillKeys = Object.keys(v.sexualSkills); for (var i = 0; i < skillKeys.length; i++) { var skill = v.sexualSkills[skillKeys[i]]; var maxLevel = skill.tradedAway ? 5 : 10; if (skill.level < maxLevel) { allMaxed = false; break; } } if (allMaxed) { if (typeof setup.achievements !== "undefined" && setup.achievements.unlock) { setup.achievements.unlock("max_all_sex_skills"); } } return allMaxed; }>> <<set setup.unlockSexualTrait = function(skillKey) { var v = State.variables; var traitMap = { oralGiving: "Oral Expert", anal: "Anal Expert", dirtyTalk: "Dirty Talker", domination: "BDSM Enthusiast - Dom", submission: "BDSM Enthusiast - Sub", exhibitionism: "Exhibitionist", rough: "Rough Sex Enthusiast", sensual: "Sensual Lover", roleplay: "Roleplay Expert", stamina: "Sexual Stamina Expert", titWorship: "Tit Worship Expert", titfuck: "Titfuck Master" }; var traitToUnlock = traitMap[skillKey]; if (traitToUnlock && v.skills.indexOf(traitToUnlock) === -1) { v.skills.push(traitToUnlock); if (!v.sexualSkillUnlockMessages) { v.sexualSkillUnlockMessages = []; } v.sexualSkillUnlockMessages.push("🔥 Sexual Skill Maxed! You've unlocked the trait: " + traitToUnlock); } }>> <<set setup.checkTraitLoss = function(traitName) { var v = State.variables; var traitToSkill = { "Oral Expert": "oralGiving", "Anal Expert": "anal", "Dirty Talker": "dirtyTalk", "BDSM Enthusiast - Dom": "domination", "BDSM Enthusiast - Sub": "submission", "Exhibitionist": "exhibitionism", "Rough Sex Enthusiast": "rough", "Sensual Lover": "sensual", "Roleplay Expert": "roleplay", "Sexual Stamina Expert": "stamina", "Tit Worship Expert": "titWorship", "Titfuck Master": "titfuck" }; var skillKey = traitToSkill[traitName]; if (skillKey && v.sexualSkills && v.sexualSkills[skillKey]) { v.sexualSkills[skillKey].level = 5; v.sexualSkills[skillKey].exp = 0; v.sexualSkills[skillKey].maxExp = Math.floor(100 * Math.pow(1.5, 4)); v.sexualSkills[skillKey].tradedAway = true; } }>> <<set setup.checkTraitGain = function(traitName) { var v = State.variables; var traitToSkill = { "Oral Expert": "oralGiving", "Anal Expert": "anal", "Dirty Talker": "dirtyTalk", "BDSM Enthusiast - Dom": "domination", "BDSM Enthusiast - Sub": "submission", "Exhibitionist": "exhibitionism", "Rough Sex Enthusiast": "rough", "Sensual Lover": "sensual", "Roleplay Expert": "roleplay", "Sexual Stamina Expert": "stamina", "Tit Worship Expert": "titWorship", "Titfuck Master": "titfuck" }; var skillKey = traitToSkill[traitName]; if (skillKey && v.sexualSkills && v.sexualSkills[skillKey]) { v.sexualSkills[skillKey].level = 5; v.sexualSkills[skillKey].exp = 0; v.sexualSkills[skillKey].maxExp = Math.floor(100 * Math.pow(1.5, 4)); v.sexualSkills[skillKey].tradedAway = false; } }>> <<set setup.resetSexualSkills = function() { var v = State.variables; v.sexualSkills = null; }>> <<set setup.getSexualSkillBonus = function(skillKey) { var v = State.variables; if (!v.sexualSkills || !v.sexualSkills[skillKey]) { return 1.0; } return 1.0 + (v.sexualSkills[skillKey].level * 0.05); }>> <<set setup.getSexualSkillDisplayName = function(skillKey) { var names = { oralGiving: "Oral (Giving)", oralReceiving: "Oral (Receiving)", vaginal: "Vaginal", anal: "Anal", handjobs: "Handjobs", fingering: "Fingering", teasing: "Teasing", titWorship: "Tit Worship", titfuck: "Titfuck", dirtyTalk: "Dirty Talk", roleplay: "Roleplay", domination: "Domination", submission: "Submission", sensual: "Sensual", rough: "Rough", stamina: "Stamina", flexibility: "Flexibility", rhythm: "Rhythm", exhibitionism: "Exhibitionism", fetishPlay: "Fetish Play" }; return names[skillKey] || skillKey; }>> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubPerformRemoveTop">> <!-- Higher requirements --> <<set _requiredStats = {charisma: 40, dexterity: 35}>> <<set _bonus = setup.calculateStripClubBonus(_requiredStats)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set $stripperTopPerformed = $stripperTopPerformed || false>> <<set $stripperTopResult = $stripperTopResult || null>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FF69B4; text-align: center; text-shadow: 0 0 20px rgba(255, 105, 180, 0.8);">👚 Tease & Reveal</h1> <!-- Stat Check Display --> <<if typeof _effectiveCha !== 'undefined' && typeof _effectiveDex !== 'undefined' && typeof _bonus !== 'undefined'>> <div class="stat-check-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); border: 3px solid #FF69B4; padding: 20px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 0 20px rgba(255, 105, 180, 0.3);"> <h3 style="color: #FFB6C1; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveCha >= 40>>met<<else>>not-met<</if>>" style="color: <<if _effectiveCha >= 40>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Charisma: <<print _effectiveCha>> / 40 Required </div> <div class="stat-requirement <<if _effectiveDex >= 35>>met<<else>>not-met<</if>>" style="color: <<if _effectiveDex >= 35>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Dexterity: <<print _effectiveDex>> / 35 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <</if>> <!-- Action Choice --> <<if !$stripperTopPerformed>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #FF69B4; box-shadow: 0 0 25px rgba(255, 105, 180, 0.4);"> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You strut to center stage, hips swaying. The music's rhythm pulses through you. Your fingers trace along your collarbone, down between your breasts, teasing the hem of your top... </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> Time to give them a show. </p> </div> <div style="text-align: center; margin: 30px 0;"> <<link "<div class='action-choice-btn' style='display: inline-block; background: linear-gradient(135deg, #FF69B4 0%, #FF1493 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(255, 105, 180, 0.6); border: 2px solid #FF69B4;'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $stripperTopResult = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $stripperTopPerformed = true>> <<goto "StripClubPerformRemoveTop">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $stripperTopResult.total >= 50>> <<set _score = $stripperTopResult.total>> <<set _firstResolve = !$stripperTopResult.resolved>> <<set $stripperTopResult.resolved = true>> <div class="result-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.4)<<else>>rgba(255, 107, 107, 0.4)<</if>>;"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $stripperTopResult.roll>> + Bonus: <<print $stripperTopResult.bonus>> </div> <div class="result-score" style="font-size: 48px; font-weight: bold; color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; text-shadow: 0 0 20px <<if _success>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> <<print _score>> </div> </div> <!-- Performance Description --> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <<if _success>> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You move like liquid sin. Your hands glide over your body, tracing every curve as you sway to the beat. Slowly, teasingly, you lift your top inch by inch—revealing smooth skin, the swell of your breasts... </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd erupts in cheers as you finally pull it off, spinning it around before tossing it aside. You cup your bare breasts, squeezing them together, letting your hands roam. Every eye in the room is locked on you. Bills rain onto the stage. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You dance sensually, your top gradually riding up to show your midriff. With a coy smile, you turn around and slowly peel it off, revealing your bare back before spinning to show them your exposed breasts. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd hoots and hollers, clearly enjoying the view. Tips start appearing at the edge of the stage as you continue to move, topless and confident. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You dance to the music, gradually working your top off with playful movements. When it finally comes off, you continue dancing with your breasts bare, feeling the cool air on your skin. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd appreciates the show with some applause and a modest amount of tips. It was a solid performance. </p> <</if>> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to move sensually, but you feel awkward and stiff. Your top comes off clumsily, and you fumble a bit trying to maintain your rhythm. The exposure feels more embarrassing than empowering. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd's reaction is lukewarm. A few people toss some bills, but it's clear you didn't quite capture their attention. </p> <</if>> </div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 15px; padding: 20px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 10px; box-shadow: 0 0 15px rgba(224, 64, 251, 0.3);"> <p style="color: #f3e5f5; margin: 0; font-size: 16px; line-height: 1.7;"><<print setup.getFutaFlavorText("stripper_tease")>></p> </div> <</if>> <!-- Calculate tips --> <<set _baseTips = Math.floor(_score * 0.6)>> <<set _tipMultiplier = 1>> <<if $physicalTraits && $physicalTraits.includes("Attractive")>><<set _tipMultiplier += 0.2>><</if>> <<if $physicalTraits && $physicalTraits.includes("Alluring")>><<set _tipMultiplier += 0.15>><</if>> <<if $bodyParts.chest && ($bodyParts.chest.includes("large") || $bodyParts.chest.includes("huge") || $bodyParts.chest.includes("gigantic"))>> <<set _tipMultiplier += 0.25>> <</if>> <!-- Apply severe penalty for terrible performance (under 30) --> <<if _score < 30>> <<set _finalTips = Math.round((_baseTips * _tipMultiplier) * 0.1)>> <<else>> <<set _finalTips = Math.round(_baseTips * _tipMultiplier)>> <</if>> <!-- ===== SKILL TREE: Apply stripper pay bonus ===== --> <<set _stripperPayBonus = setup.skillTree.getEffect("stripperPayBonus")>> <<set _skillTreePayBonus = 0>> <<if _stripperPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_finalTips * (_stripperPayBonus / 100))>> <<set _finalTips = _finalTips + _skillTreePayBonus>> <</if>> <!-- Slut 2x cash bonus for strip club --> <<set _slutActive = $physicalTraits.includes("Slut")>> <<set _slutBonus = 0>> <<if _slutActive>> <<set _slutBonus = _finalTips>> <<set _finalTips = _finalTips * 2>> <</if>> <!-- Gyaru 1.5x cash bonus for strip club --> <<set _gyaruActive = $physicalTraits.includes("Gyaru")>> <<set _gyaruBonus = 0>> <<if _gyaruActive>> <<set _gyaruBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips = _finalTips + _gyaruBonus>> <</if>> <!-- Pyrow +25% stripper pay on clear weather days --> <<set _pyrowStripperActive = $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowStripperBonus = 0>> <<if _pyrowStripperActive>> <<set _pyrowStripperBonus = Math.floor(_finalTips * 0.25)>> <<set _finalTips += _pyrowStripperBonus>> <</if>> <!-- Honeybee +50% stripper pay with lustful buff --> <<set _honeybeeStripperActive = $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _honeybeeStripperBonus = 0>> <<if _honeybeeStripperActive>> <<set _honeybeeStripperBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips += _honeybeeStripperBonus>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preBonusTips = _finalTips>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_preBonusTips * 0.5)>> <<set _finalTips = _preBonusTips + _pearlBonus>> <</if>> <<set _finalTips = Math.round(_finalTips * setup.baskingCharmCashMult())>> <<if _firstResolve>> <<set $money += _finalTips>> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <!-- Sexual XP Gain --> <<set _sexualExpGains = []>> <<if _score >= 85>> <<if !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h3 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h3> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <span style="color: #ff69b4; font-weight: bold;">Exhibitionism</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Teasing</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- ===== SKILL TREE: Display pay bonus notification ===== --> <<if _skillTreePayBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4);"> <p style="color: #E1BEE7; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ⭐ Skill Tree Bonus: +$<<print _skillTreePayBonus>> (+<<print _stripperPayBonus>>%) ⭐ </p> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Earnings Display --> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); border: 3px solid #4ade80; padding: 25px; border-radius: 15px; text-align: center; margin-bottom: 25px; box-shadow: 0 0 25px rgba(74, 222, 128, 0.3);"> <h2 style="color: #4ade80; margin: 0 0 15px 0; text-shadow: 0 0 15px rgba(74, 222, 128, 0.6);">💰 Performance Earnings</h2> <div style="font-size: 42px; font-weight: bold; color: #FFD700; text-shadow: 0 0 20px rgba(255, 215, 0, 0.6);"> +$<<print _finalTips>> <<if _pearlActive>> <span style="color: #7dd3fc; font-size: 24px;">(+50%)</span> <</if>> </div> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> = $<<print _baseTips>><br> Pearl Bonus: <span style="color: #7dd3fc;">+$<<print _pearlBonus>></span> </p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> (trait bonuses) </p> <</if>> </div> <!-- Increment performance counter --> <<set $stagePerformancesToday += 1>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Back to Stage</div>">> <<goto "StripClubStagePerformance">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubPerformStripFull">> <!-- Higher requirements --> <<set _requiredStats = {charisma: 60, dexterity: 50}>> <<set _bonus = setup.calculateStripClubBonus(_requiredStats)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set $stripperFullPerformed = $stripperFullPerformed || false>> <<set $stripperFullResult = $stripperFullResult || null>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FF1493; text-align: center; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8);">🔥 Full Exposure</h1> <!-- Stat Check Display --> <<if typeof _effectiveCha !== 'undefined' && typeof _effectiveDex !== 'undefined' && typeof _bonus !== 'undefined'>> <div class="stat-check-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border: 3px solid #FF1493; padding: 20px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.4);"> <h3 style="color: #FFB6C1; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveCha >= 60>>met<<else>>not-met<</if>>" style="color: <<if _effectiveCha >= 60>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Charisma: <<print _effectiveCha>> / 60 Required </div> <div class="stat-requirement <<if _effectiveDex >= 50>>met<<else>>not-met<</if>>" style="color: <<if _effectiveDex >= 50>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Dexterity: <<print _effectiveDex>> / 50 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <</if>> <!-- Action Choice --> <<if !$stripperFullPerformed>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #FF1493; box-shadow: 0 0 25px rgba(255, 20, 147, 0.5);"> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> The spotlight blazes down on you. This is it—the full show, nothing held back. Every piece of clothing is going to come off. Every inch of your body on display for their hungry eyes. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> You take a deep breath. Time to bare it all. </p> </div> <div style="text-align: center; margin: 30px 0;"> <<link "<div class='action-choice-btn' style='display: inline-block; background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 25px rgba(255, 20, 147, 0.7); border: 2px solid #FF1493;'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $stripperFullResult = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $stripperFullPerformed = true>> <<goto "StripClubPerformStripFull">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $stripperFullResult.total >= 50>> <<set _score = $stripperFullResult.total>> <<set _firstResolve = !$stripperFullResult.resolved>> <<set $stripperFullResult.resolved = true>> <div class="result-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.4)<<else>>rgba(255, 107, 107, 0.4)<</if>>;"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $stripperFullResult.roll>> + Bonus: <<print $stripperFullResult.bonus>> </div> <div class="result-score" style="font-size: 48px; font-weight: bold; color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; text-shadow: 0 0 20px <<if _success>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> <<print _score>> </div> </div> <!-- Performance Description --> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <<if _success>> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You command the stage like a goddess. Each piece of clothing slides off with calculated precision—your top first, revealing your breasts to thunderous applause. Then your bottoms, inch by teasing inch... </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6;"> Finally, you're completely naked under the lights, every curve on display. You don't just stand there—you dance, you move, you touch yourself sensually. Your hands glide over your bare skin, cupping your breasts, sliding between your thighs. </p> <p style="color: #fff; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd goes absolutely wild. Money literally flies through the air. You've never felt more powerful, more desired. This is what being a star feels like. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You strip down methodically, piece by piece. Top off first, then bottoms. Soon you're completely nude, body exposed to the hungry crowd. You continue dancing, letting them admire every inch of you. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The audience loves it. Cheers fill the room as bills pile up on the stage. You feel sexy, confident, completely in control. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You manage to get all your clothes off, dancing naked for the crowd. It's not your smoothest performance, but you're fully exposed and that's what counts. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd appreciates the full nudity even if your technique wasn't perfect. Tips come in steadily. </p> <</if>> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You struggle through the routine, fumbling with your clothes. When you finally get naked, you feel awkward and exposed in a bad way. Your movements are stiff, self-conscious. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd's reaction is mixed. Some people tip out of pity, but it's clear you didn't deliver the sizzling performance they expected. </p> <</if>> </div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 15px; padding: 20px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 10px; box-shadow: 0 0 15px rgba(224, 64, 251, 0.3);"> <p style="color: #f3e5f5; margin: 0; font-size: 16px; line-height: 1.7;"><<print setup.getFutaFlavorText("performance_reveal")>></p> </div> <</if>> <!-- Calculate tips --> <<set _baseTips = Math.floor(_score * 1.5)>> <<set _tipMultiplier = 1>> <<if $physicalTraits && $physicalTraits.includes("Attractive")>><<set _tipMultiplier += 0.3>><</if>> <<if $physicalTraits && $physicalTraits.includes("Alluring")>><<set _tipMultiplier += 0.25>><</if>> <<if $physicalTraits && $physicalTraits.includes("Seductive")>><<set _tipMultiplier += 0.2>><</if>> <<if $bodyParts.chest && ($bodyParts.chest.includes("large") || $bodyParts.chest.includes("huge") || $bodyParts.chest.includes("gigantic"))>> <<set _tipMultiplier += 0.3>> <</if>> <<if $bodyParts.genitals && $bodyParts.genitals.includes("vagina")>> <<set _tipMultiplier += 0.2>> <</if>> <!-- Apply severe penalty for terrible performance (under 30) --> <<if _score < 30>> <<set _finalTips = Math.round((_baseTips * _tipMultiplier) * 0.1)>> <<else>> <<set _finalTips = Math.round(_baseTips * _tipMultiplier)>> <</if>> <!-- ===== SKILL TREE: Apply stripper pay bonus ===== --> <<set _stripperPayBonus = setup.skillTree.getEffect("stripperPayBonus")>> <<set _skillTreePayBonus = 0>> <<if _stripperPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_finalTips * (_stripperPayBonus / 100))>> <<set _finalTips = _finalTips + _skillTreePayBonus>> <</if>> <!-- Slut 2x cash bonus for strip club --> <<set _slutActive = $physicalTraits.includes("Slut")>> <<set _slutBonus = 0>> <<if _slutActive>> <<set _slutBonus = _finalTips>> <<set _finalTips = _finalTips * 2>> <</if>> <!-- Gyaru 1.5x cash bonus for strip club --> <<set _gyaruActive = $physicalTraits.includes("Gyaru")>> <<set _gyaruBonus = 0>> <<if _gyaruActive>> <<set _gyaruBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips = _finalTips + _gyaruBonus>> <</if>> <!-- Pyrow +25% stripper pay on clear weather days --> <<set _pyrowStripperActive = $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowStripperBonus = 0>> <<if _pyrowStripperActive>> <<set _pyrowStripperBonus = Math.floor(_finalTips * 0.25)>> <<set _finalTips += _pyrowStripperBonus>> <</if>> <!-- Honeybee +50% stripper pay with lustful buff --> <<set _honeybeeStripperActive = $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _honeybeeStripperBonus = 0>> <<if _honeybeeStripperActive>> <<set _honeybeeStripperBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips += _honeybeeStripperBonus>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preBonusTips = _finalTips>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_preBonusTips * 0.5)>> <<set _finalTips = _preBonusTips + _pearlBonus>> <</if>> <<set _finalTips = Math.round(_finalTips * setup.baskingCharmCashMult())>> <<if _firstResolve>> <<set $money += _finalTips>> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <!-- Sexual XP Gain --> <<set _sexualExpGains = []>> <<if _score >= 85>> <<if !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualExpGains.push({skill: "Sensual", amount: _finalXP})>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h3 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h3> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <span style="color: #ff69b4; font-weight: bold;">Exhibitionism</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Teasing</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Sensual</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- ===== SKILL TREE: Display pay bonus notification ===== --> <<if _skillTreePayBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4);"> <p style="color: #E1BEE7; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ⭐ Skill Tree Bonus: +$<<print _skillTreePayBonus>> (+<<print _stripperPayBonus>>%) ⭐ </p> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Earnings Display --> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); border: 3px solid #4ade80; padding: 25px; border-radius: 15px; text-align: center; margin-bottom: 25px; box-shadow: 0 0 25px rgba(74, 222, 128, 0.3);"> <h2 style="color: #4ade80; margin: 0 0 15px 0; text-shadow: 0 0 15px rgba(74, 222, 128, 0.6);">💰 Performance Earnings</h2> <div style="font-size: 42px; font-weight: bold; color: #FFD700; text-shadow: 0 0 20px rgba(255, 215, 0, 0.6);"> +$<<print _finalTips>> <<if _pearlActive>> <span style="color: #7dd3fc; font-size: 24px;">(+50%)</span> <</if>> </div> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> = $<<print _baseTips>><br> Pearl Bonus: <span style="color: #7dd3fc;">+$<<print _pearlBonus>></span> </p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> (trait bonuses) </p> <</if>> </div> <!-- Increment performance counter --> <<set $stagePerformancesToday += 1>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Back to Stage</div>">> <<goto "StripClubStagePerformance">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubPerformPole">> <!-- Higher requirements --> <<set _requiredStats = {dexterity: 70, strength: 65}>> <<set _bonus = setup.calculateStripClubBonus(_requiredStats)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <<set $stripperPolePerformed = $stripperPolePerformed || false>> <<set $stripperPoleResult = $stripperPoleResult || null>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9D00FF; text-align: center; text-shadow: 0 0 20px rgba(157, 0, 255, 0.8);">💫 Acrobatic Seduction</h1> <!-- Stat Check Display --> <<if typeof _effectiveDex !== 'undefined' && typeof _effectiveStr !== 'undefined' && typeof _bonus !== 'undefined'>> <div class="stat-check-display" style="background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); border: 3px solid #9D00FF; padding: 20px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.4);"> <h3 style="color: #D8BFD8; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveDex >= 70>>met<<else>>not-met<</if>>" style="color: <<if _effectiveDex >= 70>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Dexterity: <<print _effectiveDex>> / 70 Required </div> <div class="stat-requirement <<if _effectiveStr >= 65>>met<<else>>not-met<</if>>" style="color: <<if _effectiveStr >= 65>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Strength: <<print _effectiveStr>> / 65 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <</if>> <!-- Action Choice --> <<if !$stripperPolePerformed>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.4);"> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> The chrome pole gleams under the spotlight, waiting for you. This is where strength meets sensuality, where athletic prowess becomes erotic art. Time to show them what your body can really do. </p> <p style="color: #D8BFD8; font-size: 16px; margin: 0; line-height: 1.6;"> You grip the cold metal, feeling it against your palms. Let's fly. </p> </div> <div style="text-align: center; margin: 30px 0;"> <<link "<div class='action-choice-btn' style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.6); border: 2px solid #9D00FF;'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $stripperPoleResult = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $stripperPolePerformed = true>> <<goto "StripClubPerformPole">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $stripperPoleResult.total >= 50>> <<set _score = $stripperPoleResult.total>> <<set _firstResolve = !$stripperPoleResult.resolved>> <<set $stripperPoleResult.resolved = true>> <div class="result-display" style="background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2a 100%); border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.4)<<else>>rgba(255, 107, 107, 0.4)<</if>>;"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $stripperPoleResult.roll>> + Bonus: <<print $stripperPoleResult.bonus>> </div> <div class="result-score" style="font-size: 48px; font-weight: bold; color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; text-shadow: 0 0 20px <<if _success>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> <<print _score>> </div> </div> <!-- Performance Description --> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <<if _success>> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You launch into motion like a professional. Gripping the pole, you spin—once, twice—your body a blur of graceful movement. Then you climb, muscles flexing beautifully as you ascend. </p> <p style="color: #D8BFD8; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6;"> At the top, you hook your leg and lean back, arching your spine until you're nearly upside down, hair cascading toward the floor. Your top slips off naturally during a spin, your bare breasts catching the light as you twirl. You execute a perfect fireman spin, your thighs gripping the pole as your body spirals down in a controlled descent. </p> <p style="color: #fff; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd erupts. You transition seamlessly into floor work, writhing sensually against the stage. Every movement is poetry, strength disguised as softness. Bills shower down like rain. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You work the pole confidently, executing spins and climbs with practiced skill. Your body moves fluidly, muscles working in harmony. You manage some impressive inverted poses that show off your physique. </p> <p style="color: #D8BFD8; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd cheers as you incorporate some sensual movements between the athletic tricks. Tips accumulate steadily as you demonstrate both skill and sex appeal. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You manage some basic pole moves—spins and climbs that look decent. Nothing too advanced, but you keep it going without any major mistakes. </p> <p style="color: #D8BFD8; font-size: 16px; margin: 0; line-height: 1.6;"> The audience appreciates the effort. A respectable amount of tips come in for your athletic display. </p> <</if>> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You grip the pole but struggle to execute the moves. Your spins are wobbly, your climbs shaky. At one point you nearly slip, catching yourself just in time. </p> <p style="color: #D8BFD8; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd watches with concern more than arousal. You get some sympathy tips, but it's clear pole work isn't your strong suit. </p> <</if>> </div> <<if _success && setup.getFutaVariant()>> <div style="margin-top: 15px; padding: 20px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 10px; box-shadow: 0 0 15px rgba(224, 64, 251, 0.3);"> <p style="color: #f3e5f5; margin: 0; font-size: 16px; line-height: 1.7;"><<print setup.getFutaFlavorText("audience_reaction")>></p> </div> <</if>> <!-- Calculate tips --> <<set _baseTips = Math.floor(_score * 1.0)>> <<set _tipMultiplier = 1>> <<if $physicalTraits && $physicalTraits.includes("Athletic")>><<set _tipMultiplier += 0.3>><</if>> <<if $physicalTraits && $physicalTraits.includes("Graceful")>><<set _tipMultiplier += 0.25>><</if>> <<if $physicalTraits && $physicalTraits.includes("Flexible")>><<set _tipMultiplier += 0.2>><</if>> <<if $bodyParts.chest && ($bodyParts.chest.includes("large") || $bodyParts.chest.includes("huge") || $bodyParts.chest.includes("gigantic"))>> <<set _tipMultiplier += 0.2>> <</if>> <!-- Apply severe penalty for terrible performance (under 30) --> <<if _score < 30>> <<set _finalTips = Math.round((_baseTips * _tipMultiplier) * 0.1)>> <<else>> <<set _finalTips = Math.round(_baseTips * _tipMultiplier)>> <</if>> <!-- ===== SKILL TREE: Apply stripper pay bonus ===== --> <<set _stripperPayBonus = setup.skillTree.getEffect("stripperPayBonus")>> <<set _skillTreePayBonus = 0>> <<if _stripperPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_finalTips * (_stripperPayBonus / 100))>> <<set _finalTips = _finalTips + _skillTreePayBonus>> <</if>> <!-- Slut 2x cash bonus for strip club --> <<set _slutActive = $physicalTraits.includes("Slut")>> <<set _slutBonus = 0>> <<if _slutActive>> <<set _slutBonus = _finalTips>> <<set _finalTips = _finalTips * 2>> <</if>> <!-- Gyaru 1.5x cash bonus for strip club --> <<set _gyaruActive = $physicalTraits.includes("Gyaru")>> <<set _gyaruBonus = 0>> <<if _gyaruActive>> <<set _gyaruBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips = _finalTips + _gyaruBonus>> <</if>> <!-- Pyrow +25% stripper pay on clear weather days --> <<set _pyrowStripperActive = $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowStripperBonus = 0>> <<if _pyrowStripperActive>> <<set _pyrowStripperBonus = Math.floor(_finalTips * 0.25)>> <<set _finalTips += _pyrowStripperBonus>> <</if>> <!-- Honeybee +50% stripper pay with lustful buff --> <<set _honeybeeStripperActive = $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _honeybeeStripperBonus = 0>> <<if _honeybeeStripperActive>> <<set _honeybeeStripperBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips += _honeybeeStripperBonus>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preBonusTips = _finalTips>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_preBonusTips * 0.5)>> <<set _finalTips = _preBonusTips + _pearlBonus>> <</if>> <<set _finalTips = Math.round(_finalTips * setup.baskingCharmCashMult())>> <<if _firstResolve>> <<set $money += _finalTips>> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <!-- Sexual XP Gain --> <<set _sexualExpGains = []>> <<if _score >= 85>> <<if !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h3 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h3> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <span style="color: #ff69b4; font-weight: bold;">Exhibitionism</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Teasing</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- ===== SKILL TREE: Display pay bonus notification ===== --> <<if _skillTreePayBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4);"> <p style="color: #E1BEE7; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ⭐ Skill Tree Bonus: +$<<print _skillTreePayBonus>> (+<<print _stripperPayBonus>>%) ⭐ </p> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Earnings Display --> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); border: 3px solid #4ade80; padding: 25px; border-radius: 15px; text-align: center; margin-bottom: 25px; box-shadow: 0 0 25px rgba(74, 222, 128, 0.3);"> <h2 style="color: #4ade80; margin: 0 0 15px 0; text-shadow: 0 0 15px rgba(74, 222, 128, 0.6);">💰 Performance Earnings</h2> <div style="font-size: 42px; font-weight: bold; color: #FFD700; text-shadow: 0 0 20px rgba(255, 215, 0, 0.6);"> +$<<print _finalTips>> <<if _pearlActive>> <span style="color: #7dd3fc; font-size: 24px;">(+50%)</span> <</if>> </div> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> = $<<print _baseTips>><br> Pearl Bonus: <span style="color: #7dd3fc;">+$<<print _pearlBonus>></span> </p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> (trait bonuses) </p> <</if>> </div> <!-- Increment performance counter --> <<set $stagePerformancesToday += 1>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Back to Stage</div>">> <<goto "StripClubStagePerformance">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubPerformFreestyle">> <!-- Higher requirements --> <<set _requiredStats = {charisma: 55, dexterity: 45}>> <<set _bonus = setup.calculateStripClubBonus(_requiredStats)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set $stripperFreestylePerformed = $stripperFreestylePerformed || false>> <<set $stripperFreestyleResult = $stripperFreestyleResult || null>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #FFD700; text-align: center; text-shadow: 0 0 20px rgba(255, 215, 0, 0.8);">✨ Improvised Desire</h1> <!-- Stat Check Display --> <<if typeof _effectiveCha !== 'undefined' && typeof _effectiveDex !== 'undefined' && typeof _bonus !== 'undefined'>> <div class="stat-check-display" style="background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); border: 3px solid #FFD700; padding: 20px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 0 20px rgba(255, 215, 0, 0.4);"> <h3 style="color: #FFE4B5; margin-top: 0;">Requirements & Bonuses</h3> <div class="stat-requirement <<if _effectiveCha >= 55>>met<<else>>not-met<</if>>" style="color: <<if _effectiveCha >= 55>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Charisma: <<print _effectiveCha>> / 55 Required </div> <div class="stat-requirement <<if _effectiveDex >= 45>>met<<else>>not-met<</if>>" style="color: <<if _effectiveDex >= 45>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Dexterity: <<print _effectiveDex>> / 45 Required </div> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <</if>> <!-- Action Choice --> <<if !$stripperFreestylePerformed>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #FFD700; box-shadow: 0 0 25px rgba(255, 215, 0, 0.4);"> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> No routine. No choreography. Just you, the music, and pure instinct. This is where raw charisma and natural sensuality shine brightest. Feel the beat and let your body express what words cannot. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Close your eyes, feel the rhythm, and dance like only you can. </p> </div> <div style="text-align: center; margin: 30px 0;"> <<link "<div class='action-choice-btn' style='display: inline-block; background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(255, 215, 0, 0.6); border: 2px solid #FFD700;'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $stripperFreestyleResult = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $stripperFreestylePerformed = true>> <<goto "StripClubPerformFreestyle">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $stripperFreestyleResult.total >= 50>> <<set _score = $stripperFreestyleResult.total>> <<set _firstResolve = !$stripperFreestyleResult.resolved>> <<set $stripperFreestyleResult.resolved = true>> <div class="result-display" style="background: linear-gradient(135deg, #1a1a0a 0%, #2a2010 100%); border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.4)<<else>>rgba(255, 107, 107, 0.4)<</if>>;"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $stripperFreestyleResult.roll>> + Bonus: <<print $stripperFreestyleResult.bonus>> </div> <div class="result-score" style="font-size: 48px; font-weight: bold; color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; text-shadow: 0 0 20px <<if _success>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> <<print _score>> </div> </div> <!-- Performance Description --> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <<if _success>> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> The music flows through you like electricity. You move with pure, unfiltered sensuality—every sway of your hips, every arch of your back feels natural, inevitable. Your hands explore your own body, caressing curves as if discovering them for the first time. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6;"> You lock eyes with someone in the crowd and dance just for them, making them feel like the only person in the room. Then you turn to someone else, giving them that same intense, personal connection. Your energy radiates outward, drawing everyone into your orbit. </p> <p style="color: #fff; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd is mesmerized. This isn't just a performance—it's an experience, a moment of pure erotic magic. Money rains down as they try to capture a piece of what you're giving. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You move freely to the music, letting it guide your body. Your dancing feels natural and sexy, a genuine expression of sensuality. You make eye contact with the crowd, smile, move in ways that feel right in the moment. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> The audience responds positively to your authentic energy. Your charisma shines through, earning you good tips and genuine appreciation. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You dance in your own style, moving however feels natural. It's not spectacular, but it's genuine. The crowd appreciates your effort and individual expression. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Decent tips come in. People respect that you're being yourself on stage. </p> <</if>> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to let loose, but you can't quite find the rhythm. Your movements feel awkward and uncertain. The freedom of freestyle becomes overwhelming rather than liberating. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> The crowd remains polite but uninspired. A few sympathy tips appear, but you didn't quite connect with them. </p> <</if>> </div> <!-- Calculate tips --> <<set _baseTips = Math.floor(_score * 0.8)>> <<set _tipMultiplier = 1>> <<if $physicalTraits && $physicalTraits.includes("Attractive")>><<set _tipMultiplier += 0.25>><</if>> <<if $physicalTraits && $physicalTraits.includes("Alluring")>><<set _tipMultiplier += 0.3>><</if>> <<if $physicalTraits && $physicalTraits.includes("Seductive")>><<set _tipMultiplier += 0.25>><</if>> <<if $bodyParts.chest && ($bodyParts.chest.includes("large") || $bodyParts.chest.includes("huge") || $bodyParts.chest.includes("gigantic"))>> <<set _tipMultiplier += 0.2>> <</if>> <!-- Apply severe penalty for terrible performance (under 30) --> <<if _score < 30>> <<set _finalTips = Math.round((_baseTips * _tipMultiplier) * 0.1)>> <<else>> <<set _finalTips = Math.round(_baseTips * _tipMultiplier)>> <</if>> <!-- ===== SKILL TREE: Apply stripper pay bonus ===== --> <<set _stripperPayBonus = setup.skillTree.getEffect("stripperPayBonus")>> <<set _skillTreePayBonus = 0>> <<if _stripperPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_finalTips * (_stripperPayBonus / 100))>> <<set _finalTips = _finalTips + _skillTreePayBonus>> <</if>> <!-- Slut 2x cash bonus for strip club --> <<set _slutActive = $physicalTraits.includes("Slut")>> <<set _slutBonus = 0>> <<if _slutActive>> <<set _slutBonus = _finalTips>> <<set _finalTips = _finalTips * 2>> <</if>> <!-- Gyaru 1.5x cash bonus for strip club --> <<set _gyaruActive = $physicalTraits.includes("Gyaru")>> <<set _gyaruBonus = 0>> <<if _gyaruActive>> <<set _gyaruBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips = _finalTips + _gyaruBonus>> <</if>> <!-- Pyrow +25% stripper pay on clear weather days --> <<set _pyrowStripperActive = $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _pyrowStripperBonus = 0>> <<if _pyrowStripperActive>> <<set _pyrowStripperBonus = Math.floor(_finalTips * 0.25)>> <<set _finalTips += _pyrowStripperBonus>> <</if>> <!-- Honeybee +50% stripper pay with lustful buff --> <<set _honeybeeStripperActive = $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _honeybeeStripperBonus = 0>> <<if _honeybeeStripperActive>> <<set _honeybeeStripperBonus = Math.floor(_finalTips * 0.5)>> <<set _finalTips += _honeybeeStripperBonus>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preBonusTips = _finalTips>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_preBonusTips * 0.5)>> <<set _finalTips = _preBonusTips + _pearlBonus>> <</if>> <<set _finalTips = Math.round(_finalTips * setup.baskingCharmCashMult())>> <<if _firstResolve>> <<set $money += _finalTips>> <!-- Satisfy Slut sexual needs if applicable --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <!-- Sexual XP Gain --> <<set _sexualExpGains = []>> <<if _score >= 85>> <<if !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualExpGains.push({skill: "Sensual", amount: _finalXP})>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h3 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h3> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <span style="color: #ff69b4; font-weight: bold;">Exhibitionism</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Teasing</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Sensual</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- ===== SKILL TREE: Display pay bonus notification ===== --> <<if _skillTreePayBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4);"> <p style="color: #E1BEE7; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ⭐ Skill Tree Bonus: +$<<print _skillTreePayBonus>> (+<<print _stripperPayBonus>>%) ⭐ </p> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Earnings Display --> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); border: 3px solid #4ade80; padding: 25px; border-radius: 15px; text-align: center; margin-bottom: 25px; box-shadow: 0 0 25px rgba(74, 222, 128, 0.3);"> <h2 style="color: #4ade80; margin: 0 0 15px 0; text-shadow: 0 0 15px rgba(74, 222, 128, 0.6);">💰 Performance Earnings</h2> <div style="font-size: 42px; font-weight: bold; color: #FFD700; text-shadow: 0 0 20px rgba(255, 215, 0, 0.6);"> +$<<print _finalTips>> <<if _pearlActive>> <span style="color: #7dd3fc; font-size: 24px;">(+50%)</span> <</if>> </div> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> = $<<print _baseTips>><br> Pearl Bonus: <span style="color: #7dd3fc;">+$<<print _pearlBonus>></span> </p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base: $<<print Math.floor(_baseTips / _tipMultiplier)>> × <<print _tipMultiplier.toFixed(2)>> (trait bonuses) </p> <</if>> </div> <!-- Increment performance counter --> <<set $stagePerformancesToday += 1>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Back to Stage</div>">> <<goto "StripClubStagePerformance">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubVIPPrivateDanceStage2">> <<set $privateDanceStage = 2>> <<set _stripper = $currentVIPStriper>> <<set _stripperGender = (_stripper.bodyParts && _stripper.bodyParts.gender) || _stripper.gender || "female">> <<set _playerGender = $bodyParts.gender || "male">> <<set _tippedStage1 = $privateDanceActions.includes("tipped_stage1")>> <<set _touchedStage1 = $privateDanceActions.includes("touching_stage1")>> <<set _isSeductive = _stripper.physicalTraits && _stripper.physicalTraits.includes("Seductive")>> <<set _isConfident = _stripper.mentalTraits && _stripper.mentalTraits.includes("Confident")>> <<set _isShy = _stripper.mentalTraits && _stripper.mentalTraits.includes("Shy")>> <<set _isGraceful = _stripper.physicalTraits && _stripper.physicalTraits.includes("Graceful")>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FF1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.5), inset 0 0 20px rgba(157, 0, 255, 0.2);"> <h1 style="color: #FF1493; text-align: center; margin: 0; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8);">🔥 Building Heat</h1> </div> <!-- Performance Description --> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 35px; border-radius: 15px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.4), 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 30px;"> <<if _touchedStage1>> <!-- Player tipped for touching --> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<= _stripper.name>> smiles at your generous tip and moves closer, straddling your lap. Her heat radiates against you as she grinds slowly, deliberately. "You can touch," she breathes, taking your hands and placing them on her hips. <<else>> <<= _stripper.name>> grins at your tip and straddles your lap, his body pressed close. "Go ahead," he murmurs, guiding your hands to his chest. His skin is warm under your palms as he grinds against you. <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<if _isSeductive>> She moves sinuously in your lap, her top already half-unbuttoned. Your hands explore her curves—the dip of her waist, the swell of her hips. She lets out a soft moan when you squeeze, leaning back to give you a better view of her cleavage. <<elseif _isShy>> She blushes as your hands roam, but doesn't pull away. Instead, she rocks her hips slowly, biting her lip. "Does that feel good?" she asks quietly, her shyness making the moment even more intimate. <<else>> She peels off her top, revealing her breasts. Your hands cup them immediately, thumbs brushing over her nipples as she grinds harder. "Mmm, that's it," she purrs, arching into your touch. <</if>> <<else>> <<if _isSeductive>> He strips off his shirt, revealing his toned torso. Your hands explore his chest, his abs, feeling the muscles flex under your fingers. He grinds his ass against your crotch, making sure you feel exactly how hard you're getting him. <<elseif _isShy>> He lets you explore his body, gasping softly when your hands find sensitive spots. His movements are less practiced but more genuine, his arousal obvious through his pants. <<else>> He rocks against you, letting you feel his body. Your hands slide over his chest, down his stomach, and he doesn't stop you when you grip his ass, pulling him harder against you. <</if>> <</if>> </p> <<elseif _tippedStage1>> <!-- Player tipped but no touching --> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<= _stripper.name>> winks at your tip and ups her game. She slowly unbuttons her top, letting it fall open to reveal her breasts barely contained by a lacy bra. She cups them, squeezing, giving you a show. <<else>> <<= _stripper.name>> nods appreciatively at your tip and pulls off his shirt, revealing his toned chest. He runs his hands over his body, teasing, letting you see exactly what you're paying for. <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> She turns and bends over right in front of you, sliding her skirt down over the curve of her ass. Underneath, a tiny thong barely covers anything. She looks back, watching your reaction as she jiggles her ass for you. <<else>> He turns, giving you a view of his ass as he slides his pants down. His underwear clings to his muscled form. He looks over his shoulder with a smirk, knowing exactly what you're thinking. <</if>> </p> <<else>> <!-- No tip, standard performance --> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<= _stripper.name>> continues her routine, moving sensually but keeping things professional. She dances just out of reach, teasing but not delivering. Her clothes come off slowly—a strap here, a button there. <<else>> <<= _stripper.name>> keeps up his routine, moving skillfully but maintaining distance. He strips gradually, showing skin but keeping the real show just out of reach. <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> It's a good performance, but you can tell <<if _stripperGender === "female">>she's<<else>>he's<</if>> saving the best for paying customers. </p> <</if>> </div> <<if setup.getFutaVariant()>> <div style="margin-top: 15px; margin-bottom: 15px; padding: 20px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 10px; box-shadow: 0 0 15px rgba(224, 64, 251, 0.3);"> <p style="color: #f3e5f5; margin: 0; font-size: 16px; line-height: 1.7;"><<print setup.getFutaFlavorText("stripper_tease")>></p> </div> <</if>> <!-- Tip Options Stage 2 --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 30px; border: 3px solid #FFD700; box-shadow: 0 0 20px rgba(255, 215, 0, 0.3);"> <h3 style="color: #FFD700; margin: 0 0 20px 0; text-align: center; text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);">💵 Take It Further?</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <!-- Just Watch --> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #666;"> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0;">Continue watching</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>👀 Keep Watching</div>">> <<goto "StripClubVIPPrivateDanceStage3">> <</link>> </div> <!-- Tip $75 --> <<if $money >= 75>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 14px; margin: 0 0 10px 0;">Strip completely naked</p> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💵 Tip $75</div>">> <<set $money -= 75>> <<set $privateDanceTips += 75>> <<run $privateDanceActions.push("naked_stage2")>> <<goto "StripClubVIPPrivateDanceStage3">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #444; opacity: 0.5;"> <p style="color: #666; font-size: 14px; margin: 0 0 10px 0;">Strip completely naked</p> <div style='background: #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💵 Tip $75 (Broke)</div> </div> <</if>> <!-- Tip $150 --> <<if $money >= 150>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #FF1493;"> <p style="color: #FF1493; font-size: 14px; margin: 0 0 10px 0;">Get intimate, make me cum</p> <<link "<div style='background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💎 Tip $150</div>">> <<set $money -= 150>> <<set $privateDanceTips += 150>> <<run $privateDanceActions.push("intimate_stage2")>> <<goto "StripClubVIPPrivateDanceStage3">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #444; opacity: 0.5;"> <p style="color: #666; font-size: 14px; margin: 0 0 10px 0;">Get intimate, make me cum</p> <div style='background: #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>💎 Tip $150 (Broke)</div> </div> <</if>> <!-- Be Rude (Mistreatment) --> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ff6b6b;"> <p style="color: #ff6b6b; font-size: 14px; margin: 0 0 10px 0;">Demand more without tipping</p> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #e74c3c 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>😠 Be Demanding</div>">> <<set $privateDanceMistreated = true>> <<run $privateDanceActions.push("mistreated")>> <<goto "StripClubVIPPrivateDanceStage3">> <</link>> </div> </div> <p style="color: #888; font-size: 13px; margin: 15px 0 0 0; text-align: center; font-style: italic;"> Tips given: $<<print $privateDanceTips>> • Current balance: $<<print $money>> </p> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubVIPPrivateDanceStage3">> <<set $privateDanceStage = 3>> <<set _stripper = $currentVIPStriper>> <<set _stripperGender = (_stripper.bodyParts && _stripper.bodyParts.gender) || _stripper.gender || "female">> <<set _playerGender = $bodyParts.gender || "male">> <<set _nakedStage2 = $privateDanceActions.includes("naked_stage2")>> <<set _intimateStage2 = $privateDanceActions.includes("intimate_stage2")>> <<set _mistreated = $privateDanceActions.includes("mistreated")>> <<set _isSeductive = _stripper.physicalTraits && _stripper.physicalTraits.includes("Seductive")>> <<set _isConfident = _stripper.mentalTraits && _stripper.mentalTraits.includes("Confident")>> <<set _isShy = _stripper.mentalTraits && _stripper.mentalTraits.includes("Shy")>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FF1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.5), inset 0 0 20px rgba(157, 0, 255, 0.2);"> <h1 style="color: #FF1493; text-align: center; margin: 0; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8);">💦 The Finale</h1> </div> <!-- Performance Description --> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 35px; border-radius: 15px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.4), 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 30px;"> <<if _mistreated>> <!-- Mistreatment Path --> <p style="color: #ff6b6b; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<= _stripper.name>>'s expression hardens when you demand more without paying. "I'm not doing this for free," she says coldly, stepping back. "You want more? Tip more. Otherwise, we're done here." <<else>> <<= _stripper.name>> stops moving, his friendly demeanor evaporating. "That's not how this works," he says flatly. "Pay up or the show's over." <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The rest of the session is awkward and tense. <<if _stripperGender === "female">>She<<else>>He<</if>> finishes the bare minimum of the performance, clearly irritated. You've ruined the mood completely. </p> <<elseif _intimateStage2>> <!-- Intimate/Sexual Path --> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<= _stripper.name>> grins at your generous tip. "You want the full experience?" sshe purrs. "Then let's make it worth your money." <<if _playerGender === "female">> She strips completely naked, then helps you out of your clothes. Her hands explore your body expertly—cupping your breasts, sliding between your thighs. "Let me take care of you," sshe whispers. <<if _isSeductive>> She pushes you back onto the chair and kneels between your legs, her tongue finding your clit with practiced precision. She works you skillfully, fingers sliding inside as she sucks and licks. Your thighs tremble as pleasure builds. <<elseif _isShy>> She's hesitant at first, but when you guide her hand where you need it, she grows bolder. Her fingers circle your clit, finding the rhythm that makes you gasp. "Like that?" she asks breathlessly, watching your face. <<else>> She doesn't waste time. Her fingers plunge inside you while her thumb works your clit. She knows exactly what she's doing, bringing you right to the edge before backing off, teasing, making you beg. <</if>> <<else>> She strips naked and straddles you, grinding her bare pussy against the bulge in your pants. "Let's get these off," she murmurs, freeing your cock. It springs up, hard and ready. <<if _isSeductive>> She sinks down onto you slowly, eyes locked on yours. "Fuck," she moans as you fill her. She rides you with expert skill, rolling her hips, squeezing around you. Her hands brace on your shoulders as she bounces faster. <<elseif _isShy>> She blushes as she positions herself, sliding down onto your cock with a soft gasp. Her movements are slower, more tentative, but genuine. "You feel so good," she whispers, rocking against you. <<else>> She drops onto your cock in one smooth motion, moaning loudly. She rides you hard, breasts bouncing, head thrown back. "Yes, fuck yes," she groans, chasing her own pleasure as much as yours. <</if>> <</if>> <<else>> <<= _stripper.name>> smirks at your tip. "Alright, let's make this memorable," he says, stripping completely. <<if _playerGender === "female">> He helps you out of your clothes, his hands roaming over your body. His cock is already hard, pressing against you as he positions himself between your thighs. <<if _isSeductive>> He slides into you slowly, groaning at how wet you are. "Fuck, you feel amazing," he murmurs, starting to thrust. He knows how to use his body, hitting just the right spots, making you arch against him. <<elseif _isShy>> He enters you carefully, checking your reactions. When you pull him deeper, he starts moving with more confidence. His rhythm is less practiced but more intimate, genuine. <<else>> He pushes into you hard, starting a steady rhythm. His hips snap against yours, cock driving deep. "Take it," he grunts, fucking you thoroughly. <</if>> <<else>> He kneels in front of you, freeing your cock from your pants. "Let me show you what I can do," he murmurs before taking you into his mouth. <<if _isSeductive>> His technique is flawless—tongue swirling, throat relaxing to take you deep. He works your cock with expert skill, one hand massaging your balls, bringing you closer and closer to the edge. <<elseif _isShy>> He's less experienced but enthusiastic, bobbing his head eagerly. His hand strokes what won't fit in his mouth. He looks up at you, watching your reactions, learning what you like. <<else>> He deep-throats you without hesitation, gagging slightly but not stopping. He's rough, hungry for it, working to make you cum hard down his throat. <</if>> <</if>> <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<if _playerGender === "female">> She doesn't stop until you're crying out, thighs clamping around her head as you cum hard. She licks you through the aftershocks, grinning up at you. "Worth it?" she asks. <<else>> She rides you faster, chasing your orgasm and hers. When you finally cum, pumping into her, she moans and shudders through her own climax. She collapses against you, both of you breathing hard. <</if>> <<else>> <<if _playerGender === "female">> He fucks you until you're trembling, then groans as he cums inside you, his cock pulsing. He stays pressed against you for a moment, both of you catching your breath. <<else>> He doesn't let up until you're shooting down his throat. He swallows it all, pulling off with a satisfied grin. "Good?" he asks, wiping his mouth. <</if>> <</if>> </p> <<elseif _nakedStage2>> <!-- Naked but not sexual --> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">> <<= _stripper.name>> strips completely, standing naked before you. She moves closer, letting you see every inch of her body—breasts, curves, the smooth skin between her thighs. She dances nude, hands sliding over her own body sensually. She touches herself—cupping her breasts, fingers teasing between her legs—giving you a show that's intimate and erotic. <<else>> <<= _stripper.name>> strips down to nothing, his cock semi-hard as he moves. He's comfortable in his skin, showing off his body with confidence. He touches himself as he dances, hand wrapping around his cock, stroking slowly. He's putting on a show, making sure you see everything. <</if>> </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> The performance is incredibly hot, even without direct contact. <<if _stripperGender === "female">>She<<else>>He<</if>> knows exactly how to tease, how to make you desperate for more. </p> <<else>> <!-- Standard finish --> <p style="color: #fff; font-size: 18px; line-height: 1.8; margin: 0 0 20px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<= _stripper.name>> finishes the performance professionally. It was a good show—sexy, entertaining, worth the base price. </p> <p style="color: #FFB6C1; font-size: 17px; line-height: 1.8; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if _stripperGender === "female">>She<<else>>He<</if>> gives you a smile as the music fades. "Hope you enjoyed that," <<if _stripperGender === "female">>she<<else>>he<</if>> says, starting to get dressed. </p> <</if>> </div> <<if setup.getFutaVariant()>> <div style="margin-top: 15px; padding: 20px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 10px; box-shadow: 0 0 15px rgba(224, 64, 251, 0.3);"> <p style="color: #f3e5f5; margin: 0; font-size: 16px; line-height: 1.7;"><<print setup.getFutaFlavorText("stripper_tease")>></p> </div> <</if>> <!-- Continue to Results --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Continue →</div>">> <<goto "StripClubVIPPrivateDanceFinale">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubVIPPrivateDanceFinale">> <<set _stripper = $currentVIPStriper>> <<set _stripperGender = (_stripper.bodyParts && _stripper.bodyParts.gender) || _stripper.gender || "female">> <<set _mistreated = $privateDanceActions.includes("mistreated")>> <<set _intimateStage2 = $privateDanceActions.includes("intimate_stage2")>> <!-- Calculate relationship change --> <<set _relationshipChange = 0>> <<if _mistreated>> <<set _relationshipChange = -5>> <<else>> <!-- Base relationship gain --> <<set _relationshipChange = 3>> <!-- Bonus for tips --> <<if $privateDanceTips >= 300>> <<set _relationshipChange += 5>> <<elseif $privateDanceTips >= 200>> <<set _relationshipChange += 3>> <<elseif $privateDanceTips >= 100>> <<set _relationshipChange += 2>> <</if>> <!-- Extra bonus for intimate --> <<if _intimateStage2>> <<set _relationshipChange += 3>> <</if>> <</if>> <!-- Apply relationship change --> <<run setup.addRelationshipPoints(_stripper.name, _relationshipChange)>> /* Satisfy sexual needs if intimate path was taken (Slut/Raiju, Cheshire Cat) */ <<if _intimateStage2>> <<if typeof setup.satisfySlutSexualNeeds === "function">><<run setup.satisfySlutSexualNeeds()>><</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">><<run setup.satisfyCheshireCatSexualNeeds()>><</if>> <</if>> <!-- Advance time --> <<run advanceTime(30)>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 30px; background: linear-gradient(135deg, #1a0a1a 0%, #2a0510 100%); border-radius: 20px; margin-bottom: 30px; border: 3px solid #FF1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.5), inset 0 0 20px rgba(157, 0, 255, 0.2);"> <h1 style="color: #FF1493; text-align: center; margin: 0; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8);">✨ Session Complete</h1> </div> <!-- Relationship Change --> <<if _mistreated>> <div style="background: linear-gradient(135deg, #2a0a0a 0%, #1a0505 100%); padding: 25px; border-radius: 12px; margin-bottom: 30px; border: 3px solid #ff6b6b; box-shadow: 0 0 25px rgba(255, 107, 107, 0.4); text-align: center; animation: pulse-red 2s infinite;"> <p style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(255, 107, 107, 0.6);"> 💔 Relationship Damaged </p> <p style="color: #ff8787; font-size: 16px; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<= _stripper.name>> is clearly unhappy with how you treated <<if _stripperGender === "female">>her<<else>>him<</if>>. </p> <p style="color: #ff6b6b; font-size: 20px; font-weight: bold; margin: 10px 0 0 0;"> <<print _relationshipChange>> Relationship Points </p> </div> <style> @keyframes pulse-red { 0%, 100% { box-shadow: 0 0 25px rgba(255, 107, 107, 0.4); } 50% { box-shadow: 0 0 35px rgba(255, 107, 107, 0.7); } } </style> <<else>> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); padding: 25px; border-radius: 12px; margin-bottom: 30px; border: 3px solid #51cf66; box-shadow: 0 0 25px rgba(81, 207, 102, 0.4); text-align: center; animation: pulse-green 2s infinite;"> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(81, 207, 102, 0.6);"> 💕 Connection Deepened </p> <p style="color: #4ade80; font-size: 16px; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> Your relationship with <<= _stripper.name>> has improved! <<if ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #e91e63;">(💖 8x Bonus!)</span> <</if>> </p> <p style="color: #51cf66; font-size: 20px; font-weight: bold; margin: 10px 0 0 0;"> +<<print _relationshipChange>> Relationship Points </p> </div> <style> @keyframes pulse-green { 0%, 100% { box-shadow: 0 0 25px rgba(81, 207, 102, 0.4); } 50% { box-shadow: 0 0 35px rgba(81, 207, 102, 0.7); } } </style> <</if>> <!-- Session Summary --> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); padding: 35px; border-radius: 15px; border: 3px solid #9D00FF; box-shadow: 0 0 25px rgba(157, 0, 255, 0.4), 0 8px 16px rgba(0,0,0,0.6); margin-bottom: 30px; text-align: center;"> <h2 style="color: #FF69B4; margin: 0 0 20px 0; font-size: 28px; text-shadow: 0 0 15px rgba(255, 105, 180, 0.8);">Session Summary</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 20px;"> <p style="color: #FFD700; font-size: 20px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(255, 215, 0, 0.6);"> Total Tips: $<<print $privateDanceTips>> </p> <p style="color: #aaa; font-size: 14px; margin: 0;"> Base session fee already paid separately </p> </div> <<if !_mistreated>> <p style="color: #fff; font-size: 17px; line-height: 1.6; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<if $privateDanceTips >= 300>> <<= _stripper.name>> gives you a genuine smile as <<if _stripperGender === "female">>she<<else>>he<</if>> gets dressed. "You're one of my favorite clients," <<if _stripperGender === "female">>she<<else>>he<</if>> says warmly. "Come back anytime." <<elseif $privateDanceTips >= 100>> <<= _stripper.name>> looks pleased as <<if _stripperGender === "female">>she<<else>>he<</if>> finishes getting dressed. "That was fun," <<if _stripperGender === "female">>she<<else>>he<</if>> says with a smile. "Hope to see you again." <<else>> <<= _stripper.name>> nods politely as <<if _stripperGender === "female">>she<<else>>he<</if>> gets dressed. "Thanks for coming in," <<if _stripperGender === "female">>she<<else>>he<</if>> says professionally. <</if>> </p> <<else>> <p style="color: #ff8787; font-size: 17px; line-height: 1.6; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.8);"> <<= _stripper.name>> gets dressed quickly, clearly wanting this to be over. <<if _stripperGender === "female">>She<<else>>He<</if>> leaves without another word. </p> <</if>> </div> <!-- Clean up variables --> <<set $currentVIPStriper = null>> <<set $privateDanceTips = 0>> <<set $privateDanceStage = 0>> <<set $privateDanceActions = []>> <<set $privateDanceMistreated = false>> <<if setup.getFutaVariant()>> <div style="margin-top: 15px; padding: 20px; background: linear-gradient(135deg, #2a1a2a 0%, #1a0a2a 100%); border: 2px solid #e040fb; border-radius: 10px; box-shadow: 0 0 15px rgba(224, 64, 251, 0.3);"> <p style="color: #f3e5f5; margin: 0; font-size: 16px; line-height: 1.7;"><<print setup.getFutaFlavorText("stripper_tease")>></p> </div> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 40px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>← Back to VIP Lounge</div>">> <<goto "StripClubVIP">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StripClubPrivateShowPerform">> <!-- Get show type --> <<set _showType = $privateShowType>> <<set _stripper = $pc>> <!-- Player is the stripper --> <!-- Calculate bonus/penalty based on show type with HIGHER requirements --> <<if _showType === "lapdance">> <<set _requiredStats = {charisma: 35, dexterity: 30}>> <<set _duration = 15>> <<set _basePay = [50, 150]>> <<elseif _showType === "tease">> <<set _requiredStats = {charisma: 55, dexterity: 50}>> <<set _duration = 20>> <<set _basePay = [100, 250]>> <<elseif _showType === "pole">> <<set _requiredStats = {dexterity: 65, strength: 60}>> <<set _duration = 20>> <<set _basePay = [125, 300]>> <<elseif _showType === "roleplay">> <<set _requiredStats = {charisma: 75, intelligence: 70}>> <<set _duration = 30>> <<set _basePay = [150, 350]>> <<elseif _showType === "intimate">> <<set _requiredStats = {charisma: 35, dexterity: 35}>> <<set _duration = 20>> <<set _basePay = [60, 175]>> <<elseif _showType === "fullservice">> <<set _requiredStats = {charisma: 90}>> <<set _duration = 45>> <<set _basePay = [200, 500]>> <</if>> <<set _bonus = setup.calculateStripClubBonus(_requiredStats)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set _effectiveDex = ($stats.dexterity || 0) + (_statBonuses.dexterity || 0)>> <<set _effectiveStr = ($stats.strength || 0) + (_statBonuses.strength || 0)>> <<set _effectiveInt = ($stats.intelligence || 0) + (_statBonuses.intelligence || 0)>> <<set $privateShowPerformed = $privateShowPerformed || false>> <<set $privateShowResult = $privateShowResult || null>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <<if _showType === "lapdance">> <h1 style="color: #FF69B4; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(255, 105, 180, 0.8);">💋 Lap Dance</h1> <<elseif _showType === "tease">> <h1 style="color: #C71585; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(199, 21, 133, 0.8);">🌹 Sensual Tease</h1> <<elseif _showType === "pole">> <h1 style="color: #9D00FF; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(157, 0, 255, 0.8);">💫 Private Pole Show</h1> <<elseif _showType === "roleplay">> <h1 style="color: #FF1493; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(255, 20, 147, 0.8);">🎭 Roleplay Fantasy</h1> <<elseif _showType === "intimate">> <h1 style="color: #FFD700; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(255, 215, 0, 0.8);">✨ Intimate Dance</h1> <<elseif _showType === "fullservice">> <h1 style="color: #DC143C; text-align: center; font-size: 36px; text-shadow: 0 0 20px rgba(220, 20, 60, 0.8);">🔥 Full Experience</h1> <</if>> <!-- Stat Check Display --> <<if typeof _requiredStats !== 'undefined' && typeof _bonus !== 'undefined'>> <div class="stat-check-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); border: 3px solid #FF69B4; padding: 20px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 0 20px rgba(255, 105, 180, 0.3);"> <h3 style="color: #FFB6C1; margin-top: 0;">Requirements & Bonuses</h3> <<if _requiredStats.charisma>> <div style="color: <<if _effectiveCha >= _requiredStats.charisma>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Charisma: <<print _effectiveCha>> / <<print _requiredStats.charisma>> Required </div> <</if>> <<if _requiredStats.dexterity>> <div style="color: <<if _effectiveDex >= _requiredStats.dexterity>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Dexterity: <<print _effectiveDex>> / <<print _requiredStats.dexterity>> Required </div> <</if>> <<if _requiredStats.strength>> <div style="color: <<if _effectiveStr >= _requiredStats.strength>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Strength: <<print _effectiveStr>> / <<print _requiredStats.strength>> Required </div> <</if>> <<if _requiredStats.intelligence>> <div style="color: <<if _effectiveInt >= _requiredStats.intelligence>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Intelligence: <<print _effectiveInt>> / <<print _requiredStats.intelligence>> Required </div> <</if>> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <</if>> <!-- Action Choice or Result --> <<if !$privateShowPerformed>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #FF1493; box-shadow: 0 0 25px rgba(255, 20, 147, 0.4);"> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You lead the client to a private room. The door closes, and you're alone with them. Time to earn your money. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0; line-height: 1.6;"> How well can you perform? </p> </div> <div style="text-align: center; margin: 30px 0;"> <<link "<div class='action-choice-btn' style='display: inline-block; background: linear-gradient(135deg, #FF1493 0%, #C71585 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(255, 20, 147, 0.6); border: 2px solid #FF1493;'>🎲 Perform (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $privateShowResult = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $privateShowPerformed = true>> <<goto "StripClubPrivateShowPerform">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $privateShowResult.total >= 50>> <<set _score = $privateShowResult.total>> <<set _firstResolve = !$privateShowResult.resolved>> <<set $privateShowResult.resolved = true>> <div class="result-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.4)<<else>>rgba(255, 107, 107, 0.4)<</if>>;"> <h3 style="color: white; margin-top: 0;">Performance Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $privateShowResult.roll>> + Bonus: <<print $privateShowResult.bonus>> </div> <div class="result-score" style="font-size: 48px; font-weight: bold; color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; text-shadow: 0 0 20px <<if _success>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> <<print _score>> </div> </div> <!-- Performance Description --> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <<if _success>> <<if _showType === "lapdance">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You straddle the client's lap with expert confidence, grinding slowly and deliberately. Your body moves like silk, every roll of your hips calculated to drive them wild. You can feel their arousal pressing against you as you work. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client is absolutely mesmerized, hands gripping the chair to resist touching. You've given them the lap dance of their life, and they know it. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You move sensually in the client's lap, grinding against them with practiced skill. Your hands roam over your own body, giving them a show while maintaining that intimate contact. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client is clearly enjoying themselves, breathing heavily as you work. Solid performance. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0;"> You give them a decent lap dance, moving in their lap and keeping things sexy. Nothing spectacular, but competent enough to satisfy. </p> <</if>> <<elseif _showType === "tease">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You strip with agonizing slowness, making every piece of clothing a production. Each reveal is timed perfectly—a flash of skin here, a glimpse there. You touch yourself sensually, moaning softly, making sure they know exactly what they're seeing. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> By the time you're completely naked, the client is trembling with desire. You've teased them masterfully, and they're desperate for more. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You perform a sensual striptease, removing your clothes piece by piece while moving to the music. Your hands explore your body as you strip, putting on a good show. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client watches hungrily, clearly enjoying the intimate performance. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0;"> You strip down for them, moving sensually enough. It's a solid tease, nothing groundbreaking but satisfactory. </p> <</if>> <<elseif _showType === "pole">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You attack the pole with athletic grace, executing spins and inversions that showcase both strength and sensuality. You climb high, then drop into a controlled slide, your thighs gripping the chrome. Every move is both impressive and erotic. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client can't take their eyes off you. You've combined acrobatic skill with pure sex appeal, giving them a private show they'll never forget. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You work the pole confidently, executing impressive moves and combining them with sensual body rolls. It's both athletic and sexy. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client watches with appreciation, clearly impressed by your pole skills. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0;"> You manage some decent pole work, showing off your body while executing basic moves. Good enough. </p> <</if>> <<elseif _showType === "roleplay">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You embody the character perfectly, committing fully to the fantasy. Whether you're playing the innocent student, the dominant boss, or the seductive stranger, you make it feel real. Your improvisation is flawless, responding to their cues naturally. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client is completely immersed in the fantasy. You've given them an experience that blurs the line between performance and reality. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You play your role convincingly, maintaining character throughout and responding appropriately to the scenario. It's engaging and fun. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client enjoys the roleplay, appreciating your commitment to the fantasy. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0;"> You go through the roleplay scenario adequately, hitting the main beats even if not perfectly in character. </p> <</if>> <<elseif _showType === "intimate">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You dance inches from them, close enough that they can feel your body heat, smell your perfume. You maintain eye contact, making them feel like the only person in the world. Your movements are both sensual and personal, creating genuine connection. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The intimacy is electric. The client is captivated by you, lost in the moment. This felt less like a transaction and more like something real. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You dance close, creating an intimate atmosphere. Your eye contact and proximity make it feel personal and connected. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client responds well to the intimacy, clearly enjoying the personal attention. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0;"> You dance close and try to make it intimate. It's decent, if not particularly memorable. </p> <</if>> <<elseif _showType === "fullservice">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You give them everything. The dance transitions seamlessly into touching, then kissing, then more. You read their desires perfectly, knowing exactly when to lead and when to let them take control. Every moment is calculated to maximize their pleasure. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> By the time you're finished, the client is completely satisfied—physically, emotionally, and every other way that matters. You've delivered an experience they'll pay top dollar for again. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You provide the full experience—dancing, touching, and whatever else they paid for. You're skilled and attentive, making sure they get their money's worth. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client is clearly satisfied with what you've given them. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0;"> You deliver the services competently, meeting the basic expectations without going above and beyond. </p> <</if>> <</if>> <<else>> <!-- Failure descriptions --> <<if _showType === "lapdance">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to give them a lap dance, but your movements are awkward and uncertain. You can't quite find the rhythm, and the contact feels clumsy rather than sexy. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client sits through it politely, but you can tell they're disappointed. </p> <<elseif _showType === "tease">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> Your striptease feels rushed and graceless. You fumble with your clothes, losing the sensual momentum. It's more awkward than arousing. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client watches, but the magic isn't there. This wasn't the tease they paid for. </p> <<elseif _showType === "pole">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You struggle with the pole work, unable to execute the moves you planned. Your spins are shaky, your grip uncertain. It looks more difficult than sexy. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client watches with concern more than arousal. You need more practice. </p> <<elseif _showType === "roleplay">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You can't quite get into character, breaking the fantasy with awkward pauses and stilted dialogue. The roleplay feels forced and unconvincing. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client tries to play along, but the immersion is broken. This wasn't the fantasy they wanted. </p> <<elseif _showType === "intimate">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to create intimacy, but you can't quite connect. Your movements feel mechanical, the eye contact forced. The closeness feels awkward rather than sensual. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client seems uncomfortable. The intimacy never materialized. </p> <<elseif _showType === "fullservice">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You provide the services, but without skill or enthusiasm. It's perfunctory, mechanical. You're just going through the motions. </p> <p style="color: #FFB6C1; font-size: 16px; margin: 0;"> The client gets what they paid for technically, but there's no passion, no connection. They won't be back. </p> <</if>> <</if>> </div> <!-- Calculate payment with severe penalty for terrible performance --> <<if _score < 30>> <<set _paymentMultiplier = 0.1>> <<else>> <<set _paymentMultiplier = Math.max(0.5, Math.min(2.0, _score / 50))>> <</if>> <<set _baseAmount = Math.floor((_basePay[0] + _basePay[1]) / 2)>> <<set _finalPay = Math.round(_baseAmount * _paymentMultiplier)>> <!-- ===== SKILL TREE: Apply stripper pay bonus ===== --> <<set _stripperPayBonus = setup.skillTree.getEffect("stripperPayBonus")>> <<set _skillTreePayBonus = 0>> <<if _stripperPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_finalPay * (_stripperPayBonus / 100))>> <<set _finalPay = _finalPay + _skillTreePayBonus>> <</if>> <!-- Pyrow +25% stripper pay on clear weather days --> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _finalPay = Math.floor(_finalPay * 1.25)>> <</if>> <!-- Honeybee +50% stripper pay with lustful buff --> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _finalPay = Math.floor(_finalPay * 1.5)>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preBonusPay = _finalPay>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_preBonusPay * 0.5)>> <<set _finalPay = _preBonusPay + _pearlBonus>> <</if>> <<set _finalPay = Math.round(_finalPay * setup.baskingCharmCashMult())>> <<if _firstResolve>> <<set $money += _finalPay>> <!-- Sexual XP Gain --> <<set _sexualExpGains = []>> <<if _score >= 85>> <<if !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <!-- Apply XP based on show type --> <<if _showType === "lapdance" || _showType === "intimate">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<elseif _showType === "tease">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualExpGains.push({skill: "Sensual", amount: _finalXP})>> <<elseif _showType === "pole">> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <<elseif _showType === "roleplay">> <<run setup.addSexualSkillExp("dirtyTalk", _finalXP)>> <<run _sexualExpGains.push({skill: "Dirty Talk", amount: _finalXP})>> <<run setup.addSexualSkillExp("roleplay", _finalXP)>> <<run _sexualExpGains.push({skill: "Roleplay", amount: _finalXP})>> <<elseif _showType === "fullservice">> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualExpGains.push({skill: "Sensual", amount: _finalXP})>> <<run setup.addSexualSkillExp("exhibitionism", _finalXP)>> <<run _sexualExpGains.push({skill: "Exhibitionism", amount: _finalXP})>> <!-- Satisfy Slut sexual needs for fullservice --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <</if>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h3 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <span style="color: #ff9800;">☀️ 4x Bonus!</span> <</if>> </h3> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <<for _i = 0; _i < _sexualExpGains.length; _i++>> <span style="color: #ff69b4; font-weight: bold;"><<print _sexualExpGains[_i].skill>></span> <span style="color: #51cf66;">+<<print _sexualExpGains[_i].amount>> XP</span><<if _i < _sexualExpGains.length - 1>> | <</if>> <</for>> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- ===== SKILL TREE: Display pay bonus notification ===== --> <<if _skillTreePayBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4);"> <p style="color: #E1BEE7; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ⭐ Skill Tree Bonus: +$<<print _skillTreePayBonus>> (+<<print _stripperPayBonus>>%) ⭐ </p> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Earnings Display --> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); border: 3px solid #4ade80; padding: 25px; border-radius: 15px; text-align: center; margin-bottom: 25px; box-shadow: 0 0 25px rgba(74, 222, 128, 0.3);"> <h2 style="color: #4ade80; margin: 0 0 15px 0; text-shadow: 0 0 15px rgba(74, 222, 128, 0.6);">💰 Performance Earnings</h2> <div style="font-size: 42px; font-weight: bold; color: #FFD700; text-shadow: 0 0 20px rgba(255, 215, 0, 0.6);"> +$<<print _finalPay>> <<if _pearlActive>> <span style="color: #7dd3fc; font-size: 24px;">(+50%)</span> <</if>> </div> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base performance: $<<print _basePay>> (score: <<print _score>>)<br> Pearl Bonus: <span style="color: #7dd3fc;">+$<<print _pearlBonus>></span> </p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Performance score: <<print _score>> (<<print Math.round(_paymentMultiplier * 100)>>% of base pay) </p> <</if>> </div> <!-- Update counters --> <<set $privateShowsToday += 1>> <<run advanceTime(_duration)>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Back to VIP Lounge</div>">> <<goto "StripClubPrivateShows">> <</link>> </div> <</if>> </div> <</nobr>>
<<set setup.calculateStripClubBonus = function(requiredStats) { var v = State.variables; var bonus = 0; /* Calculate stat bonuses with HARSHER penalties (capped at -45 total) */ var statBonuses = setup.calculateStatBonuses(); var totalStatPenalty = 0; for (var stat in requiredStats) { var effectiveStat = (v.stats[stat] || 0) + (statBonuses[stat] || 0); var required = requiredStats[stat]; if (effectiveStat < required) { /* HARSH PENALTY: -3 per point below requirement */ var deficit = required - effectiveStat; totalStatPenalty -= deficit * 3; } else if (effectiveStat > required) { /* BONUS: +1 per point above requirement */ var surplus = effectiveStat - required; bonus += surplus * 1; } } /* Cap the total stat penalty at -45 */ if (totalStatPenalty < -45) { totalStatPenalty = -45; } bonus += totalStatPenalty; /* Sexual expertise trait bonuses (NOT Sexually Skilled) */ var sexualTraits = { "Exhibitionist": 8, "Sensual Lover": 10, "Dirty Talker": 6, "Roleplay Expert": 8, "Sexual Stamina Expert": 7, "Oral Expert": 5, "Tit Worship Expert": 6, "Titfuck Master": 6 }; if (v.skills) { v.skills.forEach(function(skill) { if (sexualTraits[skill]) { bonus += sexualTraits[skill]; } }); } /* Positive physical/mental traits */ var positiveTraits = { "Attractive": 7, "Alluring": 8, "Seductive": 9, "Graceful": 6, "Confident": 7, "Curvy": 5, "Voluptuous": 6, "Athletic": 5, "Flexible": 6, "High Energy": 4, "Charming": 6, "Flirty": 5 }; var applyTraitBonus = function(traitList) { if (!traitList) return; traitList.forEach(function(trait) { if (positiveTraits[trait]) { bonus += positiveTraits[trait]; } }); }; applyTraitBonus(v.physicalTraits); applyTraitBonus(v.mentalTraits); if (v.characterCreationTrait && positiveTraits[v.characterCreationTrait]) { bonus += positiveTraits[v.characterCreationTrait]; } /* Negative traits (penalties) */ var negativeTraits = { "Shy": -10, "Awkward": -8, "Ugly": -12, "Plain": -6, "Clumsy": -8, "Weak": -5, "Insecure": -7, "Cowardly": -6, "Stiff": -7, "Slow": -5, "Underweight": -4, "Overweight": -5, "Blemished": -5 }; var applyTraitPenalty = function(traitList) { if (!traitList) return; traitList.forEach(function(trait) { if (negativeTraits[trait]) { bonus += negativeTraits[trait]; } }); }; applyTraitPenalty(v.physicalTraits); applyTraitPenalty(v.mentalTraits); if (v.characterCreationTrait && negativeTraits[v.characterCreationTrait]) { bonus += negativeTraits[v.characterCreationTrait]; } /* Sunfish bonus (+10 to all rolls, but NOT XP) */ if (v.skills && v.skills.includes("Sunfish")) { bonus += 10; } return bonus; }>> <<set $stagePerformancesToday = 0>> <<set $mingleSessionsToday = 0>> <<set $privateShowsToday = 0>> <<set $maxStagePerformancesPerDay = 3>> <<set $maxMingleSessionsPerDay = 3>> <<set $maxPrivateShowsPerDay = 3>>
<<nobr>> <<set $lastLocation = "StripClubMingleInteraction">> <!-- Get customer type --> <<set _customerType = $mingleCustomerType>> <!-- Set requirements and pay based on customer type --> <<if _customerType === "shy">> <<set _requiredStats = {charisma: 30}>> <<set _duration = 10>> <<set _basePay = [13, 38]>> <<set _customerName = "Shy Regular">> <<set _customerColor = "#87CEEB">> <<elseif _customerType === "spender">> <<set _requiredStats = {charisma: 50}>> <<set _duration = 15>> <<set _basePay = [75, 200]>> <<set _customerName = "Big Spender">> <<set _customerColor = "#FFD700">> <<elseif _customerType === "bachelor">> <<set _requiredStats = {charisma: 40}>> <<set _duration = 20>> <<set _basePay = [25, 75]>> <<set _customerName = "Bachelor Party">> <<set _customerColor = "#FF6347">> <<elseif _customerType === "businessman">> <<set _requiredStats = {charisma: 45, intelligence: 35}>> <<set _duration = 15>> <<set _basePay = [30, 88]>> <<set _customerName = "Lonely Businessman">> <<set _customerColor = "#9370DB">> <<elseif _customerType === "couple">> <<set _requiredStats = {charisma: 65}>> <<set _duration = 20>> <<set _basePay = [90, 225]>> <<set _customerName = "Adventurous Couple">> <<set _customerColor = "#FF69B4">> <<elseif _customerType === "vip">> <<set _requiredStats = {charisma: 80}>> <<set _duration = 25>> <<set _basePay = [125, 300]>> <<set _customerName = "VIP High Roller">> <<set _customerColor = "#FF1493">> <</if>> <<set _bonus = setup.calculateStripClubBonus(_requiredStats)>> <!-- Calculate effective stats for display --> <<set _statBonuses = setup.calculateStatBonuses()>> <<set _effectiveCha = ($stats.charisma || 0) + (_statBonuses.charisma || 0)>> <<set _effectiveInt = ($stats.intelligence || 0) + (_statBonuses.intelligence || 0)>> <<set $minglePerformed = $minglePerformed || false>> <<set $mingleResult = $mingleResult || null>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: <<print _customerColor>>; text-align: center; font-size: 36px; text-shadow: 0 0 20px <<print _customerColor>>;"><<print _customerName>></h1> <!-- Stat Check Display --> <div class="stat-check-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); border: 3px solid <<print _customerColor>>; padding: 20px; border-radius: 12px; margin-bottom: 25px; box-shadow: 0 0 20px rgba(255, 215, 0, 0.3);"> <h3 style="color: #FFE4B5; margin-top: 0;">Requirements & Bonuses</h3> <<if _requiredStats.charisma>> <div style="color: <<if _effectiveCha >= _requiredStats.charisma>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Charisma: <<print _effectiveCha>> / <<print _requiredStats.charisma>> Required </div> <</if>> <<if _requiredStats.intelligence>> <div style="color: <<if _effectiveInt >= _requiredStats.intelligence>>#4ade80<<else>>#ff6b6b<</if>>; margin: 8px 0;"> Intelligence: <<print _effectiveInt>> / <<print _requiredStats.intelligence>> Required </div> <</if>> <<if _bonus > 0>> <div style="color: #4ade80; margin-top: 10px;">✓ Total Bonus: +<<print _bonus>></div> <<elseif _bonus < 0>> <div style="color: #ff6b6b; margin-top: 10px;">⚠ Total Penalty: <<print _bonus>></div> <</if>> </div> <!-- Action Choice or Result --> <<if !$minglePerformed>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<print _customerColor>>; box-shadow: 0 0 25px rgba(255, 215, 0, 0.4);"> <<if _customerType === "shy">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> They're sitting alone at a corner table, nursing a drink and trying not to make eye contact with anyone. You can see the nervousness in their posture—shoulders hunched, hands fidgeting. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A gentle approach should work here. Make them feel comfortable, not overwhelmed. </p> <<elseif _customerType === "spender">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> Designer suit, expensive cologne, confident demeanor. This one's dripping with money and knows it. They're used to getting what they want, and right now they're scanning the room like they own it. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Time to show them something worth paying for. Confidence and allure are key. </p> <<elseif _customerType === "bachelor">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> The group is loud, already several drinks in, laughing and shoving each other. The groom-to-be sits in the middle, wearing a ridiculous sash. They're rowdy, energetic, and looking for someone to amp up their celebration. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Play to the crowd. Keep the energy high and make it a night they'll remember. </p> <<elseif _customerType === "businessman">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> Loosened tie, tired eyes, wedding ring. They look stressed, isolated, probably in town for some conference. They're not here for wild entertainment—they're here because their hotel room felt too lonely. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> This one needs connection more than spectacle. Listen, engage, make them feel understood. </p> <<elseif _customerType === "couple">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> They're sitting close together, whispering and giggling, occasionally glancing at the dancers. There's an electric tension between them—they're here to add some spice to their relationship, push some boundaries together. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Tricky territory. Flirt with both, favor neither. Make them feel like a team, not rivals. </p> <<elseif _customerType === "vip">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> VIP section, bottle service, entourage keeping their distance. This is the club's biggest whale, the one everyone wants to impress. Their standards are impossibly high, their patience nonexistent. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> This is the ultimate test. You need to be perfect—charming, sexy, attentive, flawless. One mistake and you're dismissed. </p> <</if>> </div> <div style="text-align: center; margin: 30px 0;"> <<link "<div class='action-choice-btn' style='display: inline-block; background: linear-gradient(135deg, <<print _customerColor>> 0%, #C71585 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(255, 215, 0, 0.6); border: 2px solid <<print _customerColor>>;'>🎲 Work Your Magic (Roll d100)</div>">> <<set _rollValue = random(1, 100)>> <<set $mingleResult = {roll: _rollValue, bonus: _bonus, total: _rollValue + _bonus}>> <<set $minglePerformed = true>> <<goto "StripClubMingleInteraction">> <</link>> </div> <<else>> <!-- Show Result --> <<set _success = $mingleResult.total >= 50>> <<set _score = $mingleResult.total>> <<set _firstResolve = !$mingleResult.resolved>> <<set $mingleResult.resolved = true>> <div class="result-display" style="background: linear-gradient(135deg, #1a0a1a 0%, #2a0a1a 100%); border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.4)<<else>>rgba(255, 107, 107, 0.4)<</if>>;"> <h3 style="color: white; margin-top: 0;">Interaction Result</h3> <div style="color: #aaa; margin: 10px 0;"> Roll: <<print $mingleResult.roll>> + Bonus: <<print $mingleResult.bonus>> </div> <div class="result-score" style="font-size: 48px; font-weight: bold; color: <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; text-shadow: 0 0 20px <<if _success>>rgba(74, 222, 128, 0.6)<<else>>rgba(255, 107, 107, 0.6)<</if>>;"> <<print _score>> </div> </div> <!-- Interaction Description --> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a1a 0%, #0a0520 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _success>>#4ade80<<else>>#ff6b6b<</if>>; box-shadow: 0 0 25px <<if _success>>rgba(74, 222, 128, 0.3)<<else>>rgba(255, 107, 107, 0.3)<</if>>;"> <<if _success>> <!-- Success outcomes --> <<if _customerType === "shy">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You approach with a warm smile, not too aggressive. "First time here?" you ask gently. They nod, clearly relieved you're being kind. You sit close—not too close—and chat about nothing important, making them laugh with light jokes. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Gradually, they open up. By the end, they're smiling genuinely, relaxed, grateful for the company. They tip generously for making them feel welcome and comfortable. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You chat with them kindly, making small talk and helping them relax. They appreciate the gentle attention and start to loosen up a bit. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They leave a decent tip with a shy smile, clearly glad you approached them. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You manage to get them talking a little. It's a bit awkward, but they seem to appreciate the effort. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A modest tip appears on the table as you leave. </p> <</if>> <<elseif _customerType === "spender">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You saunter over with perfect confidence, hip cocked, making eye contact that says you know exactly what they want. "Looking lonely over here," you purr. They grin—they like confidence. You flirt hard, touching their arm, leaning in close, letting them smell your perfume. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> You're witty, sexy, attentive—everything they're paying premium prices for. When you finally excuse yourself, they peel off bills from a thick stack without even counting. You've earned every dollar. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You flirt confidently, showing off your best assets and keeping their attention. They clearly enjoy the attention and your company. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A generous tip rewards your efforts—they got what they came for. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You do your best to impress them, flirting and chatting. They seem satisfied enough with the attention. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip decently, though you sense they've had better. </p> <</if>> <<elseif _customerType === "bachelor">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You charge in with high energy, immediately making the groom the center of attention. "So which one of you lucky bastards is getting married?" The table erupts in laughter and pointing. You tease him mercilessly, getting the whole group involved, making jokes and playing along with their energy. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> You keep them entertained, laughing, feeling like rock stars. Every guy at the table contributes to the tip pile, not wanting to look cheap in front of his friends. It adds up fast. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You join their party energy, laughing at their jokes and giving the groom special attention. They're having a great time with you at their table. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> The whole group chips in for tips, creating a nice pile of bills. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You hang out with the group, trying to keep up with their rowdy energy. It's decent entertainment for them. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip collectively—nothing spectacular but respectable. </p> <</if>> <<elseif _customerType === "businessman">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You slide into the seat across from them with a sympathetic smile. "Rough day?" They laugh bitterly—understatement of the year. You actually listen as they vent about work, the hotel, missing their family. You ask thoughtful questions, share your own stories, make them feel heard. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> For twenty minutes, you give them genuine human connection. When you leave, they press a hefty tip into your hand and thank you sincerely. You made their lonely night bearable. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You engage them in conversation, listening to their stories and making them feel less alone. They appreciate having someone to talk to. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A solid tip follows the conversation—they needed that. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You chat with them about their day and life. It's decent conversation, nothing deep but friendly enough. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip adequately for the company. </p> <</if>> <<elseif _customerType === "couple">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> This is delicate work. You approach with a flirtatious smile for both of them. "You two make a gorgeous couple," you start, making sure to compliment them as a unit. You flirt with her, then him, then back to her—keeping perfect balance, never playing favorites. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> You read their dynamic perfectly, knowing when to touch her hand, when to lean toward him, when to suggest they both deserve to feel sexy tonight. They leave glowing and excited, tipping big for adding fuel to their fire. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You navigate the couple dynamic well, flirting with both and making them both feel included. They seem to enjoy the attention together. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip generously as a couple, both contributing. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to balance attention between them, flirting with both. It's a bit awkward but they seem to appreciate the effort. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A decent combined tip appears. </p> <</if>> <<elseif _customerType === "vip">> <<if _score >= 90>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You approach the VIP table like you belong there. Perfect posture, perfect smile, perfect confidence. You read them instantly—what they want, how they want to be treated. You're charming without being desperate, sexy without being crude, attentive without being clingy. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> Every word, every gesture is calculated perfection. They're impressed—genuinely impressed. When you excuse yourself gracefully at just the right moment, they hand you a tip that makes your heart skip. You just earned VIP status yourself. </p> <<elseif _score >= 70>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You handle yourself well in the VIP section, staying professional and charming. They seem satisfied with the interaction. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A very generous tip—they pay for quality. </p> <<else>> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You do your best to impress the VIP, though you can tell you're not quite hitting their high standards. Still, they're courteous. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip well because they always do, not because you wowed them. </p> <</if>> <</if>> <<else>> <!-- Failure outcomes --> <<if _customerType === "shy">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to chat them up, but you come on too strong or too awkward. They shrink back, clearly uncomfortable. The conversation dies quickly. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They leave a small tip out of politeness, but you clearly made them more anxious than relaxed. </p> <<elseif _customerType === "spender">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to impress them, but you're not quite on their wavelength. Your flirting feels forced, your charm hollow. They check their phone while you're talking. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip minimally—they've had much better and they know it. </p> <<elseif _customerType === "bachelor">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to match their energy but can't quite get on their level. Your jokes fall flat, your timing is off. They're polite but not engaged. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A small collective tip emerges, mostly out of courtesy. </p> <<elseif _customerType === "businessman">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You try to engage them in conversation, but you can't quite connect. Your questions feel shallow, your responses generic. They remain polite but distant. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> A minimal tip—you didn't give them what they needed. </p> <<elseif _customerType === "couple">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You can't quite balance the dynamic. You favor one too much, or make the other feel excluded. Tension creeps into their body language. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> They tip small—you didn't enhance their experience, you complicated it. </p> <<elseif _customerType === "vip">> <p style="color: #fff; font-size: 18px; margin: 0 0 15px 0; line-height: 1.6;"> You're in over your head and it shows. You're trying too hard, or not hard enough. They see through everything—every forced smile, every calculated word. Within minutes, they politely dismiss you. </p> <p style="color: #FFE4B5; font-size: 16px; margin: 0; line-height: 1.6;"> The minimum tip appears out of obligation, not appreciation. You weren't ready for this level. </p> <</if>> <</if>> </div> <!-- Calculate tips with severe penalty for terrible performance --> <<if _score < 30>> <<set _paymentMultiplier = 0.1>> <<else>> <<set _paymentMultiplier = Math.max(0.5, Math.min(2.0, _score / 50))>> <</if>> <<set _baseAmount = Math.floor((_basePay[0] + _basePay[1]) / 2)>> <<set _finalPay = Math.round(_baseAmount * _paymentMultiplier)>> <!-- ===== SKILL TREE: Apply stripper pay bonus ===== --> <<set _stripperPayBonus = setup.skillTree.getEffect("stripperPayBonus")>> <<set _skillTreePayBonus = 0>> <<if _stripperPayBonus > 0>> <<set _skillTreePayBonus = Math.floor(_finalPay * (_stripperPayBonus / 100))>> <<set _finalPay = _finalPay + _skillTreePayBonus>> <</if>> <!-- Pyrow +25% stripper pay on clear weather days --> <<if $physicalTraits.includes("Pyrow") && typeof setup.isPyrowBonusActive === "function" && setup.isPyrowBonusActive()>> <<set _finalPay = Math.floor(_finalPay * 1.25)>> <</if>> <!-- Honeybee +50% stripper pay with lustful buff --> <<if $physicalTraits.includes("Honeybee") && typeof setup.hasBuff === "function" && setup.hasBuff("honeybee_lustful")>> <<set _finalPay = Math.floor(_finalPay * 1.5)>> <</if>> <!-- Apply Pearl of Abundance bonus (+50%) --> <<set _pearlActive = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _preBonusPay = _finalPay>> <<set _pearlBonus = 0>> <<if _pearlActive>> <<set _pearlBonus = Math.round(_preBonusPay * 0.5)>> <<set _finalPay = _preBonusPay + _pearlBonus>> <</if>> <<set _finalPay = Math.round(_finalPay * setup.baskingCharmCashMult())>> <<if _firstResolve>> <<set $money += _finalPay>> <!-- Sexual XP Gain --> <<set _sexualExpGains = []>> <<if _score >= 85>> <<if !$sexualSkills>> <<run setup.initializeSexualSkills()>> <</if>> <!-- Calculate base XP --> <<set _baseXP = 5>> <!-- ===== SKILL TREE: Apply sex skill XP bonus ===== --> <<set _sexSkillXPBonus = setup.skillTree.getEffect("sexSkillXPBonus")>> <<set _baseXP = _baseXP + _sexSkillXPBonus>> <<set _finalXP = _baseXP>> <<run setup.addSexualSkillExp("teasing", _finalXP)>> <<run _sexualExpGains.push({skill: "Teasing", amount: _finalXP})>> <<run setup.addSexualSkillExp("sensual", _finalXP)>> <<run _sexualExpGains.push({skill: "Sensual", amount: _finalXP})>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff69b4; box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); animation: pulse-pink 2s infinite;"> <h3 style="color: #ff69b4; margin-top: 0; text-align: center;"> 💕 Sexual Expertise Increased! <<if $currentArtifact === "The Basking Charm">> <span style="color: #ff9800;">☀️ 3x Bonus!</span> <</if>> </h3> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 10px 0;"> <span style="color: #ff69b4; font-weight: bold;">Teasing</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> | <span style="color: #ff69b4; font-weight: bold;">Sensual</span> <span style="color: #51cf66;">+<<print _finalXP>> XP</span> </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <p style="color: #ccc; font-size: 14px; text-align: center; margin: 10px 0 0 0; font-style: italic;"> The Basking Charm amplifies every sensation, every lesson learned... </p> <</if>> </div> <style> @keyframes pulse-pink { 0%, 100% { box-shadow: 0 8px 16px rgba(255, 105, 180, 0.3); } 50% { box-shadow: 0 8px 24px rgba(255, 105, 180, 0.6); } } </style> <</if>> <!-- ===== SKILL TREE: Display pay bonus notification ===== --> <<if _skillTreePayBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #CE93D8; box-shadow: 0 0 20px rgba(156, 39, 176, 0.4);"> <p style="color: #E1BEE7; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ⭐ Skill Tree Bonus: +$<<print _skillTreePayBonus>> (+<<print _stripperPayBonus>>%) ⭐ </p> </div> <</if>> <!-- Pearl of Abundance Notification --> <<if _pearlActive>> <div style="background: linear-gradient(135deg, #7dd3fc 0%, #3b82f6 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); animation: pulse-pearl 2s infinite;"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> 🐚 The Pearl of Abundance has increased your earnings by 50%! 🐚 </p> </div> <style> @keyframes pulse-pearl { 0%, 100% { box-shadow: 0 0 20px rgba(125, 211, 252, 0.4); } 50% { box-shadow: 0 0 30px rgba(125, 211, 252, 0.7); } } </style> <</if>> <!-- Basking Charm Notification --> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>> <div style="background: linear-gradient(135deg, #ffb300 0%, #ff6f00 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 3px solid #ffb300; box-shadow: 0 0 20px rgba(255, 179, 0, 0.4);"> <p style="color: white; margin: 0; text-align: center; font-size: 16px; font-weight: bold;"> ☀️ The Basking Charm tripled your earnings! ☀️ </p> </div> <</if>> <!-- Earnings Display --> <div style="background: linear-gradient(135deg, #1a4d1a 0%, #0a2a0a 100%); border: 3px solid #4ade80; padding: 25px; border-radius: 15px; text-align: center; margin-bottom: 25px; box-shadow: 0 0 25px rgba(74, 222, 128, 0.3);"> <h2 style="color: #4ade80; margin: 0 0 15px 0; text-shadow: 0 0 15px rgba(74, 222, 128, 0.6);">💰 Tips Earned</h2> <div style="font-size: 42px; font-weight: bold; color: #FFD700; text-shadow: 0 0 20px rgba(255, 215, 0, 0.6);"> +$<<print _finalPay>> <<if _pearlActive>> <span style="color: #7dd3fc; font-size: 24px;">(+50%)</span> <</if>> </div> <<if _pearlActive>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Base tips: $<<print _basePay>> (score: <<print _score>>)<br> Pearl Bonus: <span style="color: #7dd3fc;">+$<<print _pearlBonus>></span> </p> <<else>> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Performance score: <<print _score>> (<<print Math.round(_paymentMultiplier * 100)>>% of base pay) </p> <</if>> </div> <!-- Update counters --> <<set $mingleSessionsToday += 1>> <<run advanceTime(_duration)>> <!-- Co-worker relationship bonus (30% chance per co-worker during mingle sessions) --> <<set _coworkerBonuses = []>> <<set _coworkers = setup.getNPCsByJob("Stripper")>> <<if _coworkers && _coworkers.length > 0>> <<for _i = 0; _i < _coworkers.length; _i++>> <<set _coworker = _coworkers[_i]>> <<set _coworkerName = _coworker.name>> <<if random(1, 100) <= 30>> <<set _relPoints = random(1, 4)>> <<run setup.meetNPC(_coworker)>> <<run setup.addRelationshipPoints(_coworkerName, _relPoints)>> <<run _coworkerBonuses.push({name: _coworkerName, points: _relPoints})>> <</if>> <</for>> <</if>> <<if _coworkerBonuses.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-top: 20px; border: 3px solid #9D00FF;"> <h3 style="color: #9D00FF; margin: 0 0 15px 0;">👥 Backstage Bonding</h3> <p style="color: #aaa; margin-bottom: 15px;">You chatted with other dancers between sets!</p> <<for _cwb range _coworkerBonuses>> <div style="background: #1a2a3a; padding: 12px 15px; border-radius: 8px; margin-bottom: 8px; border: 2px solid #51cf66; display: flex; justify-content: space-between; align-items: center;"> <span style="color: #ddd;">💚 <<print _cwb.name>></span> <span style="color: #51cf66; font-weight: bold;">+<<print _cwb.points>> points</span> </div> <</for>> </div> <</if>> <</if>> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(157, 0, 255, 0.5); border: 2px solid #9D00FF;'>Back to Floor</div>">> <<goto "StripClubMingleCustomers">> <</link>> </div> <</if>> </div> <</nobr>>
<<script>> if (typeof setup.getBrothelImage !== "function") { setup.getBrothelImage = function(serviceType, client, playerTraits, sessionChoices) { if (!serviceType || !client || !playerTraits) return null; var imagePath = "Images/Jobs/Brothel/"; var fileName = ""; /* Helper function to get primary personality */ var getPrimaryPersonality = function() { if (playerTraits.isDominant) return "Dominant"; if (playerTraits.isSubmissive) return "Submissive"; if (playerTraits.isFlirty) return "Flirty"; if (playerTraits.isAwkward) return "Awkward"; if (playerTraits.isKind) return "Kind"; if (playerTraits.isProfessional) return "Professional"; if (playerTraits.isConfident) return "Confident"; if (playerTraits.isBitchy) return "Bitchy"; if (playerTraits.isEnergetic) return "Energetic"; return null; }; var personality = getPrimaryPersonality(); var hasRough = sessionChoices && sessionChoices.includes("rough"); switch(serviceType) { case "oralGiving": if (client.hasPenis) { if (client.gender === "male") { /* Male client with penis */ if (personality === "Dominant") fileName = "OralGiving_Male_Dominant"; else if (personality === "Submissive") fileName = "OralGiving_Male_Submissive"; else if (personality === "Flirty") fileName = "OralGiving_Male_Flirty"; else if (personality === "Awkward") fileName = "OralGiving_Male_Awkward"; else if (personality === "Professional") fileName = "OralGiving_Male_Professional"; else fileName = "OralGiving_Male_Deepthroat"; } else { /* Female client with penis */ if (personality === "Dominant") fileName = "OralGiving_Female_Dominant"; else if (personality === "Submissive") fileName = "OralGiving_Female_Submissive"; else if (personality === "Flirty") fileName = "OralGiving_Female_Flirty"; else if (personality === "Kind") fileName = "OralGiving_Female_Kind"; else fileName = "OralGiving_Female_Submissive"; } } else if (client.hasVagina) { if (client.gender === "female") { /* Female client with pussy */ if (personality === "Dominant") fileName = "OralGiving_Pussy_Dominant"; else if (personality === "Submissive") fileName = "OralGiving_Pussy_Submissive"; else if (personality === "Flirty") fileName = "OralGiving_Pussy_Flirty"; else if (personality === "Kind") fileName = "OralGiving_Pussy_Kind"; else fileName = "OralGiving_Pussy_Submissive"; } else { /* Male client with pussy */ if (personality === "Kind") fileName = "OralGiving_MalePussy_Kind"; else if (personality === "Confident") fileName = "OralGiving_MalePussy_Confident"; else fileName = "OralGiving_MalePussy_Kind"; } } break; case "vaginal": if (client.gender === "male") { /* Male client fucking player */ if (personality === "Submissive") fileName = "Vaginal_Male_Submissive"; else if (personality === "Dominant") fileName = "Vaginal_Male_Dominant"; else if (personality === "Flirty") fileName = "Vaginal_Male_Flirty"; else if (personality === "Awkward") fileName = "Vaginal_Male_Awkward"; else if (hasRough) fileName = "Vaginal_Male_Rough"; else fileName = "Vaginal_Male_Submissive"; } else { /* Female client fucking player */ if (personality === "Dominant") fileName = "Vaginal_Female_Dominant_Riding"; else if (personality === "Submissive") fileName = "Vaginal_Female_Submissive"; else if (personality === "Flirty") fileName = "Vaginal_Female_Flirty"; else fileName = "Vaginal_Female_Submissive"; } break; case "anal": if (client.hasPenis) { if (client.gender === "male") { /* Male client fucking player's ass */ if (personality === "Submissive") fileName = "Anal_Male_Submission"; else if (hasRough) fileName = "Anal_Male_Rough"; else if (personality === "Dominant") fileName = "Anal_Male_Dominant"; else if (personality === "Awkward") fileName = "Anal_Male_Awkward"; else fileName = "Anal_Male_Submission"; } else { /* Female client with penis fucking player's ass */ if (personality === "Submissive") fileName = "Anal_Female_Submissive"; else fileName = "Anal_Female_Toys"; } } else { /* No penis - toys */ fileName = "Anal_Female_Toys"; } break; case "penisPlay": /* Player using their cock */ if (client.gender === "male") { if (personality === "Dominant") fileName = "PenisPlay_Male_Dominant"; else if (personality === "Kind") fileName = "PenisPlay_Male_Kind"; else fileName = "PenisPlay_Male_Dominant"; } else { if (personality === "Dominant") fileName = "PenisPlay_Female_Dominant"; else if (personality === "Confident") fileName = "PenisPlay_Female_Confident"; else if (personality === "Flirty") fileName = "PenisPlay_Female_Flirty"; else fileName = "PenisPlay_Female_Dominant"; } break; case "handjobs": if (client.hasPenis) { if (personality === "Professional") fileName = "Handjob_Male_Professional"; else if (personality === "Flirty") fileName = "Handjob_Male_Flirty"; else if (personality === "Dominant") fileName = "Handjob_Male_Dominant"; else fileName = "Handjob_Male_Professional"; } else { if (personality === "Kind") fileName = "Fingering_Pussy_Kind"; else if (personality === "Confident") fileName = "Fingering_Pussy_Confident"; else if (personality === "Dominant") fileName = "Fingering_Pussy_Dominant"; else if (personality === "Submissive") fileName = "Fingering_Pussy_Submissive"; else fileName = "Fingering_Pussy_Expert"; } break; case "titWorship": /* Determine chest size from playerTraits if available */ var chestSize = playerTraits.chestSize || ""; if (chestSize.includes("small")) { if (personality === "Dominant") fileName = "TitWorship_Small_Dominant"; else if (personality === "Submissive") fileName = "TitWorship_Small_Submissive"; else if (client.gender === "male") fileName = "TitWorship_Small_Male"; else fileName = "TitWorship_Small_Female"; } else if (chestSize.includes("medium")) { if (personality === "Dominant") fileName = "TitWorship_Medium_Dominant"; else if (personality === "Submissive") fileName = "TitWorship_Medium_Submissive"; else if (client.gender === "male") fileName = "TitWorship_Medium_Male"; else fileName = "TitWorship_Medium_Female"; } else if (chestSize.includes("large")) { if (personality === "Dominant") fileName = "TitWorship_Large_Dominant"; else if (client.gender === "male") fileName = "TitWorship_Large_Male"; else fileName = "TitWorship_Large_Female"; } else if (chestSize.includes("huge")) { if (client.gender === "male") fileName = "TitWorship_Huge_Male_Smothering"; else fileName = "TitWorship_Huge_Female"; } else if (chestSize.includes("giant")) { if (personality === "Dominant") fileName = "TitWorship_Giant_Dominant"; else fileName = "TitWorship_Giant_Male"; } else { /* Default */ fileName = "TitWorship_Medium_Male"; } break; case "titfuck": if (!client.hasPenis) { /* Redirect to tit worship if no penis */ return setup.getBrothelImage("titWorship", client, playerTraits, sessionChoices); } var titsSize = playerTraits.chestSize || ""; if (titsSize.includes("medium")) { if (personality === "Flirty") fileName = "Titfuck_Medium_Flirty"; else if (personality === "Submissive") fileName = "Titfuck_Medium_Submissive"; else fileName = "Titfuck_Medium_Standard"; } else if (titsSize.includes("large")) { if (personality === "Dominant") fileName = "Titfuck_Large_Dominant"; else fileName = "Titfuck_Large_Standard"; } else if (titsSize.includes("huge")) { if (personality === "Dominant") fileName = "Titfuck_Huge_Dominant"; else fileName = "Titfuck_Huge_Bouncing"; } else if (titsSize.includes("giant")) { if (personality === "Dominant") fileName = "Titfuck_Giant_Dominant"; else fileName = "Titfuck_Giant_Smothering"; } else if (titsSize.includes("gigantic")) { fileName = "Titfuck_Gigantic_Bouncing"; } else { fileName = "Titfuck_Medium_Standard"; } break; case "climax": /* Climax images based on what service was used */ var primaryService = sessionChoices ? sessionChoices[sessionChoices.length - 2] : null; if (primaryService === "oralGiving" && client.hasPenis) { if (personality === "Submissive") fileName = "Climax_Oral_Swallow_Submissive"; else if (personality === "Dominant") fileName = "Climax_Oral_Facial_Dominant"; else if (personality === "Flirty") fileName = "Climax_Oral_Facial_Flirty"; else fileName = "Climax_Oral_Messy"; } else if (primaryService === "vaginal") { if (sessionChoices.includes("strong_finish")) fileName = "Climax_Creampie_Dripping"; else if (personality === "Submissive") fileName = "Climax_Creampie_Submissive"; else fileName = "Climax_Creampie_Breeding"; } else if (primaryService === "anal") { fileName = "Climax_Anal_Dripping"; } else if (primaryService === "titfuck") { var tSize = playerTraits.chestSize || ""; if (tSize.includes("huge") || tSize.includes("giant")) fileName = "Titfuck_Cumshot_Huge"; else fileName = "Titfuck_Cumshot_Medium"; } else if (sessionChoices && sessionChoices.includes("multiple")) { fileName = "Climax_Multiple_Exhausted"; } else if (sessionChoices && sessionChoices.includes("simultaneous")) { if (personality === "Flirty") fileName = "Climax_Simultaneous_Intimate"; else fileName = "Climax_Simultaneous_Intense"; } else { fileName = "Climax_Body_Covered"; } break; default: return null; } return fileName ? imagePath + fileName + ".webp" : null; }; } <</script>>
<<nobr>> <<ghwd5h48jx6>> <<if _ohwd5h48jx6>><<goto "Debug">><</if>> <div style="background:#1a1a1a;min-height:100vh;padding:20px;display:flex;align-items:center;justify-content:center"> <div style="background:linear-gradient(135deg,#2d2d2d 0%,#1a1a1a 100%);padding:40px;border-radius:15px;border:3px solid #667eea;box-shadow:0 4px 8px rgba(0,0,0,0.4);max-width:500px;text-align:center"> <h1 style="color:#667eea;margin:0 0 20px 0">🔒 Cheat Menu Access</h1> <div style="background-color:#0a0a0a;padding:20px;border-radius:10px;margin-bottom:25px;border:2px solid #ffd43b"> <p style="color:#ffd43b;font-size:18px;font-weight:bold;margin:0">⭐ Patreon Tiers Spoon and up can access the cheat menu! ⭐</p> </div> <p style="color:#e0e0e0;margin-bottom:20px;font-size:16px">Enter the password to continue:</p> <div style="margin-bottom:20px"> <input id="i_ze6sek0771" type="text" autofocus style="width:80%;padding:10px;border-radius:6px;border:2px solid #667eea;background:#2d2d2d;color:#e0e0e0;font-size:16px;text-align:center" /> </div> <<if _lhwd5h48jx6>><span style="color:#ff6b6b;font-size:14px;margin-bottom:15px">🔒 Too many failed attempts. Reload the page to try again.</span><<elseif $z_btj0q3jk>><span style="color:#ff6b6b;font-size:14px;margin-bottom:15px">❌ Incorrect password. Please try again.</span><<unset $z_btj0q3jk>><</if>> <<script>> (function () { var BTN = "b_uplqb1lgdy"; var INP = "i_ze6sek0771"; var NS = ".gu_" + "hwd5h48jx6"; $(document).off("click" + NS).on("click" + NS, "#" + BTN, function () { var el = document.getElementById(INP); var val = el ? el.value : ""; if (!val) return; try { document.getElementById(BTN).textContent = "Unlocking..."; } catch (e) {} setup["k_hwd5h48jx6"](val).then(function () { Engine.play("Debug"); }).catch(function () { State.variables["z_btj0q3jk"] = true; Engine.play("CheatMenuPassword"); }); }); $(document).off("keydown" + NS).on("keydown" + NS, "#" + INP, function (e) { if (e.key === "Enter") { $("#" + BTN).click(); } }); })(); <</script>> <div id="b_uplqb1lgdy" style="background:linear-gradient(135deg,#51cf66 0%,#40c057 100%);color:white;padding:12px 30px;border-radius:8px;text-align:center;cursor:pointer;font-weight:bold;box-shadow:0 2px 4px rgba(0,0,0,0.3);display:inline-block;margin-top:10px">Unlock</div> <div style="margin-top:30px"> <<link "<div style='background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);color:white;padding:10px 20px;border-radius:6px;text-align:center;cursor:pointer;font-weight:bold;box-shadow:0 2px 4px rgba(0,0,0,0.3);display:inline-block'>← Back</div>">><<goto $lastLocation>><</link>> </div> </div></div> <</nobr>>
<<silently>> <!-- Placeholder init passage --> <</silently>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Beach")>> <<run $visitedLocations.push("Beach")>> <!-- Check for main locations achievement (bronze) --> <<set _mainLocations = ["Downtown", "BusinessDistrict", "RedLightDistrict", "Docks", "Alleyway", "Outskirts"]>> <<set _visitedMainCount = 0>> <<for _loc range _mainLocations>> <<if $visitedLocations.includes(_loc)>> <<set _visitedMainCount++>> <</if>> <</for>> <<if _visitedMainCount >= 6>> <<run setup.achievements.unlock("visit_main_locations")>> <</if>> <</if>> <!-- Initialize swimming minutes first --> <<if !$swimmingMinutesToday>><<set $swimmingMinutesToday = 0>><</if>> <<set $lastLocation = "Beach">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #f4a460; text-align: center;">🏖️ Beach</h1> <!-- Location Image (Day/Night Cycle) --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <<set _timeOfDay = getTimeOfDay()>> <<if _timeOfDay === "morning">> <<set _locationImg = "Images/Locations/Beach.webp">> <<elseif _timeOfDay === "afternoon">> <<set _locationImg = "Images/Locations/BeachDay.webp">> <<else>> <<set _locationImg = "Images/Locations/BeachNight.webp">> <</if>> <div style="text-align: center; margin: 20px 0;"> <img @src="_locationImg" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #f4a460; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Beach"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #87ceeb 0%, #f4a460 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f4a460;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Warm sand stretches beneath your feet as ocean waves crash rhythmically against the shore. Seagulls cry overhead, and the scent of salt water mingles with sunscreen and beach food. Sunbathers dot the coastline, some seeking relaxation, others seeking attention. </p> </div> <h2 style="color: #f4a460;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Swimming --> <<set _canSwim = $swimmingMinutesToday < 180>> <<set _minutesRemaining = 180 - $swimmingMinutesToday>> <div style="border: 3px solid #4fc3f7; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4fc3f7; margin: 0 0 10px 0;">🏊 Swimming Area</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take a refreshing swim in the ocean.</p> <<if _canSwim>> <p style="font-size: 12px; color: #4fc3f7; margin: 5px 0; text-align: center;">Time left today: _minutesRemaining minutes</p> <<link "<div style='background: #4fc3f7; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Swimming (60 min)</div>">> <<advancetime 60>> <<set $swimmingMinutesToday += 60>> <!-- Swimming removes shower buffs and messes hair --> <<run setup.removeBuff("shower_fresh")>> <<run setup.removeBuff("bath_relaxed")>> <<run setup.removeBuff("bath_luxury")>> <<run setup.setHairMessy()>> <!-- Swimming skill progression (Siren transformation includes Swimming) --> <<if !$beachSwimCount>><<set $beachSwimCount = 0>><</if>> <<set _hasSwimmingSkill = ($skills && ($skills.includes("Swimming") || $skills.includes("Swimmer"))) || ($physicalTraits && $physicalTraits.includes("Siren"))>> <<if !_hasSwimmingSkill>> <<set $beachSwimCount++>> <<if $beachSwimCount >= 25>> <!-- Grant one of the swimming skills randomly --> <<set _swimmingSkills = ["Swimming", "Swimmer"]>> <<set _grantedSkill = _swimmingSkills.random()>> <<run $skills.push(_grantedSkill)>> <<set $beachSwimCount = 0>> <<set $swimSkillLearned = _grantedSkill>> <</if>> <</if>> <<goto "BeachSwimming">> <</link>> <<else>> <p style="font-size: 12px; color: #ff6b6b; margin: 5px 0; text-align: center;">You've swum enough for today (180/180 minutes)</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px; cursor: not-allowed;'>Too Tired to Swim</div> <</if>> </div> <!-- Walk Along the Beach --> <div style="border: 3px solid #90caf9; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #90caf9; margin: 0 0 10px 0;">🚶 Walk Along the Beach</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take a stroll along the shoreline.</p> <<link "<div style='background: #90caf9; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Take a Walk</div>">> <<goto "BeachWalk">> <</link>> </div> <!-- Beach Fishing --> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">🎣 Beach Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Fish from the sandy shores.</p> <<link "<div style='background: #f4a460; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Fishing</div>">> <<set $fishingLocation = "beach">> <<goto "FishingBeach">> <</link>> </div> <!-- Coral Reef (Only shows if unlocked) --><<if $coralReefUnlocked>> <div style="border: 3px solid #00bcd4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #00bcd4; margin: 0 0 10px 0;">🐠 Coral Reef</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Visit the vibrant underwater ecosystem.</p> <<link "<div style='background: #00bcd4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Coral Reef</div>">> <<goto "CoralReef">> <</link>> </div><</if>> <!-- Quesha's Dive Shop (post-intro only) --><<if $queshaIntroComplete>> <div style="border: 3px solid #4dd0e1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4dd0e1; margin: 0 0 10px 0;">🤿 Quesha's Dive Shop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Wet suits on pegs and a wall map of dive sites. Open most days.</p> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit</div>">> <<advancetime 5>> <<goto "QueshaDiveShop">> <</link>> </div><</if>> <!-- Beach Dive Workbench (post-intro) --><<if $queshaIntroComplete>> <div style="border: 3px solid #00bfa5; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #00bfa5; margin: 0 0 10px 0;">🛠 Dive Workbench</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A weathered workbench by Quesha's shop. Materials in jars, a vise, and a pair of files. Build your own dive gear.</p> <<link "<div style='background: linear-gradient(135deg, #00bfa5 0%, #00695c 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit</div>">> <<advancetime 5>> <<goto "BeachDiveWorkbench">> <</link>> </div><</if>> <!-- Sunfish Shrine (post-discovery only) --><<if $shrineFound && !setup.diving.QUESTLINES_DISABLED>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🌅 Sunfish Shrine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A pilgrimage to the shrine you found together. Quiet. Useful.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit</div>">> <<advancetime 60>> <<goto "SunfishShrine">> <</link>> </div><</if>> </div> <h2 style="color: #f4a460;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to the Bus Stop</div>">> <<bustravel>> <<goto "BusStop">> <</link>> </div> <!-- Docks --> <div style="border: 3px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the industrial waterfront.</p> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to the Docks</div>">> <<travel>> <<goto "Docks">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Beach")>> <h2 style="color: #f4a460;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f4a460; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<link "<div style='background: #f4a460; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The beach is peaceful today. Just the sound of waves and seagulls. </p> </div> <</if>> <!-- Hidden Side Path to Roisin's Beach House (visible only when possessing her or after first walking it) --> <<if $possessionActive || $discoveredRoisinPath>> <div style="display: grid; grid-template-columns: 1fr; gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #2a1a3e; box-shadow: 0 0 18px rgba(201,169,255,0.25);"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🌿 Hidden Side Path</h3> <<if !$discoveredRoisinPath>> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 12px 0; line-height: 1.5; font-style: italic;">A narrow break in the dunes, almost invisible from the main beach. You only know it because Roisin's body knows the way.</p> <<else>> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 12px 0; line-height: 1.5; font-style: italic;">The narrow path you remember. Leads a mile up the coast to a hidden beach house tucked behind the dunes.</p> <</if>> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6e4ea8 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Take the side path (15 min)</div>">> <<run advanceTime(15)>> <<set $discoveredRoisinPath = true>> <<goto "RoisinBeachHouse">> <</link>> </div> </div> <</if>> <!-- Vending Machine --> <div style="border: 3px solid #00b894; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #55efc4; margin: 0 0 10px 0;">🍫 Vending Machine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Grab a quick snack or drink.</p> <<link "<div style='background: #00b894; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Machine</div>">> <<goto "VendingMachineShop">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<advancetime 60>> <!-- Initialize tracking variables if they don't exist --> <<if !$beachWalkEventsToday>><<set $beachWalkEventsToday = []>><</if>> <<if !$beachWalkEventsEver>><<set $beachWalkEventsEver = []>><</if>> <!-- Reset daily events at day change --> <<if !$lastBeachWalkDay || $lastBeachWalkDay != $dayNumber>> <<set $beachWalkEventsToday = []>> <<set $lastBeachWalkDay = $dayNumber>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #90caf9; text-align: center;">🚶 Walking Along the Beach</h1> <div style="padding: 20px; background: linear-gradient(135deg, #87ceeb 0%, #90caf9 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #90caf9;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You stroll along the beach, feeling the warm sand between your toes and breathing in the salty ocean air... </p> </div> <!-- Event Roll --> <<set _eventRoll = random(1, 100)>> <<set _eventHappened = false>> <!-- Check if player has City Mayor job for increased chance --> <<set _isMayor = $jobs && $jobs.includes("City Mayor")>> <<set _sunfishRockChance = _isMayor ? 20 : 1>> <!-- Check pit chance - 3% first time, 15% after experiencing it once --> <<set _pitChance = $hasExperiencedRealityPit ? 15 : 3>> <!-- Event 1: Sunfish Rock (1/100 chance normally, 20/100 if City Mayor, once ever) --> <<if _eventRoll <= _sunfishRockChance && !$beachWalkEventsToday.includes("sunfishRock") && !$beachWalkEventsEver.includes("sunfishRock")>> <<set _eventHappened = true>> <<set $beachWalkEventsToday.push("sunfishRock")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">Something Strange...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> As you walk along the beach, you notice a suspicious figure following you from a distance. The silhouette looks oddly... lumpy? Like multiple sunfish stacked in a trench coat, waddling awkwardly across the sand. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You quickly turn to get a better look, but when you do, there's nothing there except a small, sunfish-shaped rock half-buried in the sand. It gleams with an unusual iridescence in the sunlight. </p> <p style="color: #aaa; margin: 0 0 20px 0; font-style: italic;"> Something about this rock feels... significant. Do you touch it? </p> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='background: #ff6b6b; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Touch the Rock</div>">> <<set $beachWalkEventsEver.push("sunfishRock")>> <<set $artifactEntryMethod = "rock">> <<goto "Sunfish Tank">> <</link>> <<link "<div style='background: #666; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave It Alone</div>">> <<goto "Beach">> <</link>> </div> </div> <!-- Event 2: Reality Pit (3/100 chance first time, 15/100 after experiencing it) --> <<elseif _eventRoll <= _pitChance && !$beachWalkEventsToday.includes("realityPit")>> <<set _eventHappened = true>> <<set $beachWalkEventsToday.push("realityPit")>> <<set $hasExperiencedRealityPit = true>> <<run setup.achievements.unlock("beach_hole")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(156,39,176,0.3);"> <h3 style="color: #9c27b0; margin: 0 0 15px 0;">The World Shifts...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You take a step forward and suddenly the sand beneath your feet gives way. But this isn't a normal sinkhole—the sand doesn't fall, it <em>warps</em>. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Reality bends and twists around you like water swirling down a drain. The beach, the ocean, the sky—everything spirals inward as you sink through layers of existence itself. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Colors you've never seen before flash past your eyes. You hear whispers in languages that shouldn't exist. Time becomes meaningless. </p> <p style="color: #9c27b0; margin: 0 0 20px 0; font-weight: bold; text-align: center; font-size: 18px;"> And then... you land. </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9c27b0 0%, #7b1fa2 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(156,39,176,0.3); font-size: 16px;'>Continue...</div>">> <<set $artifactEntryMethod = "pit">> <<goto "ArtifactRoom">> <</link>> </div> </div> <!-- Event 3: Coral Reef Discovery (20/100 chance, once ever) --> <<elseif _eventRoll <= 20 && !$coralReefUnlocked && !$beachWalkEventsEver.includes("coralReefDiscovery")>> <<set _eventHappened = true>> <<set $beachWalkEventsToday.push("coralReefDiscovery")>> <<set $beachWalkEventsEver.push("coralReefDiscovery")>> <<set $coralReefUnlocked = true>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(0,188,212,0.3);"> <h3 style="color: #00bcd4; margin: 0 0 15px 0;">A Hidden Wonder</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> As you walk along the shoreline, you notice something unusual in the water. Just beyond where the waves break, you catch glimpses of vibrant colors beneath the surface—blues, purples, oranges, and greens dancing in the sunlight. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Curious, you wade in a bit deeper to get a better look. Your breath catches as you realize what you're seeing: a magnificent coral reef, teeming with life! Schools of tropical fish dart between the coral formations, and you can see anemones swaying gently in the current. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> How had you never noticed this before? The reef is shallow enough to explore, tucked away in a sheltered cove that's easy to miss unless you know where to look. </p> <p style="color: #00bcd4; margin: 0 0 20px 0; font-weight: bold; text-align: center; font-size: 18px;"> You've discovered the Coral Reef! You can now visit it from the beach. </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #00bcd4 0%, #0097a7 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(0,188,212,0.3); font-size: 16px;'>Return to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> <!-- No Event or Already Pulled Today --> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #90caf9; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0;"> Nothing eventful happens during your walk. You enjoy the peaceful scenery and the rhythmic sound of the waves. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #f4a460; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #f4a460; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Beach</div>">> <<goto "Beach">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("SunfishTank")>> <<run $visitedLocations.push("SunfishTank")>> <</if>> <!-- Check for drown achievement (player without Sunfish skill) --> <<if !$skills || !$skills.includes("Sunfish")>> <<run setup.achievements.unlock("drown_in_tank")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4dd0e1; text-align: center;">🐟 Sunfish Tank</h1> <!-- Check if player has Sunfish skill --> <<if $skills && $skills.includes("Sunfish")>> <!-- SUNFISH SKILL VERSION --> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #4dd0e1 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dd0e1;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The moment you touch the rock, reality warps around you. You find yourself submerged in crystal-clear water, surrounded by massive sunfish drifting lazily through the blue. </p> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You're in a tank. An aquarium. But something feels... different. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dd0e1; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You catch your reflection in the glass wall of the tank. The face staring back at you isn't human anymore. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Large, round eyes. A massive, flat body. Tiny fins that seem too small for your bulk. You've become a sunfish - a real one, swimming among your kind in this impossible place. </p> <p style="color: #4dd0e1; margin: 0 0 15px 0; font-weight: bold;"> Strangely, you can breathe perfectly fine. The water feels natural, comfortable even. This is where you belong now... isn't it? </p> <p style="color: #aaa; margin: 0; font-style: italic;"> What do you do? </p> </div> <!-- Options --> <div style="display: flex; flex-direction: column; gap: 15px; margin-bottom: 25px;"> <<link "<div style='background: #4dd0e1; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>🌊 Swim Around</div>">> <<goto "SunfishTankSwim">> <</link>> </div> <<else>> <!-- DEFAULT VERSION (NO SUNFISH SKILL) --> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #4dd0e1 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dd0e1;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The moment you touch the rock, reality warps around you. </p> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You find yourself submerged in water, surrounded by massive sunfish drifting lazily through the blue void. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You're in a tank. An aquarium. The glass walls stretch impossibly high above and around you. Panic sets in as you realize the horrible truth. </p> <p style="color: #ff6b6b; margin: 0 0 15px 0; line-height: 1.6; font-weight: bold;"> You can't breathe. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Your lungs burn. You thrash desperately, trying to reach the surface, but there is no surface. The sunfish continue their peaceful drift, unbothered by your struggle. Water fills your mouth, your nose. Darkness creeps in at the edges of your vision. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Through the haze of suffocation, you see it - a figure standing just outside the glass. That same suspicious silhouette. Multiple sunfish stacked in a trench coat, standing impossibly upright. It stares directly at you with too many eyes. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> The figure doesn't move. Doesn't help. Just... watches. </p> <p style="color: #666; margin: 0; line-height: 1.6; font-style: italic;"> Everything goes black. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4caf50; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You wake up gasping on the beach, coughing up seawater. The sun beats down on your back. Sand clings to your wet clothes. </p> <p style="color: #ccc; margin: 0; line-height: 1.6;"> The sunfish-shaped rock is nowhere to be seen. Was it all real? The lingering taste of salt water suggests it was. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #f4a460; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #f4a460; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Get Up and Return to Beach</div>">> <<goto "Beach">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("CoralReef")>> <<run $visitedLocations.push("CoralReef")>> <</if>> <<set $lastLocation = "CoralReef">> <!-- Fish Bucket Blackout: if fish vanished overnight while at reef --> <<if $fishBucketBlackoutPending>> <<set $fishBucketBlackoutPending = false>> <<goto "FishBucketBlackout">> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #00bcd4; text-align: center;">🐠 Coral Reef</h1> <!-- Location Image (Day/Night Cycle) --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <<set _timeOfDay = getTimeOfDay()>> <<if _timeOfDay === "morning">> <<set _locationImg = "Images/Locations/CoralReef.webp">> <<elseif _timeOfDay === "afternoon">> <<set _locationImg = "Images/Locations/CoralReefDay.webp">> <<else>> <<set _locationImg = "Images/Locations/CoralReefNight.webp">> <</if>> <div style="text-align: center; margin: 20px 0;"> <img @src="_locationImg" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="CoralReef"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #00bcd4 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00bcd4;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Crystal clear waters reveal a vibrant underwater world. Colorful coral formations create a maze of life, while schools of tropical fish dart between the branches. The gentle current sways sea anemones, and the occasional sea turtle glides past. </p> </div> <h2 style="color: #00bcd4;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Swimming --> <div style="border: 3px solid #4fc3f7; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #4fc3f7; margin: 0 0 10px 0;">🏊 Explore the Reef</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Swim through the coral formations.</p> <<link "<div style='background: #4fc3f7; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Swimming</div>">> <<advancetime 60>> <!-- Swimming removes shower buffs and messes hair --> <<run setup.removeBuff("shower_fresh")>> <<run setup.removeBuff("bath_relaxed")>> <<run setup.removeBuff("bath_luxury")>> <<run setup.setHairMessy()>> <!-- Check for cave discovery (Siren transformation includes Swimming) --> <<set _caveRoll = random(1, 100)>> <<set _hasSunfish = $skills && $skills.includes("Sunfish")>> <<set _hasSwimmingSkill = ($skills && ($skills.includes("Swimmer") || $skills.includes("Swimming"))) || ($physicalTraits && $physicalTraits.includes("Siren"))>> <<set _caveChance = 0>> <<if _hasSunfish>> <<set _caveChance = 50>> <<set $UnderWaterCaveEntryMethod = "sunfish">> <<elseif _hasSwimmingSkill>> <<set _caveChance = 5>> <<set $UnderWaterCaveEntryMethod = "swimmer">> <</if>> <<if (_hasSunfish || _hasSwimmingSkill) && _caveRoll <= _caveChance && !$foundUnderWaterCave>> <<set $foundUnderWaterCave = true>> <<goto "UnderWaterCaveDiscovery">> <<else>> <<goto "CoralReef">> <</if>> <</link>> </div> <!-- Sunfish Cuff: Dive Deeper (only if Cuff Band held + amulet not yet found + swim trait) --> <<run setup.sunfishCuff.ensureState()>> <<set _cuffSwim = ($skills && ($skills.includes("Swimmer") || $skills.includes("Swimming"))) || ($physicalTraits && ($physicalTraits.includes("Siren") || $physicalTraits.includes("Naiad")))>> <<if $cuffPieces && $cuffPieces.band && !$cuffPieces.amulet && _cuffSwim>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(201,169,255,0.2); display: flex; flex-direction: column;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🌊 Dive Deeper</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Something at the bottom is patient. The Cuff Band hums softly when you swim past the deep edge of the reef.</p> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #4fc3f7 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Dive (60 min)</div>">> <<advancetime 60>> <<run setup.removeBuff("shower_fresh")>> <<run setup.removeBuff("bath_relaxed")>> <<run setup.removeBuff("bath_luxury")>> <<run setup.setHairMessy()>> <<goto "CoralReefDiveDeeper">> <</link>> </div> <</if>> <!-- Fishing --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🎣 Go Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Cast your line among the colorful coral formations.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Fishing</div>">> <<goto "FishingCoralReef">> <</link>> </div> <!-- Giant Chicken Fish Bucket / Bell --> <<if !setup.oni.isPlayerInOwnBody()>> <div style="border: 3px solid #6a6a6a; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #1a1a1a 0%, #0a0a0a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.7;"> <h3 style="color: #999; margin: 0 0 10px 0;">🔔 Golden Bell</h3> <p style="font-size: 14px; color: #888; margin: 0; line-height: 1.4;">The golden bell sits quiet. It will not answer a borrowed body. The bird would never know you like this.</p> </div> <<elseif $giantChickenUnlocked>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a2a1a 0%, #1a1a0a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255, 215, 0, 0.3); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🔔 Golden Bell</h3> <p style="font-size: 14px; color: #d4c47a; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A shimmering golden bell sits where the bucket once was. You know what happens when you ring it.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #ff9800 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 10px rgba(255, 215, 0, 0.4);'>🔔 Ring the Bell</div>">> <<goto "GiantChickenRide">> <</link>> </div> <<else>> <div style="border: 3px solid #ff9800; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff9800; margin: 0 0 10px 0;">🪣 Mysterious Bucket</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 5px 0; line-height: 1.4; flex-grow: 1;">A large, weathered bucket sits at the edge of the reef. Something about it feels... expectant.</p> <div style="background: #1a1a1a; border-radius: 8px; padding: 10px; margin: 10px 0; text-align: center;"> <div style="color: #ff9800; font-size: 24px; font-weight: bold;"><<print $fishBucketCount>> / 100</div> </div> <<if $fishInventory && $fishInventory.length > 0>> <p style="font-size: 13px; color: #aaa; text-align: center; margin: 5px 0;">You have <strong style="color: #2ecc71;"><<print $fishInventory.length>></strong> fish in your inventory.</p> <<link "<div style='background: linear-gradient(135deg, #ff9800 0%, #ff5722 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>🐟 Dump All Fish Into Bucket</div>">> <<set $fishBucketCount += $fishInventory.length>> <<set $fishInventory = []>> <<if $fishBucketCount >= 100>> <<goto "GiantChickenRide">> <<else>> <<goto "CoralReef">> <</if>> <</link>> <<else>> <div style="background: #333; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;">No fish in inventory</div> <</if>> </div> <</if>> </div> <h2 style="color: #00bcd4;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Beach --> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">🏖️ Beach</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the sandy shore.</p> <<link "<div style='background: #f4a460; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Beach</div>">> <<goto "Beach">> <</link>> </div> <!-- Underwater Cave (shows after discovery) --> <<if $foundUnderWaterCave>> <div style="border: 3px solid #00acc1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #00acc1; margin: 0 0 10px 0;">🌊 Underwater Cave</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Swim to the hidden cave entrance.</p> <<link "<div style='background: #00acc1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Cave</div>">> <<set $UnderWaterCaveEntryMethod = $skills && $skills.includes("Sunfish") ? "sunfish" : "swimmer">> <<goto "UnderWaterCave">> <</link>> </div> <</if>> <!-- ===== SKILL TREE: Secret Entrance ===== --> <<if setup.skillTree.getEffect("secretEntrance")>> <div style="border: 3px solid #FFD700; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a2a1a 0%, #1a1a0a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255, 215, 0, 0.3); display: flex; flex-direction: column;"> <h3 style="color: #FFD700; margin: 0 0 10px 0;">🐚 Suspicious Sand</h3> <p style="font-size: 14px; color: #d4c47a; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A patch of sand on the ocean floor that seems to shimmer differently than the rest...</p> <<link "<div style='background: linear-gradient(135deg, #FFD700 0%, #FFA500 100%); color: #000; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 10px rgba(255, 215, 0, 0.4);'>Investigate</div>">> <<goto "ArtifactRoom">> <</link>> </div> <</if>> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("CoralReef")>> <h2 style="color: #00bcd4;">🐠 People at the Reef</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(0, 188, 212, 0.2);"> <p style="color: #4fc3f7; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic;"> You spot other people enjoying the reef's beauty... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #00bcd4; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(0, 188, 212, 0.15);"> <h3 style="color: #00bcd4; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #4fc3f7; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #00bcd4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 10px rgba(0, 188, 212, 0.3);'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The reef is serene and empty. Just you and the colorful marine life. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("SunfishTankSwim")>> <<run $visitedLocations.push("SunfishTankSwim")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4dd0e1; text-align: center;">🐟 Swimming in the Tank</h1> <!-- Roll for trench coat encounter --> <<set _encounterRoll = random(1, 10)>> <<if _encounterRoll <= 3 && !$sawTrenchCoatSunfish>> <!-- Saw the trench coat person! --> <<set $sawTrenchCoatSunfish = true>> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #4dd0e1 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dd0e1;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You glide through the water with your fellow sunfish, your tiny fins propelling you in lazy circles... </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">A Familiar Presence</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Something catches your eye through the glass. You turn your bulbous sunfish body to look. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> There it is - that figure. Multiple sunfish stacked in a trench coat, standing just beyond the tank wall. It's staring directly at you with too many round, unblinking eyes. This close, you can see the trench coat is soaking wet, dripping onto the floor. </p> <p style="color: #ff6b6b; margin: 0; line-height: 1.6; font-style: italic;"> The moment you notice it watching, it quickly shuffles out of view and disappears. </p> </div> <<else>> <!-- Normal swimming --> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #4dd0e1 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dd0e1;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You glide through the water with your fellow sunfish, your tiny fins propelling you in lazy circles. The other sunfish pay you no mind - you're one of them now. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dd0e1; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0;"> The water is peaceful, almost meditative. You could get used to this life. </p> </div> <</if>> <!-- Discovery of the tunnel --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0;">Something Strange...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> As you swim near the bottom of the tank, you notice something odd. There's a tunnel - a dark passage leading somewhere else. The other sunfish seem to avoid it. </p> <p style="color: #aaa; margin: 0; font-style: italic;"> Do you enter the tunnel? </p> </div> <div style="display: flex; flex-direction: column; gap: 15px; margin-bottom: 25px;"> <<link "<div style='background: #ffc107; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Enter the Tunnel</div>">> <<goto "SunfishTankTunnel">> <</link>> <<link "<div style='background: #666; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Keep Swimming Around</div>">> <<goto "SunfishTankSwim">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("UnderwaterCave")>> <<run $visitedLocations.push("UnderwaterCave")>> <<run setup.achievements.unlock("underwater_cave")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #00bcd4; text-align: center;">🌊 Underwater Cave</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/UnderwaterCave.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Underwater Cave"> </div> <</if>> <<if $UnderWaterCaveEntryMethod === "sunfish">> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #00bcd4 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00bcd4;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You swim upward through the sloping passage. The water grows lighter, brighter. You can see the surface above! </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> With a powerful thrust of your tiny fins, you break through the surface and into open air. You gasp, expecting to suffocate again, but instead you can breathe. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You look down at yourself. Your sunfish body is transforming, shifting back to human form. Within moments, you're treading water as yourself again, in an underwater cave with a small air pocket. </p> <p style="color: #4caf50; margin: 0; line-height: 1.6; font-weight: bold;"> You're human once more. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #00bcd4 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00bcd4;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You dive deeper into the reef, your swimming skills guiding you through the coral maze. A dark opening catches your eye—a hidden cave entrance. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You swim through the narrow passage, your lungs starting to burn. Just when you think you'll need to turn back, you spot light above—an air pocket! </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You break the surface, gasping for air. You've discovered a hidden underwater cave with a small chamber of breathable air. The walls glisten with moisture and bioluminescent algae cast an eerie blue glow. </p> <p style="color: #4caf50; margin: 0; line-height: 1.6; font-weight: bold;"> A secret sanctuary beneath the waves. </p> </div> <</if>> <!-- Secret Sunfish Wall --> <<set _hasSunfishTrait = ($skills && $skills.includes("Sunfish")) || ($physicalTraits && $physicalTraits.includes("Sunfish")) || ($mentalTraits && $mentalTraits.includes("Sunfish"))>> <<set _hasAnyArtifact = ($currentArtifact || $activeTransformation === "Naiad") ? true : false>> <<set _hasForeignLanguage = $skills && $skills.includes("Foreign Language")>> <<set _canOpenPassage = _hasSunfishTrait && _hasAnyArtifact>> <div style="background: #1a2a3a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4), inset 0 0 30px rgba(0,188,212,0.1);"> <h3 style="color: #00bcd4; margin: 0 0 15px 0; text-align: center;">🐟 Strange Wall Carving</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> As your eyes adjust to the bioluminescent glow, you notice something peculiar on the far wall of the cave. Carved into the ancient stone is the unmistakable silhouette of a <span style="color: #ffc107; font-weight: bold;">sunfish</span>—its distinctive round body and tall fins etched with incredible detail. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Embedded in the center of the carving is a <span style="color: #7c4dff; font-weight: bold;">glowing orb</span> that pulses with an ethereal purple light. The glow seems to respond to your presence, brightening slightly as you approach. </p> <!-- Cryptic Message - only readable with Foreign Language --> <div style="background: #0d1a26; padding: 15px; border-radius: 8px; margin: 15px 0; border: 1px solid #00bcd4;"> <<if _hasForeignLanguage>> <p style="color: #4fc3f7; margin: 0 0 10px 0; font-style: italic; text-align: center; font-size: 14px;"> Ancient text is inscribed beneath the carving. Your knowledge of foreign languages allows you to decipher it: </p> <p style="color: #ffc107; margin: 0; text-align: center; font-family: serif; font-size: 16px; line-height: 1.8;"> <em>"When the child of the ocean sun<br> Bears a gift from depths below,<br> Touch the light and be as one—<br> The hidden path shall then bestow."</em> </p> <<else>> <p style="color: #666; margin: 0; text-align: center; font-style: italic;"> Strange symbols are inscribed beneath the carving. The writing is in an ancient language you cannot read. </p> <</if>> </div> <!-- Interaction with the wall --> <<if _canOpenPassage>> <div style="background: linear-gradient(135deg, #4a148c 0%, #7c4dff 100%); padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #b388ff;"> <p style="color: #e1bee7; margin: 0 0 10px 0; text-align: center;"> The orb pulses more intensely as you approach. You feel a strange resonance—your sunfish essence and the artifact you carry seem to <span style="color: #ffc107; font-weight: bold;">harmonize</span> with the ancient magic here. </p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7c4dff 0%, #b388ff 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #b388ff; box-shadow: 0 0 20px rgba(124,77,255,0.5);'>✨ Touch the Glowing Orb</div>">> <<goto "SunfishSecretPassage">> <</link>> </div> <<elseif _hasSunfishTrait && !_hasAnyArtifact>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #ff9800;"> <p style="color: #ffb74d; margin: 0; text-align: center;"> You feel a faint connection to the sunfish carving, but something is missing. The orb flickers weakly, as if waiting for something more... </p> </div> <<elseif _hasAnyArtifact && !_hasSunfishTrait>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #ff9800;"> <p style="color: #ffb74d; margin: 0; text-align: center;"> Your artifact hums with energy near the wall, but the orb does not respond to you. Perhaps you lack the proper connection to this place... </p> </div> <<else>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #666;"> <p style="color: #888; margin: 0; text-align: center;"> The orb remains dim and unresponsive. Whatever magic lies here, it does not recognize you. </p> </div> <</if>> </div> <!-- Activities Section --> <h2 style="color: #7c4dff; margin-top: 25px;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Fishing --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🎣 Go Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Fish in the bioluminescent waters of the cave.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Fishing</div>">> <<goto "FishingUnderwaterCave">> <</link>> </div> <!-- Witch Coven --> <<if $xantriaCovenUnlocked>> <div style="border: 3px solid #8b00ff; border-radius: 10px; padding: 15px; background: #1a0033; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(139,0,255,0.3); display: flex; flex-direction: column;"> <h3 style="color: #CE93D8; margin: 0 0 10px 0;">🔮 Xantria's Coven</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A hidden chamber pulsing with arcane energy. Xantria has made it her home.</p> <<link "<div style='background: linear-gradient(135deg, #8b00ff 0%, #4a0080 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; border: 1px solid #CE93D8;'>Enter the Coven</div>">> <<goto "WitchCoven">> <</link>> </div> <</if>> </div> <!-- Tide Hollow Mine entrance --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4080a0; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #80c0e0; margin: 0 0 10px 0;">🌊 Tide Hollow</h3> <p style="color: #b8d8e8; margin: 0 0 12px 0; font-size: 14px;">A flooded shaft pierces the cave wall, descending into salt-darkness. Pearls and aquamarine glitter on the deeper levels — but the tide can rise without warning.</p> <<link "<div style='background: linear-gradient(135deg, #4080a0 0%, #103040 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; border: 1px solid #80c0e0;'>Descend into Tide Hollow</div>">> <<run advanceTime(10)>> <<goto "TideHollowEntrance">> <</link>> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4caf50; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0;"> A current pulls you gently toward another passage that leads back to open water. You could let it carry you back to the beach. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #f4a460; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #f4a460; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("SunfishSecretPassage")>> <<run $visitedLocations.push("SunfishSecretPassage")>> <</if>> <!-- Count met NPCs with relationships --> <<set _metNPCCount = 0>> <<if $metNPCs && $relationships>> <<for _npcName range $metNPCs>> <<if $relationships[_npcName]>> <<set _metNPCCount += 1>> <</if>> <</for>> <</if>> <<set _hasSoulTrait = ($skills && $skills.includes("Soul")) || ($physicalTraits && $physicalTraits.includes("Soul")) || ($mentalTraits && $mentalTraits.includes("Soul"))>> <<set _canObtainSoul = _metNPCCount >= 20 && !_hasSoulTrait>> <div style="background: #0a0a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #b388ff; text-align: center;">✨ The Hidden Sanctuary</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2e 0%, #4a148c 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7c4dff; box-shadow: 0 0 30px rgba(124,77,255,0.3);"> <p style="color: #e1bee7; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> As your fingers touch the glowing orb, reality shifts around you. The wall dissolves into a shimmering veil of light, revealing a passage that shouldn't exist. </p> </div> <div style="background: #1a1a2e; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #7c4dff; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You step through into a vast underground chamber that defies natural law. Crystalline formations jut from the walls, ceiling, and floor, each one glowing with soft, pulsing light in shades of purple, blue, and gold. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> The air here is thick with ancient power. You feel your artifact resonate with the energy of this place, and your sunfish essence stirs within you, recognizing something primal and familiar. </p> <p style="color: #b388ff; margin: 0; line-height: 1.6; font-weight: bold;"> You have discovered a place lost to time—a sanctuary of the sunfish... </p> </div> <!-- The Vision Orb --> <div style="background: linear-gradient(135deg, #0d0d2b 0%, #1a0a3a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e040fb; box-shadow: 0 0 40px rgba(224,64,251,0.3);"> <h3 style="color: #e040fb; margin: 0 0 15px 0; text-align: center;">🔮 The Vision Orb</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> At the center of the chamber floats a massive crystalline orb, pulsing with inner light. As you approach, images begin to swirl within its depths—faces, familiar faces... </p> <<if _metNPCCount > 0>> <div style="background: rgba(0,0,0,0.5); padding: 15px; border-radius: 8px; margin: 15px 0; border: 1px solid #e040fb;"> <p style="color: #ce93d8; margin: 0 0 10px 0; text-align: center; font-style: italic;"> The orb flashes through visions of people you've encountered in Sunfish City... </p> <p style="color: #ffc107; margin: 0; text-align: center; font-weight: bold;"> _metNPCCount souls recognized by the orb </p> </div> <<else>> <div style="background: rgba(0,0,0,0.5); padding: 15px; border-radius: 8px; margin: 15px 0; border: 1px solid #666;"> <p style="color: #888; margin: 0; text-align: center; font-style: italic;"> The orb remains dark and still. You have not yet formed enough connections in this city... </p> </div> <</if>> <<if _hasSoulTrait>> <!-- Already has Soul trait --> <div style="background: linear-gradient(135deg, #1b5e20 0%, #2e7d32 100%); padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #4caf50;"> <p style="color: #a5d6a7; margin: 0; text-align: center;"> ✨ The orb recognizes you. Your <span style="color: #ffc107; font-weight: bold;">Soul</span> trait pulses in harmony with its light. </p> </div> <<elseif _canObtainSoul>> <!-- Can obtain Soul trait --> <div style="background: linear-gradient(135deg, #b71c1c 0%, #c62828 100%); padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #ef5350;"> <p style="color: #ffcdd2; margin: 0 0 15px 0; text-align: center;"> The orb pulses intensely. It has seen enough of your connections to this world. It offers you something... a piece of yourself made manifest. </p> <p style="color: #ffc107; margin: 0; text-align: center; font-weight: bold;"> "Take hold of your essence. Become whole." </p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #e040fb; box-shadow: 0 0 20px rgba(224,64,251,0.5);'>🌟 Grasp Your Soul</div>">> <<if !$mentalTraits>><<set $mentalTraits = []>><</if>> <<run $mentalTraits.push("Soul")>> <<goto "SoulTraitAcquired">> <</link>> </div> <<else>> <!-- Not enough NPCs met --> <div style="background: rgba(0,0,0,0.5); padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #ff9800;"> <p style="color: #ffb74d; margin: 0; text-align: center;"> The orb flickers weakly. Your connections to this world are still forming... You sense you must know at least <span style="color: #ffc107; font-weight: bold;">20 souls</span> before the orb will respond to you. </p> <p style="color: #888; margin: 10px 0 0 0; text-align: center; font-size: 14px;"> (You have met _metNPCCount / 20 required NPCs) </p> </div> <</if>> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #00bcd4 0%, #006064 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #00bcd4; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to the Cave</div>">> <<goto "UnderWaterCave">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #0a0a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e040fb; text-align: center;">✨ Soul Awakened</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a148c 0%, #7c4dff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e040fb; box-shadow: 0 0 50px rgba(224,64,251,0.5);"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); text-align: center;"> You reach into the orb and grasp... yourself. A piece of your very essence, crystallized and made tangible. </p> </div> <div style="background: #1a1a2e; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e040fb; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> The sensation is indescribable. You feel <em>complete</em> in a way you never knew you were incomplete. A warmth spreads through your chest as the essence merges with your being. </p> <p style="color: #e040fb; margin: 0; line-height: 1.6; font-weight: bold; text-align: center; font-size: 20px;"> You have acquired the "Soul" trait! </p> </div> <!-- Spoiler Section --> <div style="background: #1a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; text-align: center;">❓ What does the Soul trait do?</h3> <p style="color: #aaa; margin: 0 0 15px 0; text-align: center; font-style: italic;"> Click below to reveal the secrets of the Soul... </p> <div id="soul-spoiler-container" style="text-align: center;"> <<link "<div style='display: inline-block; background: #333; color: #ffc107; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #ffc107;'>🔓 Reveal Soul Mechanics</div>">> <<replace "#soul-spoiler-container">> <div style="background: #0d0d0d; padding: 20px; border-radius: 8px; border: 2px solid #ffc107; text-align: left;"> <h4 style="color: #ffc107; margin: 0 0 15px 0;">🌟 The Power of the Soul</h4> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.8;"> The Soul trait allows you to <span style="color: #e040fb; font-weight: bold;">permanently swap lives</span> with another person through the trading system. When trading with an NPC, a hidden option will appear allowing you to offer your Soul. </p> <h4 style="color: #ff9800; margin: 0 0 10px 0;">⚠️ Requirements to Swap Lives:</h4> <ul style="color: #ccc; margin: 0 0 15px 0; line-height: 2;"> <li>You must have <span style="color: #4caf50; font-weight: bold;">at least one stat at 50 or higher</span> (naturally, without bonuses)</li> <li>You must <span style="color: #f44336; font-weight: bold;">NOT</span> have: Unskilled, Unlucky, or Gambling Addiction</li> <li>You must have the <span style="color: #ffc107; font-weight: bold;">Sunfish trait</span> (it will be consumed in the swap)</li> <li>The NPC must not be <span style="color: #9c27b0; font-weight: bold;">protected from life swapping</span></li> </ul> <p style="color: #ff6b6b; margin: 0; font-weight: bold;"> Warning: This is a permanent decision. Choose wisely who you become. </p> </div> <</replace>> <</link>> </div> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #00bcd4 0%, #006064 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #00bcd4; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to the Sanctuary</div>">> <<goto "SunfishSecretPassage">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $soulSwapTarget>> <<if !_npc>> <<goto "Downtown">> <<elseif $possessionActive === true && $lifeSwapPortraitSource === "Roisin Sullivan">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 3px solid #ff6b6b; text-align: center;"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0;">Soul Exchange Unavailable</h2> <p style="color: #ccc; font-size: 16px;">You cannot perform a soul exchange while possessing Roisin through the Sunfish Cuff.</p> <p style="color: #888; font-size: 14px;">Return to your own body first.</p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px;'>← Go Back</div>">> <<unset $soulSwapTarget>> <<goto "Downtown">> <</link>> </div> </div> <<else>> <<set _npcName = _npc.originalName || _npc.name>> <div style="background: #0a0a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e040fb; text-align: center;">🔮 Soul Exchange</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a148c 0%, #7c4dff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e040fb; box-shadow: 0 0 50px rgba(224,64,251,0.5);"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); text-align: center;"> You prepare to offer your very Soul to <strong><<= _npcName>></strong>... </p> </div> <div style="background: #1a1a2e; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff9800; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff9800; margin: 0 0 15px 0; text-align: center;">⚠️ Final Warning</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.8; text-align: center;"> This action is <span style="color: #f44336; font-weight: bold;">PERMANENT and IRREVERSIBLE</span>. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> If you proceed: </p> <ul style="color: #ccc; margin: 0 0 15px 0; line-height: 2;"> <li>Your <span style="color: #e040fb; font-weight: bold;">Soul trait</span> will remain with you</li> <li>Your <span style="color: #ffc107; font-weight: bold;">Sunfish trait</span> will be sacrificed</li> <li>You will permanently become <span style="color: #4caf50; font-weight: bold;"><<= _npcName>></span></li> <li>You will gain <span style="color: #4caf50; font-weight: bold;">all of their traits</span> in addition to keeping Soul</li> <li>Your old identity will be gone forever</li> </ul> <p style="color: #ff6b6b; margin: 0; font-weight: bold; text-align: center;"> There is no going back. </p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 25px;"> <<link "<div style='background: linear-gradient(135deg, #f44336 0%, #c62828 100%); color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 0 30px rgba(244,67,54,0.5); border: 2px solid #ef5350;'>🔮 Offer My Soul</div>">> /* Soul swap: Player KEEPS Soul trait after swapping */ /* Only Sunfish trait is consumed */ /* Remove Sunfish trait from wherever it exists */ <<if $skills && $skills.includes("Sunfish")>> <<run $skills.delete("Sunfish")>> <</if>> <<if $physicalTraits && $physicalTraits.includes("Sunfish")>> <<run $physicalTraits.delete("Sunfish")>> <</if>> <<if $mentalTraits && $mentalTraits.includes("Sunfish")>> <<run $mentalTraits.delete("Sunfish")>> <</if>> /* Store old player info for transformation passage */ <<set $lifeSwapOldPlayerName = $playerFirstName + " " + $playerLastName>> <<set $lifeSwapOldPlayerTraits = { physicalTraits: JSON.parse(JSON.stringify($physicalTraits)), mentalTraits: JSON.parse(JSON.stringify($mentalTraits)), skills: JSON.parse(JSON.stringify($skills)), bodyParts: JSON.parse(JSON.stringify($bodyParts)), stats: JSON.parse(JSON.stringify($stats)) }>> <<set $lifeSwapNPCOldName = _npcName>> <<set $lifeSwapNPCOldTraits = { physicalTraits: JSON.parse(JSON.stringify(_npc.physicalTraits || [])), mentalTraits: JSON.parse(JSON.stringify(_npc.mentalTraits || [])), skills: JSON.parse(JSON.stringify(_npc.skills || [])), bodyParts: JSON.parse(JSON.stringify(_npc.bodyParts)), stats: JSON.parse(JSON.stringify(_npc.stats)) }>> <<run setup.performLifeSwap(_npc)>> <<goto "LifeSwapTransformation">> <</link>> <<link "<div style='background: #666; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Cancel</div>">> <<unset $soulSwapTarget>> <<goto "Downtown">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ChamberOfArtifacts")>> <<run $visitedLocations.push("ChamberOfArtifacts")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffc107; text-align: center;">✨ Chamber of Artifacts</h1> <<if $artifactEntryMethod === "pit">> <div style="padding: 20px; background: linear-gradient(135deg, #9c27b0 0%, #7b1fa2 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9c27b0; box-shadow: 0 0 20px rgba(156,39,176,0.3);"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You land softly on smooth stone, the warping sensation fading away like waking from a dream. The air here feels thick with power. </p> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Looking around, you find yourself in a chamber that shouldn't exist—a secret place torn from reality itself. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #f57f17 0%, #ffc107 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffc107;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You swim upward into the golden passage. The tunnel seems to shift and twist around you, reality bending in impossible ways. </p> </div> <</if>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You emerge into a circular chamber. The water here glows with an otherworldly light. Arranged around the room are seven pedestals, each holding a glowing artifact of incredible beauty and power. </p> <p style="color: #ffc107; margin: 0; line-height: 1.6; font-weight: bold;"> The artifacts pulse with energy, calling to you... </p> </div> <!-- Check if player has Sunfish skill --> <<if !$skills || !$skills.includes("Sunfish")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #dc3545; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #dc3545; margin: 0; text-align: center; font-weight: bold; font-size: 18px;"> The artifacts do not respond to you. You lack the connection needed to claim them. </p> <p style="color: #aaa; margin: 15px 0 0 0; text-align: center; font-style: italic;"> Only those who carry the essence of the sunfish may take from this place. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #666; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Empty-Handed</div>">> <<goto "Beach">> <</link>> </div> <<else>> <!-- Player has Sunfish skill - show artifacts --> <<if $currentArtifact>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4caf50; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #4caf50; margin: 0 0 15px 0; text-align: center;">You Already Possess an Artifact</h3> <p style="color: #ccc; margin: 0 0 15px 0; text-align: center; line-height: 1.6;"> Current Artifact: <strong style="color: #ffc107;">$currentArtifact</strong> </p> <p style="color: #aaa; margin: 0; text-align: center; font-style: italic;"> You may exchange it for another, but doing so will once again consume your sunfish essence. </p> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #4dabf7; margin: 0; text-align: center; font-weight: bold; font-size: 16px;"> Choose wisely. Taking an artifact will consume your sunfish essence. </p> </div> <</if>> <h2 style="color: #ffc107; text-align: center;">The Seven Artifacts</h2> <div style="display: grid; grid-template-columns: 1fr; gap: 20px; margin-bottom: 25px; max-width: 800px; margin-left: auto; margin-right: auto;"> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Sunfish Hook")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Sunfish Hook --> <div style="border: 3px solid #9c27b0; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9c27b0; margin: 0 0 10px 0;">🪝 The Sunfish Hook</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> A barbed hook carved from sunfish bone, warm to the touch. The sea gives up its treasures more willingly when it is cast. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "What the sunfish blesses, the deep cannot keep. Even a lost catch finds its way back to the bone hook." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Pulls up far more treasure, and sometimes lands an epic catch you would have lost </p> <<if $currentArtifact === "The Sunfish Hook">> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #9c27b0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Sunfish Hook">> <<set $artifactStealthBonus = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Gentle Giant's Heart")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Gentle Giant's Heart --> <div style="border: 3px solid #e91e63; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💖 The Gentle Giant's Heart</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> A smooth, rounded stone that radiates warmth and calm. It pulses gently like a beating heart. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "Despite their size, sunfish are harmless and curious. Your presence brings the same peaceful comfort." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Others find themselves drawn to you, bonds forming much faster than normal </p> <<if ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #e91e63; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Gentle Giant's Heart">> <<set $artifactRelationshipBonus = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Basking Charm")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Basking Charm --> <div style="border: 3px solid #ff9800; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff9800; margin: 0 0 10px 0;">☀️ The Basking Charm</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> A sun-warmed pendant shaped like a surfacing sunfish. It feels pleasantly warm against your skin. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "Sunfish bask openly in the warmth. Embrace exposure without shame." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Your body learns the arts of pleasure with supernatural speed, and your sensual work earns far richer rewards </p> <<if ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #ff9800; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Basking Charm">> <<set $artifactSexSkillBonus = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Drifter's Coin")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Drifter's Coin --> <div style="border: 3px solid #00bcd4; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #00bcd4; margin: 0 0 10px 0;">🪙 The Drifter's Coin</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> An ancient coin with a sunfish on one side and swirling ocean currents on the other. It never stays still in your hand. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "Go with the flow. Drift toward mutual benefit." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Negotiations always seem to go in your favor </p> <<if ($currentArtifact === "The Drifter's Coin" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #00bcd4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Drifter's Coin">> <<set $artifactTradingBonus = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Pearl of Abundance")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Pearl of Abundance --> <div style="border: 3px solid #f5f5f5; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #f5f5f5; margin: 0 0 10px 0;">🔮 The Pearl of Abundance</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> A massive pearl supposedly from a sunfish's belly. It glows with inner light and feels heavy with potential. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "What the sunfish consumes becomes treasure. Wealth follows naturally." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Every effort yields greater rewards, prosperity flowing like the tide </p> <<if ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #f5f5f5; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Pearl of Abundance">> <<set $artifactMoneyBonus = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Crowd's Eye")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Crowd's Eye --> <div style="border: 3px solid #673ab7; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #673ab7; margin: 0 0 10px 0;">👁️ The Crowd's Eye</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> A preserved sunfish eye that never stops looking. Its gaze is magnetic, drawing attention wherever you go. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "All eyes turn to witness the sunfish. All eyes will turn to you." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Eyes turn to you, drawn by an irresistible magnetism </p> <<if ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #673ab7; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Crowd's Eye">> <<set $artifactPopularityBonus = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> <<if $oasisAltarConsumed && $oasisAltarConsumed.includes("The Tidal Memory Stone")>> <div style="border: 3px solid #444; border-radius: 10px; padding: 20px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.5;"> <h3 style="color: #666; margin: 0 0 10px 0;">Empty Pedestal</h3> <p style="color: #555; margin: 0; line-height: 1.6; font-style: italic;">This artifact has been placed upon the oasis altar. The pedestal stands empty.</p> </div> <<else>> <!-- The Tidal Memory Stone --> <div style="border: 3px solid #4dabf7; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">🌊 The Tidal Memory Stone</h3> <p style="color: #ccc; margin: 0 0 10px 0; line-height: 1.6;"> A stone that pulses with the rhythm of ocean currents. Images of places flicker across its surface. </p> <p style="color: #aaa; margin: 0 0 15px 0; font-style: italic; font-size: 14px;"> "Sunfish traverse all oceans, remembering every current. Return to where the tides once carried you." </p> <p style="color: #4caf50; margin: 0 0 15px 0; font-weight: bold;"> Effect: Attune a location by using the stone there, then teleport between every place you have attuned </p> <<if $currentArtifact === "The Tidal Memory Stone">> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Currently Possessed</div> <<else>> <<link "<div style='background: #4dabf7; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Claim This Artifact</div>">> <<set $currentArtifact = "The Tidal Memory Stone">> <<set $artifactTeleportation = true>> <<set $skills.delete("Sunfish")>> <<goto "ArtifactClaimed">> <</link>> <</if>> </div> <</if>> </div> <!-- Leave Without Taking --> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #666; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Leave Without Claiming</div>">> <<goto "Beach">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("SunfishTankTunnel")>> <<run $visitedLocations.push("SunfishTankTunnel")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4dd0e1; text-align: center;">🌑 The Tunnel</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a1a 0%, #006064 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dd0e1;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> You swim into the darkness. The tunnel twists and turns, growing narrower. Just when you think it might close completely, it opens into a chamber. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dd0e1; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> The chamber splits into multiple passages. Each one beckons with a different quality of light: </p> <p style="color: #4dabf7; margin: 0 0 10px 0; line-height: 1.6;"> ← A passage on the left pulses with ancient blue-green light </p> <p style="color: #00bcd4; margin: 0 0 10px 0; line-height: 1.6;"> → A passage on the right slopes upward into brightness </p> <<if $sawTrenchCoatSunfish>> <p style="color: #ffc107; margin: 0; line-height: 1.6;"> ↑ A third passage above emanates a strange golden glow </p> <</if>> </div> <div style="display: flex; flex-direction: column; gap: 15px; margin-bottom: 25px;"> <<link "<div style='background: #4dabf7; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Swim Left</div>">> <<set $comingFromSunfishTank = true>> <<goto "TheAlter">> <</link>> <<link "<div style='background: #00bcd4; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>→ Swim Right</div>">> <<goto "UnderWaterCave">> <</link>> <<if $sawTrenchCoatSunfish>> <<link "<div style='background: #ffc107; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>↑ Swim Upward</div>">> <<goto "ArtifactRoom">> <</link>> <</if>> <<link "<div style='background: #666; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Turn Back</div>">> <<goto "SunfishTankSwim">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track artifacts obtained --> <<if !$artifactsObtained>><<set $artifactsObtained = []>><</if>> <<if !$artifactsObtained.includes($currentArtifact)>> <<run $artifactsObtained.push($currentArtifact)>> <</if>> <!-- Check for first artifact achievement --> <<if $artifactsObtained.length === 1>> <<run setup.achievements.unlock("first_artifact")>> <</if>> <!-- Check for all artifacts obtained achievement --> <<set _allArtifacts = ["The Sunfish Hook", "The Gentle Giant's Heart", "The Basking Charm", "The Drifter's Coin", "The Pearl of Abundance", "The Crowd's Eye", "The Tidal Memory Stone"]>> <<set _hasAllArtifacts = true>> <<for _i = 0; _i < _allArtifacts.length; _i++>> <<if !$artifactsObtained.includes(_allArtifacts[_i])>> <<set _hasAllArtifacts = false>> <</if>> <</for>> <<if _hasAllArtifacts>> <<run setup.achievements.unlock("all_artifacts")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffc107; text-align: center;">✨ Artifact Claimed</h1> <div style="padding: 20px; background: linear-gradient(135deg, #f57f17 0%, #ffc107 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffc107;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> As your hand closes around the artifact, you feel the sunfish essence drain from your body. The connection that allowed you to access this place flows out of you and into the artifact, consumed as the price of its power. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 8px 16px rgba(255, 193, 7, 0.4);"> <h3 style="color: #ffc107; margin: 0 0 15px 0; text-align: center;">You Have Claimed: $currentArtifact</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6; text-align: center;"> The artifact pulses with life in your hands, now awakened by the essence you sacrificed. Its power flows into you like a warm current, imbuing you with its gift—permanent, undeniable, and yours to command. </p> <p style="color: #4caf50; margin: 0; line-height: 1.6; text-align: center; font-style: italic;"> You feel different. Changed. The artifact's blessing now courses through you. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4caf50; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0;"> A current pulls you gently through a hidden passage. Before you know it, you're washed up on the beach, the artifact clutched in your hand and its power humming within you. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #f4a460; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #f4a460; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Stand Up and Return to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* ======================================== ARTIFACTS INITIALIZATION ======================================== */ /* Initialize current artifact variable */ <<if !$currentArtifact>> <<set $currentArtifact = null>> <</if>> /* Setup artifact data */ <<if !setup.artifacts>> <<set setup.artifacts = { "The Sunfish Hook": { name: "The Sunfish Hook", icon: "🪝", color: "#9c27b0", description: "A barbed hook carved from sunfish bone, warm to the touch. The sea gives up its treasures more willingly when it is cast.", lore: "What the sunfish blesses, the deep cannot keep. Even a lost catch finds its way back to the bone hook.", effect: "Lands far more treasure when fishing, and can rescue a lost epic catch" }, "The Gentle Giant's Heart": { name: "The Gentle Giant's Heart", icon: "💖", color: "#e91e63", description: "A smooth, rounded stone that radiates warmth and calm. It pulses gently like a beating heart.", lore: "Despite their size, sunfish are harmless and curious. Your presence brings the same peaceful comfort.", effect: "Multiplies relationship and romance point gains by 8x with all NPCs" }, "The Basking Charm": { name: "The Basking Charm", icon: "☀️", color: "#ff9800", description: "A sun-warmed pendant shaped like a surfacing sunfish. It feels pleasantly warm against your skin.", lore: "Sunfish bask openly in the warmth. Embrace exposure without shame.", effect: "Quadruples sex skill XP gain, and triples money from prostitution, brothel, and stripper work" }, "The Drifter's Coin": { name: "The Drifter's Coin", icon: "🪙", color: "#00bcd4", description: "An ancient coin with a sunfish on one side and swirling ocean currents on the other. It never stays still in your hand.", lore: "Go with the flow. Drift toward mutual benefit.", effect: "Double all trade bonuses" }, "The Pearl of Abundance": { name: "The Pearl of Abundance", icon: "🔮", color: "#f5f5f5", description: "A massive pearl supposedly from a sunfish's belly. It glows with inner light and feels heavy with potential.", lore: "What the sunfish consumes becomes treasure. Wealth follows naturally.", effect: "Earn 50% more money from hourly jobs and gambling" }, "The Crowd's Eye": { name: "The Crowd's Eye", icon: "👁️", color: "#673ab7", description: "A preserved sunfish eye that never stops looking. Its gaze is magnetic, drawing attention wherever you go.", lore: "All eyes turn to witness the sunfish. All eyes will turn to you.", effect: "Gain fame/popularity 3x faster" }, "The Tidal Memory Stone": { name: "The Tidal Memory Stone", icon: "🌊", color: "#4dabf7", description: "A stone that pulses with the rhythm of ocean currents. Images of places flicker across its surface.", lore: "Sunfish traverse all oceans, remembering every current. Return to where the tides once carried you.", effect: "Teleport between locations you have attuned by using the stone there" } }>> <</if>> <</nobr>>
<<nobr>> <<if !$tidalUnlockedLocations>><<set $tidalUnlockedLocations = []>><</if>> <<if previous() && previous() !== "Teleport">><<set $tidalCameFrom = previous()>><</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4dabf7; text-align: center;">🌀 Tidal Memory Stone</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4dabf7 0%, #3b82f6 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dabf7; box-shadow: 0 0 20px rgba(77, 171, 247, 0.4);"> <p style="color: white; font-size: 16px; margin: 0; text-align: center;"> The stone only remembers places you have attuned it to. Stand at a location and attune it here to weave it into your teleport network. </p> </div> <<if setup.tidal.isLocation($tidalCameFrom)>> <<set _here = $tidalCameFrom>> <div style="background: #20283a; border: 2px solid #4dabf7; border-radius: 12px; padding: 18px; margin-bottom: 25px; text-align: center;"> <<if $tidalUnlockedLocations.includes(_here)>> <p style="color: #51cf66; margin: 0; font-weight: bold;">✓ <<= setup.tidal.emoji(_here)>> <<= setup.tidal.label(_here)>> is already attuned.</p> <<else>> <p style="color: #ccc; margin: 0 0 12px 0;">You are standing at <strong style="color: #4dabf7;"><<= setup.tidal.emoji(_here)>> <<= setup.tidal.label(_here)>></strong>.</p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4dabf7 0%, #3b82f6 100%); color: white; padding: 12px 28px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 15px rgba(77,171,247,0.5);'>🌀 Attune This Location</div>">> <<run $tidalUnlockedLocations.push(_here)>> <<goto "Teleport">> <</link>> <</if>> </div> <<else>> <div style="background: #20283a; border: 2px solid #555; border-radius: 12px; padding: 15px; margin-bottom: 25px; text-align: center;"> <p style="color: #888; margin: 0;">Open the stone while standing at a location to attune it.</p> </div> <</if>> <h2 style="color: #4dabf7;">Attuned Locations <span style="font-size: 13px; color: #888; font-weight: normal;">(<<= $tidalUnlockedLocations.length>>)</span></h2> <<if $tidalUnlockedLocations.length === 0>> <p style="color: #888; margin-top: 10px;">No locations attuned yet. Travel the island and use the stone at each place you want to remember.</p> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <<for _i, _dest range $tidalUnlockedLocations>> <<capture _dest>> <<set _cardStyle = "border: 3px solid " + setup.tidal.color(_dest) + "; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);">> <<set _h3Style = "color: " + setup.tidal.color(_dest) + "; margin: 0; flex: 1; min-width: 0;">> <<set _btnHtml = "<div style='background: " + setup.tidal.color(_dest) + "; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Teleport</div>">> <div @style="_cardStyle"> <div style="display: flex; align-items: center; justify-content: space-between; gap: 8px;"> <h3 @style="_h3Style"><<= setup.tidal.emoji(_dest)>> <<= setup.tidal.label(_dest)>></h3> <<link "<span style='font-size: 18px; cursor: pointer; color: #e74c3c; flex-shrink: 0;' title='Forget this location'>✕</span>">> <<set $tidalUnlockedLocations = $tidalUnlockedLocations.filter(function(d){ return d !== _dest; })>> <<goto "Teleport">> <</link>> </div> <<link _btnHtml>> <<set $money = ($money || 0) + 7>> <<goto _dest>> <</link>> </div> <</capture>> <</for>> </div> <</if>> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #00bcd4; text-align: center;">🌊 A Hidden Discovery</h1> <<if $UnderWaterCaveEntryMethod === "sunfish">> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #00bcd4 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00bcd4;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Swimming through the reef, your sunfish instincts guide you toward something... a dark opening hidden among the coral. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Your small sunfish body slips easily through the cave entrance. The passage slopes upward, and you can sense an air pocket above. </p> <p style="color: #00bcd4; margin: 0; line-height: 1.6; font-weight: bold;"> You've discovered an underwater cave! You can now access it from the Coral Reef. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #006064 0%, #00bcd4 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00bcd4;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Your trained swimming skills allow you to explore deeper into the reef. You spot a dark opening—a cave entrance hidden in the coral. </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Curious, you swim closer and peer inside. The passage looks navigable, sloping upward toward what might be an air pocket. </p> <p style="color: #00bcd4; margin: 0; line-height: 1.6; font-weight: bold;"> You've discovered an underwater cave! You can now access it from the Coral Reef. </p> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #00bcd4; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold; border: 2px solid #00bcd4; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Return to Coral Reef</div>">> <<goto "CoralReef">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _totalValue = $altarSacrificeValue>> <!-- Store old values for transformation text --> <<set _oldChest = $bodyParts.chest>> <<set _oldButt = $bodyParts.butt>> <!-- Remove sacrificed traits --> <<for _i = 0; _i < $altarSelectedTraits.length; _i++>> <<set _trait = $altarSelectedTraits[_i]>> <<if _trait.type === "physical">> <<run $physicalTraits.delete(_trait.name)>> <<elseif _trait.type === "mental">> <!-- Bimbo: deactivate FIRST so the player's pre-Bimbo traits and body are restored before we drop the Bimbo trait itself. Otherwise the player keeps the bimbo overlay traits and loses their originals. --> <<if _trait.name === "Bimbo" && typeof setup.deactivateBimboTrait === "function">> <<run setup.deactivateBimboTrait(State.variables)>> <</if>> <<run $mentalTraits.delete(_trait.name)>> <<elseif _trait.type === "skill">> <<run $skills.delete(_trait.name)>> <</if>> <</for>> <!-- Determine reward tier and what to grant --> <<set _rewardType = "">> <<set _rewardName = "">> <<if _totalValue >= 999>> <<if $skills && $skills.includes("Sunfish")>> <<set _rewardType = "money">> <<set _rewardName = "$100,000">> <<set $money += 100000>> <<else>> <<set _rewardType = "sunfish">> <<run $skills.push("Sunfish")>> <</if>> <<elseif _totalValue >= 800>> <<set _hasWere = $skills && $skills.includes("Were-Creature")>> <<set _hasDefVamp = $physicalTraits && $physicalTraits.includes("Definitely not a Vampire")>> <<set _hasTotVamp = $physicalTraits && $physicalTraits.includes("Totally not a Vampire")>> <<set _hasLucky = $mentalTraits && $mentalTraits.includes("Lucky")>> <!-- Check if traits are blocked by transformation --> <<set _luckyBlockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation("Lucky", "mental")>> <<set _wereBlockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation("Were-Creature", "physical")>> <<set _defVampBlockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation("Definitely not a Vampire", "physical")>> <<set _totVampBlockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation("Totally not a Vampire", "physical")>> <<if (_hasWere || _wereBlockedByTransform) && (_hasDefVamp || _defVampBlockedByTransform) && (_hasTotVamp || _totVampBlockedByTransform) && (_hasLucky || _luckyBlockedByTransform)>> <<set _rewardType = "money">> <<set _rewardName = "$50,000">> <<set $money += 50000>> <<else>> <<set _options = []>> <<if !_hasWere && !_wereBlockedByTransform>><<set _options.push("were")>><</if>> <<if !_hasDefVamp && !_defVampBlockedByTransform>><<set _options.push("defvamp")>><</if>> <<if !_hasTotVamp && !_totVampBlockedByTransform>><<set _options.push("totvamp")>><</if>> <<if !_hasLucky && !_luckyBlockedByTransform>><<set _options.push("lucky")>><</if>> <<set _choice = _options.random()>> <<if _choice === "were">> <<set _rewardType = "were">> <<run $skills.push("Were-Creature")>> <<elseif _choice === "defvamp">> <<set _rewardType = "defvamp">> <<run $physicalTraits.push("Definitely not a Vampire")>> <<elseif _choice === "totvamp">> <<set _rewardType = "totvamp">> <<run $physicalTraits.push("Totally not a Vampire")>> <<else>> <<set _rewardType = "lucky">> <<run $mentalTraits.push("Lucky")>> <</if>> <</if>> <<elseif _totalValue >= 500>> <<if $bodyParts.chest === "gigantic" && $bodyParts.butt === "gigantic">> <<set _rewardType = "money">> <<set _rewardName = "$25,000">> <<set $money += 25000>> <<else>> <<set _options = []>> <<if $bodyParts.chest !== "gigantic">><<set _options.push("gigchest")>><</if>> <<if $bodyParts.butt !== "gigantic">><<set _options.push("gigbutt")>><</if>> <<set _choice = _options.random()>> <<if _choice === "gigchest">> <<set _rewardType = "gigchest">> <<set $bodyParts.chest = "gigantic">> <<else>> <<set _rewardType = "gigbutt">> <<set $bodyParts.butt = "gigantic">> <</if>> <</if>> <<elseif _totalValue >= 300>> <<set _hasGiantChest = ($bodyParts.chest === "gigantic" || $bodyParts.chest === "giant")>> <<set _hasGiantButt = ($bodyParts.butt === "gigantic" || $bodyParts.butt === "giant")>> <<set _hasBimbo = $mentalTraits && $mentalTraits.includes("Bimbo")>> <<set _hasOccult = $skills && $skills.includes("Occult Expert")>> /* Bimbo cannot be granted on top of an existing transformation. */ <<set _bimboBlockedByTransform = ($witchFormActive === true) || (setup.hasActiveTransformation && setup.hasActiveTransformation())>> <<if _hasGiantChest && _hasGiantButt && (_hasBimbo || _bimboBlockedByTransform) && _hasOccult>> <<set _rewardType = "money">> <<set _rewardName = "$10,000">> <<set $money += 10000>> <<else>> <<set _options = []>> <<if !_hasGiantChest>><<set _options.push("giantchest")>><</if>> <<if !_hasGiantButt>><<set _options.push("giantbutt")>><</if>> <<if !_hasBimbo && !_bimboBlockedByTransform>><<set _options.push("bimbo")>><</if>> <<if !_hasOccult>><<set _options.push("occult")>><</if>> <<set _choice = _options.random()>> <<if _choice === "giantchest">> <<set _rewardType = "giantchest">> <<set $bodyParts.chest = "giant">> <<elseif _choice === "giantbutt">> <<set _rewardType = "giantbutt">> <<set $bodyParts.butt = "giant">> <<elseif _choice === "bimbo">> <<set _rewardType = "bimbo">> <<run $mentalTraits.push("Bimbo")>> <!-- Only the Bimbo mental trait is gained, no physical changes to body parts --> <<else>> <<set _rewardType = "occult">> <<run $skills.push("Occult Expert")>> <</if>> <</if>> <<elseif _totalValue >= 100>> <<set _hasHugeChest = ($bodyParts.chest === "gigantic" || $bodyParts.chest === "giant" || $bodyParts.chest === "huge")>> <<set _hasHugeButt = ($bodyParts.butt === "gigantic" || $bodyParts.butt === "giant" || $bodyParts.butt === "huge")>> <<set _hasVoluptuous = $physicalTraits && $physicalTraits.includes("Voluptuous")>> <<set _hasLeadership = $skills && $skills.includes("Leadership")>> <<set _leadershipBlockedByTransform = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation("Leadership", "skill")>> <<if _hasHugeChest && _hasHugeButt && _hasVoluptuous && (_hasLeadership || _leadershipBlockedByTransform)>> <<set _rewardType = "money">> <<set _rewardName = "$5,000">> <<set $money += 5000>> <<else>> <<set _options = []>> <<if !_hasHugeChest>><<set _options.push("hugechest")>><</if>> <<if !_hasHugeButt>><<set _options.push("hugebutt")>><</if>> <<if !_hasVoluptuous>><<set _options.push("voluptuous")>><</if>> <<if !_hasLeadership && !_leadershipBlockedByTransform>><<set _options.push("leadership")>><</if>> <<set _choice = _options.random()>> <<if _choice === "hugechest">> <<set _rewardType = "hugechest">> <<set $bodyParts.chest = "huge">> <<elseif _choice === "hugebutt">> <<set _rewardType = "hugebutt">> <<set $bodyParts.butt = "huge">> <<elseif _choice === "voluptuous">> <<set _rewardType = "voluptuous">> <<run $physicalTraits.push("Voluptuous")>> <<else>> <<set _rewardType = "leadership">> <<run $skills.push("Leadership")>> <</if>> <</if>> <<else>> <<set _rewardType = "money">> <<set _rewardName = "$100">> <<set $money += 100>> <</if>> <!-- Achievement checks --> <<if _rewardType === "bimbo">> <<run setup.achievements.unlock("become_bimbo")>> <</if>> <<if _rewardType === "lucky">> <<run setup.achievements.unlock("lucky_trait")>> <</if>> <<if _rewardType === "gigchest" || _rewardType === "gigbutt">> <!-- Check if both are now gigantic --> <<if $bodyParts.chest === "gigantic" && $bodyParts.butt === "gigantic">> <<run setup.achievements.unlock("gigantic_proportions")>> <</if>> <</if>> <div style="background: linear-gradient(135deg, #0a1a2a 0%, #000000 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #9c27b0; text-align: center; text-shadow: 0 0 30px #9c27b0, 0 0 50px #9c27b0, 0 0 70px #9c27b0;">🔥 The Sacrifice</h1> <div style="padding: 25px; background: linear-gradient(135deg, #4a148c 0%, #6a1b9a 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 8px 16px rgba(156, 39, 176, 0.6), 0 0 40px rgba(156, 39, 176, 0.4), inset 0 0 30px rgba(156, 39, 176, 0.2);"> <p style="color: #e1bee7; font-size: 18px; margin: 0; text-align: center; line-height: 1.6; text-shadow: 0 0 15px rgba(225, 190, 231, 0.5);"> You place your hands on the jewel. It pulses with hunger, eager to consume. Your sacrificed traits begin to flow out of you like wisps of colored smoke. Memories, abilities, aspects of yourself spiraling into the gem's depths. </p> </div> <div style="background: linear-gradient(135deg, #152535 0%, #0a1520 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 4px 8px rgba(0,0,0,0.6), 0 0 30px rgba(156, 39, 176, 0.3);"> <h3 style="color: #9c27b0; margin: 0 0 15px 0; text-align: center; text-shadow: 0 0 20px #9c27b0;">Traits Sacrificed:</h3> <<for _i = 0; _i < $altarSelectedTraits.length; _i++>> <p style="color: #ff6b6b; margin: 5px 0; text-align: center; text-shadow: 0 0 10px rgba(255, 107, 107, 0.5);">- $altarSelectedTraits[_i].name ($altarSelectedTraits[_i].value points)</p> <</for>> </div> <!-- TRANSFORMATION SCENES --> <<if _rewardType === "sunfish">> <div style="padding: 25px; background: linear-gradient(135deg, #006064 0%, #00bcd4 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #00bcd4; box-shadow: 0 8px 16px rgba(0,188,212, 0.6), 0 0 50px rgba(0,188,212, 0.5), inset 0 0 40px rgba(0,188,212, 0.2);"> <p style="color: #e0f7fa; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(224, 247, 250, 0.6);"> The jewel flares brilliant blue-green, the color of deep ocean waters. The light engulfs you completely. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #00bcd4;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSunfishTransformationText(true)>> </p> </div> </div> <<elseif _rewardType === "were">> <div style="padding: 25px; background: linear-gradient(135deg, #3e2723 0%, #5d4037 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #795548; box-shadow: 0 8px 16px rgba(121, 85, 72, 0.6), 0 0 50px rgba(121, 85, 72, 0.5), inset 0 0 40px rgba(121, 85, 72, 0.2);"> <p style="color: #d7ccc8; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(215, 204, 200, 0.6);"> The jewel pulses with primal energy. You feel your teeth sharpen, then return to normal. Your muscles spasm and flex with impossible strength for just a moment before settling. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #795548;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getWereCreatureTransformationText(true, "wolf")>> </p> </div> </div> <<elseif _rewardType === "defvamp" || _rewardType === "totvamp">> <div style="padding: 25px; background: linear-gradient(135deg, #1a0000 0%, #4a0000 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #c62828; box-shadow: 0 8px 16px rgba(198, 40, 40, 0.6), 0 0 50px rgba(198, 40, 40, 0.5), inset 0 0 40px rgba(198, 40, 40, 0.2);"> <p style="color: #ffcdd2; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(255, 205, 210, 0.6);"> The jewel turns crimson, pulsing like a heartbeat. Your own heart... slows. And slows. You feel cold spread through your veins, yet you're more alive than ever. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #c62828;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getVampireTransformationText(true)>> </p> </div> <p style="color: #ffcdd2; font-size: 16px; margin: 15px 0 0 0; text-align: center; line-height: 1.6; text-shadow: 0 0 15px rgba(255, 205, 210, 0.6);"> You are <<if _rewardType === "defvamp">>definitely<<else>>totally<</if>> not a vampire. <<if _rewardType === "defvamp">>Definitely.<<else>>Totally.<</if>> </p> </div> <<elseif _rewardType === "lucky">> <div style="padding: 25px; background: linear-gradient(135deg, #f57f17 0%, #fbc02d 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #ffd600; box-shadow: 0 8px 16px rgba(255, 214, 0, 0.6), 0 0 50px rgba(255, 214, 0, 0.5), inset 0 0 40px rgba(255, 214, 0, 0.2);"> <p style="color: #1a1a1a; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(255, 255, 255, 0.8);"> The jewel shimmers with golden light. You feel... lighter. As if invisible chains have fallen away. The universe shifts ever so slightly in your favor. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ffd600;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getMentalTraitChangeText("Lucky", true)>> </p> </div> </div> <<elseif _rewardType === "gigchest">> <div style="padding: 25px; background: linear-gradient(135deg, #880e4f 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 8px 16px rgba(233, 30, 99, 0.6), 0 0 50px rgba(233, 30, 99, 0.5), inset 0 0 40px rgba(233, 30, 99, 0.2);"> <p style="color: #f8bbd0; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(248, 187, 208, 0.6);"> Heat blooms in your chest. Not painful. Pleasurable. Your nipples harden instantly as warmth spreads across your torso. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #e91e63;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getChestTransformationText(_oldChest, "gigantic")>> </p> </div> </div> <<elseif _rewardType === "gigbutt">> <div style="padding: 25px; background: linear-gradient(135deg, #4a148c 0%, #6a1b9a 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 8px 16px rgba(156, 39, 176, 0.6), 0 0 50px rgba(156, 39, 176, 0.5), inset 0 0 40px rgba(156, 39, 176, 0.2);"> <p style="color: #e1bee7; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(225, 190, 231, 0.6);"> Warmth spreads through your hips and thighs, pooling in your rear. You feel a tingling sensation, then a rush of pleasure as the transformation begins. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #9c27b0;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getButtTransformationText(_oldButt, "gigantic")>> </p> </div> </div> <<elseif _rewardType === "giantchest">> <div style="padding: 25px; background: linear-gradient(135deg, #880e4f 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 8px 16px rgba(233, 30, 99, 0.6), 0 0 50px rgba(233, 30, 99, 0.5), inset 0 0 40px rgba(233, 30, 99, 0.2);"> <p style="color: #f8bbd0; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(248, 187, 208, 0.6);"> A warm tingling spreads across your chest. You feel pressure building, pleasant and insistent. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #e91e63;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getChestTransformationText(_oldChest, "giant")>> </p> </div> </div> <<elseif _rewardType === "giantbutt">> <div style="padding: 25px; background: linear-gradient(135deg, #4a148c 0%, #6a1b9a 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 8px 16px rgba(156, 39, 176, 0.6), 0 0 50px rgba(156, 39, 176, 0.5), inset 0 0 40px rgba(156, 39, 176, 0.2);"> <p style="color: #e1bee7; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(225, 190, 231, 0.6);"> Heat blooms in your rear, spreading through your hips. You gasp as the transformation begins. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #9c27b0;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getButtTransformationText(_oldButt, "giant")>> </p> </div> </div> <<elseif _rewardType === "bimbo">> <div style="padding: 25px; background: linear-gradient(135deg, #c2185b 0%, #f06292 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #ff4081; box-shadow: 0 8px 16px rgba(255, 64, 129, 0.6), 0 0 50px rgba(255, 64, 129, 0.5), inset 0 0 40px rgba(255, 64, 129, 0.2);"> <h3 style="color: #fce4ec; margin: 0 0 15px 0; text-align: center; font-size: 24px; text-shadow: 0 0 20px rgba(252, 228, 236, 0.8);">💋 Bimbo Transformation</h3> <p style="color: #fce4ec; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(252, 228, 236, 0.6);"> Pink light floods through you. Your entire body tingles with building pleasure. The transformation starts everywhere at once. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #ff4081;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getBimboTransformationText(true)>> </p> </div> </div> <<elseif _rewardType === "occult">> <div style="padding: 25px; background: linear-gradient(135deg, #311b92 0%, #512da8 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #673ab7; box-shadow: 0 8px 16px rgba(103, 58, 183, 0.6), 0 0 50px rgba(103, 58, 183, 0.5), inset 0 0 40px rgba(103, 58, 183, 0.2);"> <p style="color: #d1c4e9; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(209, 196, 233, 0.6);"> The jewel pulses with eldritch energy. Symbols flash through your mind. Ancient, powerful, forbidden. Knowledge floods into you. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #673ab7;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSkillGainText("Occult Expert")>> </p> </div> </div> <<elseif _rewardType === "hugechest">> <div style="padding: 25px; background: linear-gradient(135deg, #880e4f 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #e91e63; box-shadow: 0 8px 16px rgba(233, 30, 99, 0.6), 0 0 50px rgba(233, 30, 99, 0.5), inset 0 0 40px rgba(233, 30, 99, 0.2);"> <p style="color: #f8bbd0; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(248, 187, 208, 0.6);"> Warmth spreads across your chest. You feel a pleasant tingling as your breasts begin to grow. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #e91e63;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getChestTransformationText(_oldChest, "huge")>> </p> </div> </div> <<elseif _rewardType === "hugebutt">> <div style="padding: 25px; background: linear-gradient(135deg, #4a148c 0%, #6a1b9a 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 8px 16px rgba(156, 39, 176, 0.6), 0 0 50px rgba(156, 39, 176, 0.5), inset 0 0 40px rgba(156, 39, 176, 0.2);"> <p style="color: #e1bee7; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(225, 190, 231, 0.6);"> A pleasant warmth spreads through your rear. You feel tingling as the transformation begins. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #9c27b0;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getButtTransformationText(_oldButt, "huge")>> </p> </div> </div> <<elseif _rewardType === "voluptuous">> <div style="padding: 25px; background: linear-gradient(135deg, #ad1457 0%, #d81b60 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #f06292; box-shadow: 0 8px 16px rgba(240, 98, 146, 0.6), 0 0 50px rgba(240, 98, 146, 0.5), inset 0 0 40px rgba(240, 98, 146, 0.2);"> <p style="color: #f8bbd0; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(248, 187, 208, 0.6);"> Warmth floods through your entire body. Your curves... amplify. Everything becomes more pronounced, more sensual. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #f06292;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getPhysicalTraitChangeText("Voluptuous", true)>> </p> </div> </div> <<elseif _rewardType === "leadership">> <div style="padding: 25px; background: linear-gradient(135deg, #b71c1c 0%, #d32f2f 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #f44336; box-shadow: 0 8px 16px rgba(244, 67, 54, 0.6), 0 0 50px rgba(244, 67, 54, 0.5), inset 0 0 40px rgba(244, 67, 54, 0.2);"> <p style="color: #ffcdd2; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(255, 205, 210, 0.6);"> The jewel blazes with commanding crimson light. Authority fills your very being. Your posture straightens, your gaze sharpens, and an undeniable presence radiates from you. </p> <div style="background: #1a1a1a; padding: 15px; margin: 15px 0; border-radius: 8px; border: 2px solid #f44336;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getSkillGainText("Leadership")>> </p> </div> </div> <<elseif _rewardType === "money">> <div style="padding: 25px; background: linear-gradient(135deg, #1b5e20 0%, #2e7d32 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #4caf50; box-shadow: 0 8px 16px rgba(76, 175, 80, 0.6), 0 0 50px rgba(76, 175, 80, 0.5), inset 0 0 40px rgba(76, 175, 80, 0.2);"> <p style="color: #c8e6c9; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6; text-shadow: 0 0 15px rgba(200, 230, 201, 0.6);"> The jewel flashes green. You feel... nothing physical. But when you look down, a stack of bills has materialized at your feet. </p> <p style="color: #c8e6c9; font-size: 16px; margin: 0; text-align: center; text-shadow: 0 0 15px rgba(200, 230, 201, 0.6);"> The altar grants you _rewardName in compensation. </p> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4fd1c5 0%, #339af0 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(79, 209, 197, 0.5); text-shadow: 0 0 10px rgba(255, 255, 255, 0.6);'>Continue</div>">> <<set $altarSelectedTraits = []>> <<set $altarSacrificeValue = 0>> <<goto "TheAlter">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(135deg, #1e3a5f 0%, #0d1b2a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #4fc3f7; text-align: center; text-shadow: 0 0 20px #4fc3f7;">🏊 Swimming</h1> <!-- Swimming time tracking display --> <<set _totalSwimTime = $swimmingMinutesToday>> <<set _remainingSwimTime = 180 - _totalSwimTime>> <div style="background: #1a2a3a; padding: 12px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #4fc3f7; text-align: center;"> <p style="color: #4fc3f7; margin: 0; font-size: 14px;"> Today's Swimming: _totalSwimTime / 180 minutes <<if _remainingSwimTime > 0>> (_remainingSwimTime minutes remaining) <<else>> <span style="color: #ff6b6b;">(Daily limit reached!)</span> <</if>> </p> </div> <<if $swimSkillLearned>> <!-- Skill learned message --> <div style="padding: 25px; background: linear-gradient(135deg, #1565c0 0%, #0d47a1 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #4fc3f7; box-shadow: 0 8px 16px rgba(79, 195, 247, 0.6), 0 0 40px rgba(79, 195, 247, 0.4);"> <p style="color: #bbdefb; font-size: 18px; margin: 0 0 15px 0; text-align: center; line-height: 1.6; text-shadow: 0 0 10px rgba(187, 222, 251, 0.5);"> You dive into the cool ocean water, your movements becoming more fluid and natural with each stroke. After weeks of practice, swimming has become second nature to you. </p> <p style="color: #4caf50; font-size: 20px; margin: 0; text-align: center; font-weight: bold; text-shadow: 0 0 20px #4caf50;"> You have gained the $swimSkillLearned skill! </p> </div> <<set $swimSkillLearned = null>> <<else>> <!-- Normal swimming message --> <div style="padding: 20px; background: linear-gradient(135deg, #1565c0 0%, #0d47a1 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4fc3f7; box-shadow: 0 4px 8px rgba(79, 195, 247, 0.3);"> <p style="color: #bbdefb; font-size: 16px; margin: 0; text-align: center; line-height: 1.6;"> You spend an hour swimming in the refreshing ocean water. The waves are gentle today, and the water is the perfect temperature. </p> </div> <!-- Progress indicator (only show if they don't have the skills, Siren includes Swimming) --> <<set _hasSwimmingSkill = ($skills && ($skills.includes("Swimming") || $skills.includes("Swimmer"))) || ($physicalTraits && $physicalTraits.includes("Siren"))>> <<if !_hasSwimmingSkill && $beachSwimCount > 0>> <div style="background: #1a2a3a; padding: 15px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #4fc3f7;"> <p style="color: #4fc3f7; margin: 0 0 10px 0; text-align: center; font-weight: bold;">Swimming Practice Progress</p> <div style="background: #0a1a2a; height: 30px; border-radius: 15px; overflow: hidden; border: 1px solid #4fc3f7;"> <<set _progress = ($beachSwimCount / 25) * 100>> <div style="background: linear-gradient(90deg, #4fc3f7 0%, #2196f3 100%); height: 100%; width: _progress%; transition: width 0.3s;"></div> </div> <p style="color: #aaa; margin: 10px 0 0 0; text-align: center; font-size: 14px;">$beachSwimCount / 25 sessions completed</p> </div> <</if>> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4fc3f7 0%, #2196f3 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.3);'>Return to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> <</nobr>>
<<if $phoneBackground and $phoneBackground neq "">> <<set _bgStyle = "background-image: url('" + $phoneBackground + "'); background-size: cover; background-position: center; background-repeat: no-repeat;">> <<else>> <<set _bgStyle = "background: linear-gradient(135deg, #3b82f6 0%, #ec4899 100%);">> <</if>> <div class="phone-wrapper"> <div class="phone-device"> <div class="phone-notch-container"> <div class="notch-base"></div> </div> <div class="phone-screen" @style="_bgStyle"> <div class="phone-statusbar"> <span class="status-left"><<= getTimeString()>></span> <span class="status-right">📶 🔋</span> </div> <div class="phone-content"> <!-- 6 rows of 4 apps --> <div class="apps-grid"> <!-- Row 1 --> <div class="app-row"> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/notes.webp"> <span>Notes</span> </div> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/maps.webp"> <span>Maps</span> </div> <div class="app-slot" onclick="SugarCube.Engine.play('BankApp')"> <img src="Images/Phone/App_Icons/bank.webp"> <span>Bank</span> </div> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/instafin.webp"> <span>InstaFin</span> </div> </div> <!-- Row 2 --> <div class="app-row"> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/sunfishnet.webp"> <span>SunfishNet</span> </div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> </div> <!-- Row 3 --> <div class="app-row"> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> </div> <!-- Row 4 --> <div class="app-row"> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> </div> <!-- Row 5 --> <div class="app-row"> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> </div> <!-- Row 6 --> <div class="app-row"> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> <div class="app-slot empty"></div> </div> </div> <!-- Dock --> <div class="apps-dock"> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/messages.webp"> <span>Messages</span> </div> <div class="app-slot" onclick="SugarCube.Engine.play('Gallery')"> <img src="Images/Phone/App_Icons/gallery.webp"> <span>Gallery</span> </div> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/contacts.webp"> <span>Contacts</span> </div> <div class="app-slot" onclick="alert('This function will be added in a future update.')"> <img src="Images/Phone/App_Icons/settings.webp"> <span>Settings</span> </div> </div> </div> <div class="phone-homebtn"></div> </div> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #1a1a1a; color: white; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold; border: 2px solid #667eea; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<if $lastLocation && $lastLocation !== "">> <<goto $lastLocation>> <<else>> <<goto "Alleyway">> <</if>> <</link>> </div> <style> .phone-wrapper { display: flex; justify-content: center; align-items: center; padding: 20px; } .phone-device { width: 360px; height: 680px; background: #0a0a0a; border-radius: 42px; padding: 6px; box-shadow: 0 25px 50px rgba(0,0,0,0.9); position: relative; display: flex; flex-direction: column; } .phone-notch-container { position: absolute; top: -24px; left: 50%; transform: translateX(-50%); z-index: 100; } .notch-base { width: 140px; height: 28px; background: #0a0a0a; border-radius: 0 0 18px 18px; } .phone-screen { border-radius: 36px; flex: 1; overflow: hidden; display: flex; flex-direction: column; position: relative; } .phone-statusbar { display: flex; justify-content: space-between; padding: 32px 25px 8px 25px; font-size: 12px; color: white; font-weight: 600; position: relative; z-index: 50; } .status-left { text-align: left; flex: 1; } .status-right { text-align: right; flex: 1; } .phone-content { flex: 1; display: flex; flex-direction: column; padding: 10px 18px 0 18px; overflow: hidden; } .apps-grid { flex: 1; display: flex; flex-direction: column; gap: 18px; } .app-row { display: flex; justify-content: space-around; align-items: flex-start; } .apps-dock { display: flex; justify-content: space-around; align-items: center; margin: 25px 0 0 0; padding: 14px 8px; background: rgba(255,255,255,0.2); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); border-radius: 20px; } .app-slot { display: flex; flex-direction: column; align-items: center; width: 70px; cursor: pointer; transition: transform 0.2s; } .app-slot.empty { visibility: hidden; pointer-events: none; } .app-slot:not(.empty):hover { transform: scale(1.1); } .app-slot:not(.empty):active { transform: scale(0.95); } .app-slot img { width: 56px; height: 56px; border-radius: 14px; box-shadow: 0 4px 12px rgba(0,0,0,0.5); display: block; } .app-slot span { margin-top: 5px; font-size: 10px; color: white; text-shadow: 0 1px 3px rgba(0,0,0,0.9); font-weight: 500; text-align: center; max-width: 70px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .phone-homebtn { width: 110px; height: 4px; background: rgba(255,255,255,0.5); border-radius: 2px; margin: 8px auto 8px auto; } </style>
<<if not $galleryViewMode>><<set $galleryViewMode = false>><</if>> <<if not $galleryViewIndex>><<set $galleryViewIndex = 0>><</if>> <<if $galleryViewMode>> <!-- Full Image View --> <div class="gallery-wrapper"> <div class="gallery-device"> <div class="gallery-notch-container"> <div class="gallery-notch-base"></div> </div> <div class="gallery-screen gallery-view-screen"> <div class="gallery-view-header"> <span class="back-btn" id="close-view">← Back</span> <span class="view-counter"><<print $galleryViewIndex + 1>> / 8</span> <span class="spacer"></span> </div> <div class="image-viewer" id="image-viewer"> <<if $galleryViewIndex == 0>> <img src="Images/Phone/Gallery/Background_1.webp" class="view-image"> <<elseif $galleryViewIndex == 1>> <img src="Images/Phone/Gallery/Background_2.webp" class="view-image"> <<elseif $galleryViewIndex == 2>> <img src="Images/Phone/Gallery/Background_3.webp" class="view-image"> <<elseif $galleryViewIndex == 3>> <img src="Images/Phone/Gallery/Background_4.webp" class="view-image"> <<elseif $galleryViewIndex == 4>> <img src="Images/Phone/Gallery/Background_5.webp" class="view-image"> <<elseif $galleryViewIndex == 5>> <img src="Images/Phone/Gallery/Background_6.webp" class="view-image"> <<elseif $galleryViewIndex == 6>> <div class="view-gradient"></div> <<elseif $galleryViewIndex == 7>> <<if $customUploadedImage>> <img @src="$customUploadedImage" class="view-image"> <<else>> <div class="view-placeholder">No custom image</div> <</if>> <</if>> </div> <div class="view-actions"> <button class="set-wallpaper-btn" id="set-wallpaper">Set as Wallpaper</button> </div> <div class="gallery-homebtn"></div> </div> </div> </div> <script> (function() { let startX = 0; let currentX = 0; let isDragging = false; const viewer = document.getElementById('image-viewer'); const threshold = 50; viewer.addEventListener('touchstart', handleStart, false); viewer.addEventListener('touchmove', handleMove, false); viewer.addEventListener('touchend', handleEnd, false); viewer.addEventListener('mousedown', handleStart, false); viewer.addEventListener('mousemove', handleMove, false); viewer.addEventListener('mouseup', handleEnd, false); viewer.addEventListener('mouseleave', handleEnd, false); function handleStart(e) { isDragging = true; startX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX; } function handleMove(e) { if (!isDragging) return; currentX = e.type.includes('mouse') ? e.clientX : e.touches[0].clientX; const diff = currentX - startX; viewer.style.transform = `translateX(${diff}px)`; } function handleEnd(e) { if (!isDragging) return; isDragging = false; const diff = currentX - startX; viewer.style.transform = ''; if (Math.abs(diff) > threshold) { if (diff > 0) { if (SugarCube.State.variables.galleryViewIndex > 0) { SugarCube.State.variables.galleryViewIndex--; SugarCube.Engine.play('Gallery'); } } else { if (SugarCube.State.variables.galleryViewIndex < 7) { SugarCube.State.variables.galleryViewIndex++; SugarCube.Engine.play('Gallery'); } } } } document.getElementById('close-view').addEventListener('click', function() { SugarCube.State.variables.galleryViewMode = false; SugarCube.Engine.play('Gallery'); }); document.getElementById('set-wallpaper').addEventListener('click', function() { const index = SugarCube.State.variables.galleryViewIndex; if (index === 6) { /* Default gradient - set to empty string */ SugarCube.State.variables.phoneBackground = ''; } else { const images = [ 'Images/Phone/Gallery/Background_1.webp', 'Images/Phone/Gallery/Background_2.webp', 'Images/Phone/Gallery/Background_3.webp', 'Images/Phone/Gallery/Background_4.webp', 'Images/Phone/Gallery/Background_5.webp', 'Images/Phone/Gallery/Background_6.webp', '', SugarCube.State.variables.customUploadedImage || '' ]; SugarCube.State.variables.phoneBackground = images[index]; } SugarCube.Engine.play('Phone'); }); })(); </script> <<else>> <!-- Gallery Grid View --> <div class="gallery-wrapper"> <div class="gallery-device"> <div class="gallery-notch-container"> <div class="gallery-notch-base"></div> </div> <div class="gallery-screen"> <div class="gallery-statusbar"> <span class="status-left"><<link "← Phone" "Phone">><</link>></span> <h2>Gallery</h2> <span class="spacer"></span> </div> <div class="gallery-content"> <div class="photo-grid"><img src="Images/Phone/Gallery/Background_1.webp" class="grid-photo"><img src="Images/Phone/Gallery/Background_2.webp" class="grid-photo"><img src="Images/Phone/Gallery/Background_3.webp" class="grid-photo"><img src="Images/Phone/Gallery/Background_4.webp" class="grid-photo"><img src="Images/Phone/Gallery/Background_5.webp" class="grid-photo"><img src="Images/Phone/Gallery/Background_6.webp" class="grid-photo"><div class="grid-photo grid-gradient"></div><<if $customUploadedImage>><img @src="$customUploadedImage" class="grid-photo"><<else>><label for="custom-wallpaper" class="grid-photo grid-upload"><span class="upload-icon">+</span><input type="file" id="custom-wallpaper" accept="image/*" style="display: none;"></label><</if>></div> </div> <div class="gallery-homebtn"></div> </div> </div> </div> <script> (function() { /* Apply click handlers to images */ const grid = document.querySelector('.photo-grid'); const imgs = grid.querySelectorAll('img:not([type="file"])'); imgs.forEach((img, index) => { if (index < 6) { img.style.cursor = 'pointer'; img.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); SugarCube.State.variables.galleryViewMode = true; SugarCube.State.variables.galleryViewIndex = index; SugarCube.Engine.play('Gallery'); }); } else if (index === 6) { /* This is the custom uploaded image */ img.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); SugarCube.State.variables.galleryViewMode = true; SugarCube.State.variables.galleryViewIndex = 7; SugarCube.Engine.play('Gallery'); }); } }); /* Add click handler to gradient */ const gradient = document.querySelector('.grid-gradient'); if (gradient) { gradient.addEventListener('click', function() { SugarCube.State.variables.galleryViewMode = true; SugarCube.State.variables.galleryViewIndex = 6; SugarCube.Engine.play('Gallery'); }); } const uploadInput = document.getElementById('custom-wallpaper'); if (uploadInput) { uploadInput.addEventListener('change', function(e) { const file = e.target.files[0]; if (file && file.type.startsWith('image/')) { const reader = new FileReader(); reader.onload = function(event) { SugarCube.State.variables.customUploadedImage = event.target.result; SugarCube.Engine.play('Gallery'); }; reader.readAsDataURL(file); } }); } })(); </script> <</if>> <style> .gallery-wrapper { display: flex; justify-content: center; align-items: center; padding: 20px; min-height: 100vh; background: #0a0a0a; } .gallery-device { width: 360px; height: 680px; background: #0a0a0a; border-radius: 42px; padding: 6px; box-shadow: 0 25px 50px rgba(0,0,0,0.9); position: relative; display: flex; flex-direction: column; } .gallery-notch-container { position: absolute; top: -24px; left: 50%; transform: translateX(-50%); z-index: 100; } .gallery-notch-base { width: 140px; height: 28px; background: #0a0a0a; border-radius: 0 0 18px 18px; } .gallery-screen { background: #2a2a2a; border-radius: 36px; flex: 1; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; position: relative; } .gallery-statusbar { display: flex; justify-content: space-between; align-items: center; padding: 32px 20px 12px 20px; font-size: 12px; color: white; font-weight: 600; position: sticky; top: 0; background: #2a2a2a; z-index: 50; border-bottom: 1px solid #3a3a3a; } .gallery-statusbar a { color: #3b82f6; text-decoration: none; font-size: 14px; } .gallery-statusbar h2 { margin: 0; font-size: 16px; color: #ffffff; } .spacer { width: 50px; } .gallery-content { padding: 8px; flex: 1; } .photo-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; } .photo-grid img { width: 100%; height: 108px; object-fit: cover; border-radius: 4px; display: block; } .grid-photo { width: 100%; height: 108px; object-fit: cover; border-radius: 4px; display: block; cursor: pointer; } .grid-gradient { background: linear-gradient(135deg, #3b82f6 0%, #ec4899 100%); cursor: pointer; } .grid-upload { background: #3a3a3a; display: flex; align-items: center; justify-content: center; } .upload-icon { font-size: 32px; color: #888; } .gallery-homebtn { width: 110px; height: 4px; background: rgba(255,255,255,0.5); border-radius: 2px; margin: 8px auto 8px auto; } /* Image Viewer Styles */ .gallery-view-screen { background: #000000; } .gallery-view-header { display: flex; justify-content: space-between; align-items: center; padding: 32px 20px 12px 20px; color: white; font-weight: 600; background: rgba(0,0,0,0.8); z-index: 50; } .back-btn { color: #3b82f6; cursor: pointer; font-size: 14px; } .view-counter { font-size: 14px; color: #ffffff; } .image-viewer { flex: 1; display: flex; align-items: center; justify-content: center; padding: 20px; touch-action: pan-y; user-select: none; transition: transform 0.2s ease-out; } .view-image { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; border-radius: 8px; } .view-gradient { width: 100%; height: 400px; background: linear-gradient(135deg, #3b82f6 0%, #ec4899 100%); border-radius: 8px; } .view-placeholder { color: #888; font-size: 16px; text-align: center; } .view-actions { padding: 15px 20px; background: rgba(0,0,0,0.8); } .set-wallpaper-btn { width: 100%; background: #555555; color: white; border: none; padding: 12px; border-radius: 8px; font-size: 15px; font-weight: 600; cursor: pointer; } .set-wallpaper-btn:hover { background: #666666; } </style>
<!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("SecretLocation")>> <h2 style="color: #ff6b9d; text-shadow: 0 0 15px #ff6b9d;">🔮 Mysterious Visitors</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b9d; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(255, 107, 157, 0.3);"> <p style="color: #ffa5c5; font-size: 14px; margin: 0 0 15px 0; text-align: center; font-style: italic; text-shadow: 0 0 10px rgba(255, 165, 197, 0.5);"> Others who know of this hidden place gather here... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ff6b9d; border-radius: 10px; padding: 15px; background: #0f0f1e; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 107, 157, 0.2);"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0; text-shadow: 0 0 10px rgba(255, 107, 157, 0.5);">_npc.name</h3> <p style="font-size: 14px; color: #ffa5c5; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: linear-gradient(135deg, #ff6b9d 0%, #c44569 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 15px rgba(255, 107, 157, 0.3);'>💬 Approach _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #888; margin: 0; font-style: italic;"> The secret location is empty. You are alone in the shadows. </p> </div> <</if>>
<<nobr>> <<set _npc = $tradingWithNPC>> <!-- Initialize if needed --> <<if !$selectedTraitsToSell>> <<set $selectedTraitsToSell = []>> <</if>> <!-- ===== SKILL TREE: Get bonuses ===== --> <<set _sellValueBonus = setup.skillTree.getEffect("sellValueBonus")>> <<set _sellWeeklyBonus = setup.skillTree.getEffect("sellWeeklyBonus")>> <<set _sellRelationshipBonus = setup.skillTree.getEffect("sellRelationshipBonus")>> <!-- Calculate total value and cash --> <<set _totalValue = 0>> <<set _baseCash = 0>> <<for _i = 0; _i < $selectedTraitsToSell.length; _i++>> <<set _totalValue += $selectedTraitsToSell[_i].value>> <<set _baseCash += ($selectedTraitsToSell[_i].value * 3)>> <</for>> <!-- ===== SKILL TREE: Apply sell value bonus ===== --> <<set _bonusMultiplier = 1 + (_sellValueBonus / 100)>> <<set _totalCash = Math.floor(_baseCash * _bonusMultiplier)>> <<set _bonusCash = _totalCash - _baseCash>> <!-- ===== SKILL TREE: Apply weekly bonus if available ===== --> <<set _weeklyBonusCash = 0>> <<set _weeklyBonusApplied = false>> <<if _sellWeeklyBonus > 0 && !$sellWeeklyBonusUsed && $selectedTraitsToSell.length > 0>> <<set _weeklyBonusCash = _sellWeeklyBonus * 3>> <<set _totalCash += _weeklyBonusCash>> <<set $sellWeeklyBonusUsed = true>> <<set _weeklyBonusApplied = true>> <</if>> <!-- Punk 1.5x cash bonus when selling traits to Roisin --> <<set _punkBonusApplied = false>> <<set _punkBonusCash = 0>> <<if $physicalTraits && $physicalTraits.includes("Punk")>> <<set _punkBonusCash = Math.floor(_totalCash * 0.5)>> <<set _totalCash = Math.floor(_totalCash * 1.5)>> <<set _punkBonusApplied = true>> <</if>> <!-- Remove traits from player --> <<for _i = 0; _i < $selectedTraitsToSell.length; _i++>> <<set _trait = $selectedTraitsToSell[_i]>> <<if _trait.type === "physical">> <<run $physicalTraits.delete(_trait.name)>> <<elseif _trait.type === "mental">> <<run $mentalTraits.delete(_trait.name)>> <<elseif _trait.type === "skill">> <<run $skills.delete(_trait.name)>> <</if>> <</for>> <!-- Unlock achievement for first trait sale --> <<if $selectedTraitsToSell.length > 0>> <<run setup.achievements.unlock("sell_trait")>> <</if>> <!-- Add cash --> <<set $money += _totalCash>> <!-- Update tracking --> <<set $roisinTraitsSoldValue += _totalValue>> <<set $roisinWeeklySoldValue += _totalValue>> <!-- Calculate relationship increase (1 point per 50 points sold) --> <<set _baseRelationshipIncrease = Math.floor(_totalValue / 50)>> <!-- ===== SKILL TREE: Apply relationship bonus ===== --> <<set _relationshipIncrease = _baseRelationshipIncrease>> <<if _sellRelationshipBonus > 0 && $selectedTraitsToSell.length > 0>> <<set _relationshipIncrease += _sellRelationshipBonus>> <</if>> <<if _relationshipIncrease > 0>> <<set _npc.relationship += _relationshipIncrease>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #28a745 0%, #20c997 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #28a745;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">✅ Sale Complete!</h1> </div> <!-- Sale Summary --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 15px 0;">💰 Transaction Summary</h3> <<if $selectedTraitsToSell.length > 0>> <p style="color: #ccc; margin: 5px 0;">Traits Sold: <<print $selectedTraitsToSell.length>></p> <p style="color: #ffc107; margin: 5px 0; font-size: 18px; font-weight: bold;">Total Points: _totalValue</p> <!-- Show breakdown if bonuses applied --> <<if _bonusCash > 0 || _weeklyBonusCash > 0>> <p style="color: #888; margin: 5px 0; font-size: 14px;">Base Cash: $<<print _baseCash>></p> <<if _bonusCash > 0>> <p style="color: #9C27B0; margin: 2px 0; font-size: 14px;">⭐ Value Bonus (+<<print _sellValueBonus>>%): +$<<print _bonusCash>></p> <</if>> <<if _weeklyBonusApplied>> <p style="color: #51cf66; margin: 2px 0; font-size: 14px;">⭐ Weekly Bonus (+<<print _sellWeeklyBonus>> pts): +$<<print _weeklyBonusCash>></p> <</if>> <<if _punkBonusApplied>> <p style="color: #ff6b9d; margin: 2px 0; font-size: 14px;">✓ Punk Bonus (1.5x): +$<<print _punkBonusCash>></p> <</if>> <</if>> <p style="color: #28a745; margin: 5px 0; font-size: 20px; font-weight: bold;">Cash Received: $<<print _totalCash>></p> <<if _relationshipIncrease > 0>> <p style="color: #e91e63; margin: 10px 0 0 0; font-size: 18px; font-weight: bold;"> 💕 Relationship with _npc.name increased by _relationshipIncrease! <<if _sellRelationshipBonus > 0 && _baseRelationshipIncrease < _relationshipIncrease>> <span style="color: #9C27B0; font-size: 14px;">(⭐ +<<print _sellRelationshipBonus>> from skill tree)</span> <</if>> </p> <</if>> <<else>> <p style="color: #888; margin: 0; font-style: italic;">No traits were sold.</p> <</if>> </div> <!-- Roisin's Response --> <<if $selectedTraitsToSell.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; font-size: 18px; font-style: italic; margin: 0; text-align: center;"> <<if _totalValue >= 100>> "Now that's a proper deal! Pleasure doin' business with ye." <<elseif _totalValue >= 50>> "Not bad at all. I'll take what I can get." <<else>> "A small deal, but money's money, eh?" <</if>> </p> </div> <</if>> <!-- Continue Button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Continue</div>">> <<set $selectedTraitsToSell = []>> <<goto "NPCInteraction">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.95); padding: 30px; border-radius: 15px; max-width: 600px; margin: 50px auto; border: 3px solid #e040fb; box-shadow: 0 0 30px rgba(224, 64, 251, 0.3);"> <div style="text-align: center;"> <div style="font-size: 64px; margin-bottom: 20px;">🧬</div> <h1 style="color: #e040fb; margin: 0 0 20px 0;">Trait Storage Unlocked!</h1> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #7c4dff;"> <p style="color: #ccc; font-size: 16px; margin: 0 0 15px 0; line-height: 1.6;"> Roisin nods approvingly as the money changes hands. </p> <p style="color: #e040fb; font-size: 18px; margin: 0; font-style: italic;"> "Smart investment. Now you can store traits for later... very useful for someone in our line of work." </p> </div> <div style="background: linear-gradient(135deg, #2d1f3d 0%, #1a1a2a 100%); padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #e040fb;"> <h3 style="color: #e040fb; margin: 0 0 15px 0;">What You Can Do:</h3> <ul style="color: #ccc; text-align: left; margin: 0; padding-left: 25px; line-height: 2;"> <li>Store positive traits from your body for safekeeping</li> <li>Retrieve stored traits when you want them back</li> <li>Access trait storage from your Inventory menu</li> </ul> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Continue</div>">> <<goto "NPCInteraction">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <!-- Initialize tracking variable if needed --> <<if !$roisinTraitsSoldValue>> <<set $roisinTraitsSoldValue = 0>> <</if>> <!-- Initialize weekly tracking --> <<if !$roisinWeeklySoldValue>> <<set $roisinWeeklySoldValue = 0>> <</if>> <<if !$roisinLastWeekReset>> <<set $roisinLastWeekReset = $weekNumber || 0>> <</if>> <!-- Initialize weekly bonus tracking --> <<if !$sellWeeklyBonusUsed>> <<set $sellWeeklyBonusUsed = false>> <</if>> <!-- Reset weekly counter if new week --> <<if $weekNumber > $roisinLastWeekReset>> <<set $roisinWeeklySoldValue = 0>> <<set $roisinLastWeekReset = $weekNumber>> <<set $sellWeeklyBonusUsed = false>> <</if>> <!-- ===== SKILL TREE: Get bonuses for display ===== --> <<set _sellValueBonus = setup.skillTree.getEffect("sellValueBonus")>> <<set _sellWeeklyBonus = setup.skillTree.getEffect("sellWeeklyBonus")>> <<set _sellRelationshipBonus = setup.skillTree.getEffect("sellRelationshipBonus")>> <!-- Check if player is lifeswapped (not in original body) --> <<if $lifeSwapPortraitSource && $lifeSwapPortraitSource !== "player">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #9C27B0;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">🔄 Wrong Body</h1> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #9C27B0; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #CE93D8; font-size: 20px; font-weight: bold; margin: 0 0 15px 0; text-align: center;"> Roisin squints at you suspiciously. </p> <p style="color: #ccc; font-size: 18px; font-style: italic; margin: 0; text-align: center;"> "Hold on a feckin' minute... Ye're not in yer own body, are ye? I can smell it on ye. Come back when ye're yerself again - I don't deal in stolen goods, and sellin' someone else's traits counts as thievery in me book." </p> </div> <!-- Back Button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>↠Back</div>">> <<set $selectedTraitsToSell = []>> <<goto "NPCInteraction">> <</link>> </div> </div> <<else>> <!-- Check if player is a bimbo --> <<if $mentalTraits && $mentalTraits.includes("Bimbo")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #dc3545;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">🚫 No Deal</h1> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #dc3545; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ff6b6b; font-size: 20px; font-weight: bold; margin: 0 0 15px 0; text-align: center;"> Roisin looks you up and down with disgust. </p> <p style="color: #ccc; font-size: 18px; font-style: italic; margin: 0; text-align: center;"> "I don't do business with stupid fuckin' bimbos, ye hear? Now piss off before I lose me patience entirely." </p> </div> <!-- Back Button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<set $selectedTraitsToSell = []>> <<goto "NPCInteraction">> <</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #28a745 0%, #20c997 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #28a745;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">💰 Sell Traits to _npc.name</h1> <p style="color: white; margin: 0; font-size: 16px; text-align: center; font-style: italic;"> "Right then, I'll pay ye for any trait yer willin' to part with. Cash up front, no questions asked." </p> </div> <!-- Info Box --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">ℹ️ How This Works</h3> <p style="color: #ccc; margin: 5px 0;">• Select traits to sell for cash</p> <p style="color: #ccc; margin: 5px 0;">• Cannot sell worthless or certain traits</p> <p style="color: #ccc; margin: 5px 0;">• Base rate: 3x trait value in cash</p> <p style="color: #ffc107; margin: 10px 0 0 0; font-weight: bold;">Total Sold This Week: $roisinWeeklySoldValue points</p> </div> <!-- ===== SKILL TREE: Bonus Display ===== --> <<if _sellValueBonus > 0 || _sellWeeklyBonus > 0 || _sellRelationshipBonus > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #9C27B0; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #CE93D8; margin: 0 0 10px 0;">⭐ Skill Tree Bonuses Active</h3> <<if _sellValueBonus > 0>> <p style="color: #CE93D8; margin: 5px 0;">• +<<print _sellValueBonus>>% bonus cash on all sales</p> <</if>> <<if _sellWeeklyBonus > 0>> <<if !$sellWeeklyBonusUsed>> <p style="color: #51cf66; margin: 5px 0;">• +<<print _sellWeeklyBonus>> bonus points on first sale this week (AVAILABLE!)</p> <<else>> <p style="color: #888; margin: 5px 0;">• +<<print _sellWeeklyBonus>> bonus points on first sale this week (already claimed)</p> <</if>> <</if>> <<if _sellRelationshipBonus > 0>> <p style="color: #CE93D8; margin: 5px 0;">• +<<print _sellRelationshipBonus>> extra relationship per sale</p> <</if>> </div> <</if>> <!-- Selected Traits to Sell --> <<if !$selectedTraitsToSell>> <<set $selectedTraitsToSell = []>> <</if>> <<set _totalValue = 0>> <<set _baseCash = 0>> <<for _i = 0; _i < $selectedTraitsToSell.length; _i++>> <<set _totalValue += $selectedTraitsToSell[_i].value>> <<set _baseCash += ($selectedTraitsToSell[_i].value * 3)>> <</for>> <!-- ===== SKILL TREE: Apply sell value bonus ===== --> <<set _bonusMultiplier = 1 + (_sellValueBonus / 100)>> <<set _totalCash = Math.floor(_baseCash * _bonusMultiplier)>> <<set _bonusCash = _totalCash - _baseCash>> <!-- ===== SKILL TREE: Apply weekly bonus if available ===== --> <<set _weeklyBonusCash = 0>> <<if _sellWeeklyBonus > 0 && !$sellWeeklyBonusUsed && $selectedTraitsToSell.length > 0>> <<set _weeklyBonusCash = _sellWeeklyBonus * 3>> <<set _totalCash += _weeklyBonusCash>> <</if>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 15px 0;">📦 Selected Traits to Sell</h3> <<if $selectedTraitsToSell.length === 0>> <p style="color: #888; margin: 0; font-style: italic;">None selected yet, c'mon then...</p> <<else>> <<for _i = 0; _i < $selectedTraitsToSell.length; _i++>> <<capture _i>> <<set _trait = $selectedTraitsToSell[_i]>> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #28a745;"> <span style="color: #51cf66;">_trait.name (_trait.value pts = $<<print _trait.value * 3>>)</span> <<link "<span style='color: #ff6b6b; cursor: pointer; font-weight: bold;'>✖ Remove</span>">> <<run $selectedTraitsToSell.deleteAt(_i)>> <<goto "SellTraits">> <</link>> </div> <</capture>> <</for>> <div style="margin-top: 15px; padding: 15px; background: #1a1a1a; border-radius: 6px; border: 2px solid #ffc107;"> <p style="color: #ffc107; margin: 0; font-size: 18px; font-weight: bold;">Total Points: _totalValue</p> <<if _bonusCash > 0 || _weeklyBonusCash > 0>> <p style="color: #888; margin: 5px 0 0 0; font-size: 14px;">Base Cash: $<<print _baseCash>></p> <<if _bonusCash > 0>> <p style="color: #9C27B0; margin: 2px 0 0 0; font-size: 14px;">⭐ Value Bonus (+<<print _sellValueBonus>>%): +$<<print _bonusCash>></p> <</if>> <<if _weeklyBonusCash > 0>> <p style="color: #51cf66; margin: 2px 0 0 0; font-size: 14px;">⭐ Weekly Bonus (+<<print _sellWeeklyBonus>> pts): +$<<print _weeklyBonusCash>></p> <</if>> <</if>> <p style="color: #28a745; margin: 5px 0 0 0; font-size: 20px; font-weight: bold;">Total Cash: $<<print _totalCash>></p> </div> <</if>> </div> <!-- Available Traits --> <<set _availableTraits = []>> <!-- Get all player traits --> <<set _physicalTraits = $physicalTraits || []>> <<set _mentalTraits = $mentalTraits || []>> <<set _skills = $skills || []>> <!-- Stereotypes and forbidden traits --> <<set _forbiddenTraits = ["Bimbo", "Sunfish", "Short Hair", "Long Hair", "Awkward", "Bookworm", "Corrupt", "Cynical", "Flirty", "Introverted", "Kind", "Loyal", "Musky", "Negotiator", "Nonchalant", "Paranoid", "Quiet", "Shy", "Tease", "Tone Deaf", "Bad Luck", "Unpredictable", "Unskilled", "Blemished", "Clumsy", "Definitely not a Vampire", "Monotone Expression", "Overweight", "Petite", "Plain", "Short", "Slow", "Soft", "Stiff", "Ugly", "Underweight", "Voluptuous", "Weak"]>> <!-- Build forbidden set: base forbidden + event traits + all lab transformations --> <<set _forbiddenSellSet = new Set(_forbiddenTraits)>> <<run ["Blessed", "Wild", "Chosen", "Honey", "Cog", "Mystic", "Heart", "Guardian", "Darkness", "Alcoholic", "Disturbed", "Mirrored", "Thirsty", "Blood", "Burnt", "Inferno", "Scaled", "Divine Sunfish", "Electrified", "Totally not a Vampire", "Fish", "Futanari"].forEach(function(t) { _forbiddenSellSet.add(t); })>> <<run setup.combinationOnlyTraits.forEach(function(t) { _forbiddenSellSet.add(t); })>> <!-- Add physical traits --> <<for _i = 0; _i < _physicalTraits.length; _i++>> <<set _trait = _physicalTraits[_i]>> <<set _value = setup.getTraitValue("physical", _trait)>> <<if !_forbiddenSellSet.has(_trait) && _value && _value > 0>> <<set _availableTraits.push({name: _trait, type: "physical", value: _value})>> <</if>> <</for>> <!-- Add mental traits --> <<for _i = 0; _i < _mentalTraits.length; _i++>> <<set _trait = _mentalTraits[_i]>> <<set _value = setup.getTraitValue("mental", _trait)>> <<if !_forbiddenSellSet.has(_trait) && _value && _value > 0>> <<set _availableTraits.push({name: _trait, type: "mental", value: _value})>> <</if>> <</for>> <!-- Add skills --> <<for _i = 0; _i < _skills.length; _i++>> <<set _trait = _skills[_i]>> <<set _value = setup.getTraitValue("skill", _trait)>> <<if !_forbiddenSellSet.has(_trait) && _value && _value > 0>> <<set _availableTraits.push({name: _trait, type: "skill", value: _value})>> <</if>> <</for>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #667eea; margin: 0 0 15px 0;">📋 Available Traits to Sell</h3> <<if _availableTraits.length === 0>> <p style="color: #888; margin: 0; font-style: italic;">"Nothin' worth sellin', eh? Shame, that."</p> <<else>> <div style="max-height: 400px; overflow-y: auto;"> <<for _i = 0; _i < _availableTraits.length; _i++>> <<set _trait = _availableTraits[_i]>> <<set _alreadySelected = false>> <<for _j = 0; _j < $selectedTraitsToSell.length; _j++>> <<if $selectedTraitsToSell[_j].name === _trait.name>> <<set _alreadySelected = true>> <</if>> <</for>> <<if !_alreadySelected>> <<capture _trait>> <div style="background: #1a1a1a; padding: 12px; border-radius: 6px; margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #667eea;"> <span style="color: #a5b4fc;">_trait.name (_trait.value pts = $<<print _trait.value * 3>>)</span> <<link "<span style='color: #28a745; cursor: pointer; font-weight: bold;'>✚ Add</span>">> <<run $selectedTraitsToSell.push(_trait)>> <<goto "SellTraits">> <</link>> </div> <</capture>> <</if>> <</for>> </div> <</if>> </div> <!-- Sell Button --> <<if $selectedTraitsToSell.length > 0>> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); color: white; padding: 20px 40px; border-radius: 12px; font-weight: bold; font-size: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(40, 167, 69, 0.3);'>💰 Complete Sale ($<<print _totalCash>>)</div>">> <<goto "SellTraitsComplete">> <</link>> </div> <</if>> <!-- Back Button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<set $selectedTraitsToSell = []>> <<goto "NPCInteraction">> <</link>> </div> </div> <</if>> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "BeautySalonJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 16px; margin: 0;"> The salon manager looks impressed with your credentials. "We'd love to have you join our team! As a stylist here, you'll earn $18 per hour. You can work shifts between 9 AM and 6 PM, up to 8 hours per day. Plus, you'll get free hair services while you work here. What do you say?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Beauty Salon Stylist.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Beauty Salon Stylist"]>> <<set $homeless = false>> <<goto "BeautySalonJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "BeautySalon">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BeautySalonJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome to Angelfish Beauty Salon! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Excellent! Welcome aboard. You can start working whenever you're ready. Just come by during business hours and clock in for your shift. Looking forward to working with you!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Position:</strong> Beauty Salon Stylist</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Pay:</strong> $18 per hour</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Hours:</strong> 9 AM - 6 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Max Daily:</strong> 8 hours</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Benefits:</strong> Free hair services</p> </div> <<link "<div style='background: #28a745; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "BeautySalon">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DocksJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 16px; margin: 0;"> The dock foreman looks you up and down, then nods approvingly. "You look like you can handle the work. We need strong backs down here loading cargo. Pay is $23 per hour. Shifts run from 6 AM to 10 PM, and you can work up to 8 hours a day. It's hard work, but honest pay. You in?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Dock Worker.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Dock Worker"]>> <<set $homeless = false>> <<goto "DocksJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "Docks">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DocksJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome to the Docks! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Good! Report to the loading bay whenever you're ready to work. Just remember - we work hard down here, so keep up or get out. See you on the docks." </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Position:</strong> Dock Worker</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Pay:</strong> $23 per hour</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Hours:</strong> 6 AM - 10 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #28a745; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "Docks">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BrothelJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #007FFF; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #007FFF 0%, #0059b3 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #007FFF;"> <p style="color: white; font-size: 16px; margin: 0;"> The madam looks you over with an appraising eye, then smiles. "You have the grace and charm we look for here at the Azure Angelfish Lounge. This is a high-end establishment - our clients expect discretion, sophistication, and skill. The work is demanding but the compensation is excellent. Are you interested in joining our team?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin-top: 0;">✅ Accept Position</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Brothel Worker.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I accept\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I accept\"</div>">> <<set $jobs = ["Brothel Worker"]>> <<set $homeless = false>> <<goto "BrothelJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not at this time\"</div>">> <<goto "Brothel">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BrothelJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">✅ Position Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #007FFF 0%, #0059b3 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #007FFF;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome to the Azure Angelfish Lounge </p> <p style="color: white; font-size: 16px; margin: 0;"> "Excellent. You'll start at our professional level and work your way up as you gain experience. Remember - discretion, charm, and skill are what set us apart from other establishments. Make yourself comfortable, and when you're ready, we'll introduce you to your first client." </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Position Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #007FFF;">Position:</strong> Brothel Worker</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #007FFF;">Establishment:</strong> High-end luxury lounge</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #007FFF;">Pay:</strong> Performance-based + tips</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #007FFF;">Benefits:</strong> Level progression system</p> </div> <<link "<div style='background: #007FFF; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "Brothel">> <</link>> </div> <</nobr>>
<<nobr>> <<set _result = setup.spinRoulette($rouletteBetType, $rouletteBetValue, $currentBetAmount)>> <<advancetime 5>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 0 20px #ffd700;">🎡 The Wheel Spins...</h1> <div style="padding: 20px; background: linear-gradient(135deg, #0f4c3a 0%, #1a5c4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(46, 204, 113, 0.3);"> <p style="color: #a8e6cf; font-size: 18px; margin: 0; text-align: center;"> The dealer releases the ball... it bounces and rattles around the spinning wheel... </p> </div> <!-- Spinning Animation Section --> <div style="padding: 40px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid <<if _result.won>>#51cf66<<else>>#c62828<</if>>; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px <<if _result.won>>rgba(81, 207, 102, 0.5)<<else>>rgba(198, 40, 40, 0.5)<</if>>;"> <div style="text-align: center;"> <!-- Winning Number Display --> <div style="display: inline-block; background: <<if _result.winningColor === 'green'>>linear-gradient(135deg, #2ecc71 0%, #1b7943 100%)<<elseif _result.winningColor === 'red'>>linear-gradient(135deg, #c62828 0%, #8b0000 100%)<<else>>linear-gradient(135deg, #1a1a1a 0%, #000000 100%)<</if>>; padding: 30px; border-radius: 50%; margin: 20px 0; box-shadow: 0 0 40px <<if _result.winningColor === 'green'>>rgba(46, 204, 113, 0.8)<<elseif _result.winningColor === 'red'>>rgba(198, 40, 40, 0.8)<<else>>rgba(26, 26, 26, 0.8)<</if>>; border: 5px solid #ffd700;"> <p style="color: white; font-size: 72px; font-weight: bold; margin: 0; text-shadow: 0 0 20px rgba(0,0,0,0.8);"> _result.winningNumber </p> </div> <p style="color: #ffd700; font-size: 24px; font-weight: bold; margin: 20px 0 0 0; text-transform: uppercase; text-shadow: 0 0 15px #ffd700;"> <<if _result.winningColor === "green">>🟢 Green<<elseif _result.winningColor === "red">>🔴 Red<<else>>⚫ Black<</if>> </p> </div> </div> <!-- Result Section --> <<if _result.won>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px rgba(81, 207, 102, 0.5);"> <h2 style="color: #51cf66; text-align: center; margin: 0 0 20px 0; font-size: 32px; text-shadow: 0 0 20px #51cf66;">🎉 WINNER! 🎉</h2> <div style="text-align: center;"> <p style="color: #a8e6cf; font-size: 20px; margin: 0 0 15px 0;"> Your bet: <b style="color: #ffd700;"><<if $rouletteBetType === "color">><<print $rouletteBetValue.toUpperCase()>><<else>>Number _result.winningNumber<</if>></b> </p> <p style="color: #a8e6cf; font-size: 20px; margin: 0 0 15px 0;"> Wagered: <b style="color: #ffd700;">$<<print $currentBetAmount.toLocaleString()>></b> </p> <<if _result.pearlBonus && _result.pearlBonus > 0>> <p style="color: #51cf66; font-size: 36px; font-weight: bold; margin: 0; text-shadow: 0 0 25px #51cf66;"> Won: $<<print (_result.payout + _result.pearlBonus).toLocaleString()>> </p> <p style="color: #a8e6cf; font-size: 16px; margin: 5px 0 0 0; font-style: italic;"> ($<<print _result.payout.toLocaleString()>> base + $<<print _result.pearlBonus.toLocaleString()>> Pearl bonus) </p> <<else>> <p style="color: #51cf66; font-size: 36px; font-weight: bold; margin: 0; text-shadow: 0 0 25px #51cf66;"> Won: $<<print _result.payout.toLocaleString()>> </p> <</if>> <<if $rouletteBetType === "number">> <p style="color: #a8e6cf; font-size: 16px; margin: 15px 0 0 0; font-style: italic;"> (35:1 payout - Incredible luck!) </p> <<else>> <p style="color: #a8e6cf; font-size: 16px; margin: 15px 0 0 0; font-style: italic;"> (2:1 payout - Nice win!) </p> <</if>> <<if _result.luckyBoost>> <div style="background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); padding: 12px; border-radius: 6px; margin-top: 15px; border: 2px solid #ffd700; box-shadow: 0 0 15px rgba(255, 215, 0, 0.5);"> <p style="color: #000; font-size: 15px; font-weight: bold; margin: 0;"> ✨ Your Lucky trait turned the odds in your favor! ✨ </p> </div> <</if>> <<if _result.pearlBonus && _result.pearlBonus > 0>> <div style="background: linear-gradient(135deg, #f5f5f5 0%, #e0e0e0 100%); padding: 12px; border-radius: 6px; margin-top: 15px; border: 2px solid #f5f5f5; box-shadow: 0 0 15px rgba(245, 245, 245, 0.5);"> <p style="color: #333; font-size: 15px; font-weight: bold; margin: 0;"> 🔮 Pearl of Abundance grants +$<<print _result.pearlBonus.toLocaleString()>> bonus! 🔮 </p> <p style="color: #666; font-size: 13px; margin: 5px 0 0 0; font-style: italic;"> (This bonus doesn't count toward your limit) </p> </div> <</if>> </div> <<if _result.kickedOut>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 8px; margin-top: 25px; border: 3px solid #c62828; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(198, 40, 40, 0.5);"> <p style="color: #c62828; font-size: 18px; font-weight: bold; margin: 0 0 10px 0; text-align: center; text-shadow: 0 0 10px #c62828;"> ⚠️ CASINO SECURITY NOTICE ⚠️ </p> <p style="color: #ffcdd2; font-size: 16px; margin: 0; text-align: center;"> You've won $50,000 at roulette. The casino has asked you to take a break. Come back in 30 days! </p> </div> <</if>> </div> <<else>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #c62828; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px rgba(198, 40, 40, 0.5);"> <h2 style="color: #c62828; text-align: center; margin: 0 0 20px 0; font-size: 32px; text-shadow: 0 0 20px #c62828;">❌ Better Luck Next Time</h2> <div style="text-align: center;"> <p style="color: #ffcdd2; font-size: 20px; margin: 0 0 15px 0;"> Your bet: <b style="color: #ffd700;"><<if $rouletteBetType === "color">><<print $rouletteBetValue.toUpperCase()>><<else>>Number <<print $rouletteBetValue>><</if>></b> </p> <p style="color: #ffcdd2; font-size: 20px; margin: 0 0 15px 0;"> Winning result: <b style="color: #ffd700;"><<if _result.winningColor === "green">>🟢 GREEN<<elseif _result.winningColor === "red">>🔴 RED<<else>>⚫ BLACK<</if>> (_result.winningNumber)</b> </p> <p style="color: #c62828; font-size: 36px; font-weight: bold; margin: 0; text-shadow: 0 0 25px #c62828;"> Lost: $<<print $currentBetAmount.toLocaleString()>> </p> <p style="color: #ffcdd2; font-size: 16px; margin: 15px 0 0 0; font-style: italic;"> The house always wins... eventually. </p> <<if _result.unluckyCurse>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 12px; border-radius: 6px; margin-top: 15px; border: 2px solid #c62828; box-shadow: 0 0 15px rgba(198, 40, 40, 0.5);"> <p style="color: #ff6b6b; font-size: 15px; font-weight: bold; margin: 0;"> 💀 Your Unlucky trait cursed what should have been a win! 💀 </p> </div> <</if>> </div> </div> <</if>> <!-- Current Status --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <h3 style="color: #ffd700; margin: 0 0 15px 0; text-align: center;">Your Current Status</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="text-align: center;"> <p style="color: #51cf66; font-size: 24px; font-weight: bold; margin: 0;">$<<print $money.toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Available Cash</p> </div> <div style="text-align: center;"> <p style="color: <<if $rouletteSystem.periodWinnings >= 50000>>#c62828<<elseif $rouletteSystem.periodWinnings >= 25000>>#f39c12<<else>>#51cf66<</if>>; font-size: 24px; font-weight: bold; margin: 0;">$<<print $rouletteSystem.periodWinnings.toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Period Winnings</p> </div> <div style="text-align: center;"> <p style="color: #ffd43b; font-size: 24px; font-weight: bold; margin: 0;">$<<print (50000 - $rouletteSystem.periodWinnings).toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Until 30-Day Ban</p> </div> </div> </div> <!-- Action Buttons --> <div style="text-align: center;"> <<if _result.kickedOut>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #c62828; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #c6282844; margin: 10px;'>🚫 Leave Casino (Banned for 30 Days)</div>">> <<set $currentBetAmount = null>> <<set $forcedGambling = false>> <<goto "Casino">> <</link>> <<elseif $forcedGambling>> <!-- Forced Gambling Mode --> <<if _result.won>> <!-- Won - can leave now --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 16px; margin: 0; font-weight: bold;"> ✓ You won! Your compulsion is satisfied... for now. </p> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #51cf6644; margin: 10px;'>← Leave Casino</div>">> <<set $currentBetAmount = null>> <<set $forcedGambling = false>> <<goto "Casino">> <</link>> <<elseif $money < 100>> <!-- Lost everything - forced to leave --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #c62828;"> <p style="color: #c62828; font-size: 16px; margin: 0; font-weight: bold;"> You don't have enough for the minimum bet... Security escorts you out. </p> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #c62828; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #c6282844; margin: 10px;'>← Leave Casino (Broke)</div>">> <<set $currentBetAmount = null>> <<set $forcedGambling = false>> <<goto "RedLightDistrict">> <</link>> <<else>> <!-- Lost but still have money - must continue --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #ff6b6b;"> <p style="color: #ff6b6b; font-size: 16px; margin: 0; font-weight: bold;"> The addiction grips you... You can't leave until you win or go broke! </p> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #ff6b6b44; margin: 10px;'>🎡 Bet Again (Compelled)</div>">> <<goto "RouletteRoom">> <</link>> <</if>> <<else>> <!-- Normal Mode --> <<if $money >= 100>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #51cf6644; margin: 10px;'>🎰 Bet Again</div>">> <<goto "RouletteRoom">> <</link>> <</if>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44; margin: 10px;'>← Leave Table</div>">> <<set $currentBetAmount = null>> <<goto "Casino">> <</link>> <</if>> </div> </div> <</nobr>>
/* ========================================== * CASINO ROULETTE SYSTEM * ==========================================*/ <<set $rouletteSystem = { periodWinnings: 0, lockoutStartDay: 0, kickedOut: false, lastBetAmount: 0, lastBetType: "", lastBetValue: null }>> /* Check and reset roulette winnings after 30 days */ <<set setup.checkRouletteReset = function() { var v = State.variables; /* Only check if currently kicked out */ if (v.rouletteSystem.kickedOut && v.rouletteSystem.lockoutStartDay > 0) { var daysSinceLockout = v.dayNumber - v.rouletteSystem.lockoutStartDay; if (daysSinceLockout >= 30) { setup.DEBUG && console.log("Resetting roulette winnings - 30 days have passed since lockout"); v.rouletteSystem.periodWinnings = 0; v.rouletteSystem.kickedOut = false; v.rouletteSystem.lockoutStartDay = 0; } } }>> /* Legacy function for compatibility - now just calls checkRouletteReset */ <<set setup.resetRouletteWeeklyWinnings = function() { setup.checkRouletteReset(); }>> /* Check if player can access roulette */ <<set setup.canPlayRoulette = function() { var v = State.variables; /* First check if 30 days have passed since lockout */ setup.checkRouletteReset(); /* Check if kicked out (banned for 30 days after hitting $50k) */ if (v.rouletteSystem.kickedOut) { var daysRemaining = 30 - (v.dayNumber - v.rouletteSystem.lockoutStartDay); if (daysRemaining < 0) daysRemaining = 0; return { canPlay: false, reason: "You've won $50,000 at roulette. The casino has asked you to take a break. Come back in " + daysRemaining + " day" + (daysRemaining === 1 ? "" : "s") + "." }; } /* Check winnings limit ($50,000) */ if (v.rouletteSystem.periodWinnings >= 50000) { /* Start the 30-day timer now */ v.rouletteSystem.kickedOut = true; v.rouletteSystem.lockoutStartDay = v.dayNumber; return { canPlay: false, reason: "You've won $50,000 at roulette. The casino has asked you to take a break. Come back in 30 days." }; } return { canPlay: true }; }>> /* Spin the roulette wheel */ <<set setup.spinRoulette = function(betType, betValue, betAmount) { var v = State.variables; /* Check for Lucky/Unlucky traits */ var hasLucky = (v.mentalTraits && v.mentalTraits.includes("Lucky")) || (v.physicalTraits && v.physicalTraits.includes("Cupid")) || (v.physicalTraits && v.physicalTraits.includes("Cheshire Cat")); var hasSoul = (v.mentalTraits && v.mentalTraits.includes("Soul")) || (v.physicalTraits && v.physicalTraits.includes("Soul")) || (v.skills && v.skills.includes("Soul")); var hasWild = v.mentalTraits && v.mentalTraits.includes("Wild"); var isOriginalBody = !v.lifeSwapOriginalBodyNPC; var hasUnlucky = v.mentalTraits && (v.mentalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")); /* Generate winning number (0-36) */ var winningNumber = random(0, 36); /* Determine color (0 is green, odd is red, even is black) */ var winningColor; if (winningNumber === 0) { winningColor = "green"; } else if (winningNumber % 2 === 1) { winningColor = "red"; } else { winningColor = "black"; } /* Store bet info */ v.rouletteSystem.lastBetAmount = betAmount; v.rouletteSystem.lastBetType = betType; v.rouletteSystem.lastBetValue = betValue; /* Calculate win/loss with trait modifiers */ var won = false; var payout = 0; var naturalWin = false; /* Did they naturally win? */ if (betType === "number") { naturalWin = (winningNumber === betValue); /* Unlucky trait: always lose - force a different number */ if (hasUnlucky) { won = false; naturalWin = false; if (winningNumber === betValue) { var newNumber = random(0, 36); while (newNumber === betValue) { newNumber = random(0, 36); } winningNumber = newNumber; if (winningNumber === 0) { winningColor = "green"; } else if (winningNumber % 2 === 1) { winningColor = "red"; } else { winningColor = "black"; } } } else { if (naturalWin) { won = true; } else if (hasLucky) { /* Lucky trait gives 10% additional chance to force a win */ var luckyRoll = random(1, 100); if (luckyRoll <= 10) { won = true; winningNumber = betValue; if (winningNumber === 0) { winningColor = "green"; } else if (winningNumber % 2 === 1) { winningColor = "red"; } else { winningColor = "black"; } } } } if (won) { payout = betAmount * 35; /* 35:1 payout */ } } else if (betType === "color") { naturalWin = (winningColor === betValue); /* Unlucky trait: always lose - force a different color */ if (hasUnlucky) { won = false; naturalWin = false; if (winningColor === betValue) { var oppositeColor = (betValue === "red") ? "black" : "red"; var greenOrOpposite = random(1, 100); if (greenOrOpposite <= 5) { winningNumber = 0; winningColor = "green"; } else { var validNumbers = []; for (var i = 1; i <= 36; i++) { var checkColor = (i % 2 === 1) ? "red" : "black"; if (checkColor === oppositeColor) { validNumbers.push(i); } } winningNumber = validNumbers[random(0, validNumbers.length - 1)]; winningColor = oppositeColor; } } } else { if (naturalWin) { won = true; } else if (hasLucky) { /* Lucky trait gives 10% additional chance to force a win */ var luckyRoll = random(1, 100); if (luckyRoll <= 10) { won = true; winningColor = betValue; var validNumbers = []; for (var i = 1; i <= 36; i++) { var checkColor = (i % 2 === 1) ? "red" : "black"; if (checkColor === betValue) { validNumbers.push(i); } } if (validNumbers.length > 0) { winningNumber = validNumbers[random(0, validNumbers.length - 1)]; } } } } if (won) { payout = betAmount * 2; /* 1:1 payout (double money) */ } } /* Process result */ if (won) { v.money += payout; var profit = payout - betAmount; /* Net profit from this win */ v.rouletteSystem.periodWinnings += profit; /* Only base profit counts toward limit */ /* Pearl of Abundance bonus: +50% extra money (doesn't count toward limit) */ var pearlBonus = 0; var hasPearl = (v.currentArtifact === "The Pearl of Abundance" || (v.physicalTraits && v.physicalTraits.includes("Naiad"))); if (hasPearl) { pearlBonus = Math.floor(profit * 0.5); /* 50% bonus on profit */ v.money += pearlBonus; /* Add bonus to money WITHOUT adding to period limit */ } /* Check if player needs to be kicked out ($50k period winnings) */ if (v.rouletteSystem.periodWinnings >= 50000) { v.rouletteSystem.kickedOut = true; v.rouletteSystem.lockoutStartDay = v.dayNumber; /* Start 30-day timer */ } } else { v.money -= betAmount; } return { won: won, winningNumber: winningNumber, winningColor: winningColor, payout: payout, kickedOut: (v.rouletteSystem.periodWinnings >= 50000), luckyBoost: (hasLucky && won && !naturalWin), unluckyCurse: (hasUnlucky && !won && naturalWin), pearlBonus: pearlBonus }; }>>
/* ========================================== * SLOT MACHINE SYSTEM * ==========================================*/ <<set $slotMachineSystem = { totalPlays: 0, lastResult: null }>> /* Slot machine spin function with trait and Pearl modifiers */ <<set setup.spinSlotMachine = function() { var v = State.variables; /* Track plays for gambling addiction */ v.slotMachineSystem.totalPlays++; /* Check for traits */ var hasLucky = (v.mentalTraits && v.mentalTraits.includes("Lucky")) || (v.physicalTraits && v.physicalTraits.includes("Cupid")) || (v.physicalTraits && v.physicalTraits.includes("Cheshire Cat")); var hasUnlucky = v.mentalTraits && (v.mentalTraits.includes("Unlucky") || v.mentalTraits.includes("Bad Luck")); var hasPearl = (v.currentArtifact === "The Pearl of Abundance" || (v.physicalTraits && v.physicalTraits.includes("Naiad"))); /* ===== SKILL TREE: Get gambling bonuses ===== */ var slotsWinBonus = 0; var slotsPayoutBonus = 0; if (typeof setup.skillTree !== "undefined" && typeof setup.skillTree.getEffect === "function") { slotsWinBonus = setup.skillTree.getEffect("slotsWinBonus") || 0; slotsPayoutBonus = setup.skillTree.getEffect("slotsPayoutBonus") || 0; } /* Check if player is in beginner phase (first 25 rolls) */ var isBeginnerPhase = (v.slotMachineSystem.totalPlays <= 25); /* Define base odds */ var odds = {}; if (isBeginnerPhase) { /* BEGINNER ODDS: More favorable for first 25 spins */ odds = { nothing: 61.945, /* Decreased by 30 percentage points */ win100: 27.945, /* Increased by 22 percentage points */ win250: 8, /* Increased by 7 percentage points */ win1000: 2, /* Increased by 1 percentage point */ win10000: 0.1, win1000000: 0.01 }; } else { /* NORMAL ODDS: Standard house edge */ odds = { nothing: 91.945, win100: 5.945, win250: 1, win1000: 1, win10000: 0.1, win1000000: 0.01 }; } /* Lucky trait: -10% nothing, +10% to $100 */ if (hasLucky) { odds.nothing = odds.nothing - 10; odds.win100 = odds.win100 + 10; } /* Unlucky trait: impossible to win */ if (hasUnlucky) { odds.nothing = 100; odds.win100 = 0; odds.win250 = 0; odds.win1000 = 0; odds.win10000 = 0; odds.win1000000 = 0; } /* ===== SKILL TREE: Apply win bonus (reduce nothing chance, boost wins) ===== */ if (slotsWinBonus > 0) { /* Each 1% bonus reduces "nothing" by 1% and distributes to wins */ odds.nothing = Math.max(50, odds.nothing - slotsWinBonus); odds.win100 = odds.win100 + (slotsWinBonus * 0.6); /* 60% to $100 */ odds.win250 = odds.win250 + (slotsWinBonus * 0.25); /* 25% to $250 */ odds.win1000 = odds.win1000 + (slotsWinBonus * 0.1); /* 10% to $1000 */ odds.win10000 = odds.win10000 + (slotsWinBonus * 0.04); /* 4% to $10000 */ odds.win1000000 = odds.win1000000 + (slotsWinBonus * 0.01); /* 1% to jackpot */ } /* Roll for result */ var roll = Math.random() * 100; var payout = 0; var symbols = []; /* Determine outcome */ if (roll < odds.win1000000) { payout = 1000000; symbols = ["💎", "💎", "💎"]; } else if (roll < odds.win1000000 + odds.win10000) { payout = 10000; symbols = ["👑", "👑", "👑"]; } else if (roll < odds.win1000000 + odds.win10000 + odds.win1000) { payout = 1000; symbols = ["🍀", "🍀", "🍀"]; } else if (roll < odds.win1000000 + odds.win10000 + odds.win1000 + odds.win250) { payout = 250; symbols = ["🎰", "🎰", "🎰"]; } else if (roll < 100 - odds.nothing) { payout = 100; symbols = ["🍒", "🍒", "🍒"]; } else { payout = 0; /* Random losing combination */ var allSymbols = ["🍒", "🍋", "🍊", "🍇", "⭐", "7️⃣"]; symbols = [ allSymbols[random(0, allSymbols.length - 1)], allSymbols[random(0, allSymbols.length - 1)], allSymbols[random(0, allSymbols.length - 1)] ]; /* Make sure they don't all match */ while (symbols[0] === symbols[1] && symbols[1] === symbols[2]) { symbols[2] = allSymbols[random(0, allSymbols.length - 1)]; } } /* ===== SKILL TREE: Apply payout bonus ===== */ var skillTreePayoutBonus = 0; if (slotsPayoutBonus > 0 && payout > 0) { skillTreePayoutBonus = Math.floor(payout * (slotsPayoutBonus / 100)); } /* Apply Pearl of Abundance bonus (on base payout only) */ var pearlBonus = 0; if (hasPearl && payout > 0) { pearlBonus = Math.floor(payout * 0.5); /* 50% bonus */ } /* Calculate total winnings */ var totalWon = payout + skillTreePayoutBonus + pearlBonus; /* Add winnings to money */ if (totalWon > 0) { v.money += totalWon; } /* Deduct cost (with casino staff discount if applicable) */ var slotCost = setup.getSlotCost(); v.money -= slotCost; /* Check for gambling addiction (25+ plays) */ var gainedAddiction = false; if (v.slotMachineSystem.totalPlays >= 25 && v.mentalTraits && !v.mentalTraits.includes("Gambling Addiction")) { v.mentalTraits.push("Gambling Addiction"); gainedAddiction = true; } /* Store result */ v.slotMachineSystem.lastResult = { symbols: symbols, payout: payout, skillTreePayoutBonus: skillTreePayoutBonus, pearlBonus: pearlBonus, totalWon: totalWon, gainedAddiction: gainedAddiction, slotsWinBonus: slotsWinBonus, slotsPayoutBonus: slotsPayoutBonus }; return v.slotMachineSystem.lastResult; }>> /* Calculate slot machine cost with casino staff discount */ <<set setup.getSlotCost = function() { var v = State.variables; var baseCost = 50; /* Check if player works at the casino (Security Guard or Cocktail Waitress) */ var isCasinoStaff = false; if (v.jobs && (v.jobs.includes("Security Guard") || v.jobs.includes("Cocktail Waitress"))) { isCasinoStaff = true; } /* 5% discount for casino staff */ if (isCasinoStaff) { baseCost = Math.floor(baseCost * 0.95); /* $47 */ } return baseCost; }>> /* Check for forced gambling when entering casino */ <<set setup.checkGamblingAddiction = function() { var v = State.variables; if (v.mentalTraits && v.mentalTraits.includes("Gambling Addiction") && v.money >= 50) { var roll = random(1, 100); if (roll <= 50) { return true; /* Force gambling */ } } return false; }>>
<<nobr>> <<set _result = setup.spinSlotMachine()>> <<advancetime 2>> <!-- Check for jackpot achievement and grant lucky trait --> <<if _result.payout >= 1000000>> <<run setup.achievements.unlock("casino_jackpot")>> <!-- Only grant Lucky if player doesn't have it AND it's not blocked by transformation --> <<set _luckyBlocked = setup.isTraitBlockedByTransformation && setup.isTraitBlockedByTransformation("Lucky", "mental")>> <<if !$mentalTraits.includes("Lucky") && !_luckyBlocked>> <<set $mentalTraits.push("Lucky")>> <<run setup.achievements.unlock("lucky_trait")>> <<set _gainedLucky = true>> <</if>> <</if>> <!-- Check for gambling addiction achievement --> <<if _result.gainedAddiction>> <<run setup.achievements.unlock("gambling_addiction")>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 0 20px #ffd700;">🎰 Spinning...</h1> <div style="padding: 20px; background: linear-gradient(135deg, #0f4c3a 0%, #1a5c4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(46, 204, 113, 0.3);"> <p style="color: #a8e6cf; font-size: 18px; margin: 0; text-align: center;"> The reels spin and click into place... </p> </div> <!-- Slot Machine Result Display --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 40px 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid <<if _result.payout > 0>>#51cf66<<else>>#c62828<</if>>; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px <<if _result.payout > 0>>rgba(81, 207, 102, 0.5)<<else>>rgba(198, 40, 40, 0.5)<</if>>;"> <div style="display: flex; justify-content: center; gap: 20px; margin-bottom: 30px;"> <div style="background: <<if _result.payout > 0>>#1b5e20<<else>>#1a1a1a<</if>>; border: 3px solid <<if _result.payout > 0>>#51cf66<<else>>#667eea<</if>>; border-radius: 10px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 64px; box-shadow: 0 0 30px <<if _result.payout > 0>>rgba(81, 207, 102, 0.5)<<else>>rgba(0,0,0,0.5)<</if>>;"> <span><<print _result.symbols[0]>></span> </div> <div style="background: <<if _result.payout > 0>>#1b5e20<<else>>#1a1a1a<</if>>; border: 3px solid <<if _result.payout > 0>>#51cf66<<else>>#667eea<</if>>; border-radius: 10px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 64px; box-shadow: 0 0 30px <<if _result.payout > 0>>rgba(81, 207, 102, 0.5)<<else>>rgba(0,0,0,0.5)<</if>>;"> <span><<print _result.symbols[1]>></span> </div> <div style="background: <<if _result.payout > 0>>#1b5e20<<else>>#1a1a1a<</if>>; border: 3px solid <<if _result.payout > 0>>#51cf66<<else>>#667eea<</if>>; border-radius: 10px; width: 120px; height: 120px; display: flex; align-items: center; justify-content: center; font-size: 64px; box-shadow: 0 0 30px <<if _result.payout > 0>>rgba(81, 207, 102, 0.5)<<else>>rgba(0,0,0,0.5)<</if>>;"> <span><<print _result.symbols[2]>></span> </div> </div> </div> <!-- Win/Loss Result --> <<if _result.payout > 0>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px rgba(81, 207, 102, 0.5);"> <h2 style="color: #51cf66; text-align: center; margin: 0 0 20px 0; font-size: 32px; text-shadow: 0 0 20px #51cf66;">🎉 WINNER! 🎉</h2> <div style="text-align: center;"> <p style="color: #a8e6cf; font-size: 20px; margin: 0 0 15px 0;"> Cost: <b style="color: #ffd700;">$50</b> </p> <!-- Check if any bonuses apply --> <<set _hasBonuses = (_result.skillTreePayoutBonus > 0) || (_result.pearlBonus > 0)>> <<if _hasBonuses>> <p style="color: #51cf66; font-size: 36px; font-weight: bold; margin: 0; text-shadow: 0 0 25px #51cf66;"> Won: $<<print _result.totalWon.toLocaleString()>> </p> <!-- Breakdown of bonuses --> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin: 15px auto; max-width: 300px; border: 2px solid #333;"> <p style="color: #888; font-size: 14px; margin: 5px 0;">Base: $<<print _result.payout.toLocaleString()>></p> <!-- ===== SKILL TREE: Show payout bonus ===== --> <<if _result.skillTreePayoutBonus > 0>> <p style="color: #CE93D8; font-size: 14px; margin: 5px 0;">⭐ Skill Tree (+<<print _result.slotsPayoutBonus>>%): +$<<print _result.skillTreePayoutBonus.toLocaleString()>></p> <</if>> <<if _result.pearlBonus > 0>> <p style="color: #f5f5f5; font-size: 14px; margin: 5px 0;">🔮 Pearl (+50%): +$<<print _result.pearlBonus.toLocaleString()>></p> <</if>> </div> <<else>> <p style="color: #51cf66; font-size: 36px; font-weight: bold; margin: 0; text-shadow: 0 0 25px #51cf66;"> Won: $<<print _result.payout.toLocaleString()>> </p> <</if>> <p style="color: #51cf66; font-size: 20px; margin: 15px 0 0 0; font-weight: bold;"> Net Profit: $<<print (_result.totalWon - 50).toLocaleString()>> </p> <!-- ===== SKILL TREE: Highlight if skill tree bonus contributed ===== --> <<if _result.skillTreePayoutBonus > 0>> <div style="background: linear-gradient(135deg, #9C27B0 0%, #7B1FA2 100%); padding: 12px; border-radius: 6px; margin-top: 15px; border: 2px solid #CE93D8; box-shadow: 0 0 15px rgba(156, 39, 176, 0.5);"> <p style="color: #E1BEE7; font-size: 15px; font-weight: bold; margin: 0;"> ⭐ Skill Tree Bonus: +$<<print _result.skillTreePayoutBonus.toLocaleString()>>! ⭐ </p> </div> <</if>> <<if _result.pearlBonus > 0>> <div style="background: linear-gradient(135deg, #f5f5f5 0%, #e0e0e0 100%); padding: 12px; border-radius: 6px; margin-top: 15px; border: 2px solid #f5f5f5; box-shadow: 0 0 15px rgba(245, 245, 245, 0.5);"> <p style="color: #333; font-size: 15px; font-weight: bold; margin: 0;"> 🔮 Pearl of Abundance: +$<<print _result.pearlBonus.toLocaleString()>>! 🔮 </p> </div> <</if>> <!-- Lucky trait gained from jackpot --> <<if _gainedLucky>> <div style="background: linear-gradient(135deg, #ffd700 0%, #ffb300 100%); padding: 15px; border-radius: 8px; margin-top: 20px; border: 3px solid #ffd700; box-shadow: 0 0 30px rgba(255, 215, 0, 0.7); animation: pulse 1s infinite;"> <p style="color: #1a1a1a; font-size: 18px; font-weight: bold; margin: 0; text-align: center;"> 🍀 JACKPOT BLESSING! 🍀 </p> <p style="color: #1a1a1a; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> Your incredible luck has blessed you with the <b>Lucky</b> trait! </p> </div> <</if>> </div> </div> <<else>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #c62828; box-shadow: 0 8px 16px rgba(0,0,0,0.6), 0 0 40px rgba(198, 40, 40, 0.5);"> <h2 style="color: #c62828; text-align: center; margin: 0 0 20px 0; font-size: 32px; text-shadow: 0 0 20px #c62828;">❌ No Match</h2> <div style="text-align: center;"> <p style="color: #ffcdd2; font-size: 20px; margin: 0 0 15px 0;"> The symbols don't match... </p> <p style="color: #c62828; font-size: 36px; font-weight: bold; margin: 0; text-shadow: 0 0 25px #c62828;"> Lost: $50 </p> <p style="color: #ffcdd2; font-size: 16px; margin: 15px 0 0 0; font-style: italic;"> Better luck next time! </p> <!-- ===== SKILL TREE: Remind player of their bonuses ===== --> <<if _result.slotsWinBonus > 0>> <p style="color: #CE93D8; font-size: 14px; margin: 15px 0 0 0;"> ⭐ Your skill tree gave you +<<print _result.slotsWinBonus>>% better odds </p> <</if>> </div> </div> <</if>> <!-- Gambling Addiction Warning --> <<if _result.gainedAddiction>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 8px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 107, 107, 0.5);"> <p style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin: 0 0 10px 0; text-align: center; text-shadow: 0 0 10px #ff6b6b;"> ⚠️ GAMBLING ADDICTION ACQUIRED ⚠️ </p> <p style="color: #ffcdd2; font-size: 16px; margin: 0; text-align: center;"> You've played the slots 25 times... You can't stop thinking about the next spin. When you enter the casino with money, you may be compelled to gamble! </p> </div> <</if>> <!-- Current Status --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <h3 style="color: #ffd700; margin: 0 0 15px 0; text-align: center;">Your Current Status</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="text-align: center;"> <p style="color: #51cf66; font-size: 24px; font-weight: bold; margin: 0;">$<<print $money.toLocaleString()>></p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Available Cash</p> </div> <div style="text-align: center;"> <p style="color: #4dabf7; font-size: 24px; font-weight: bold; margin: 0;">$slotMachineSystem.totalPlays</p> <p style="color: #888; font-size: 14px; margin: 5px 0 0 0;">Total Plays</p> </div> </div> </div> <!-- Action Buttons --> <div style="text-align: center;"> <<if $forcedGambling>> <!-- Forced Gambling Mode --> <<if _result.payout > 0>> <!-- Won - can leave now --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 16px; margin: 0; font-weight: bold;"> ✓ You won! Your compulsion is satisfied... for now. </p> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #51cf6644; margin: 10px;'>← Leave Casino</div>">> <<set $forcedGambling = false>> <<goto "Casino">> <</link>> <<elseif $money < 50>> <!-- Lost everything - forced to leave --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #c62828;"> <p style="color: #c62828; font-size: 16px; margin: 0; font-weight: bold;"> You're broke... Security escorts you out. </p> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #c62828; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #c6282844; margin: 10px;'>← Leave Casino (Broke)</div>">> <<set $forcedGambling = false>> <<goto "RedLightDistrict">> <</link>> <<else>> <!-- Lost but still have money - must continue --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #ff6b6b;"> <p style="color: #ff6b6b; font-size: 16px; margin: 0; font-weight: bold;"> The addiction grips you... You can't leave until you win or go broke! </p> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; color: #ff6b6b; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #ff6b6b44; margin: 10px;'>🎰 Spin Again (Compelled)</div>">> <<goto "SlotMachineResult">> <</link>> <</if>> <<else>> <!-- Normal Mode --> <<set _hasGamblingAddiction = $mentalTraits && $mentalTraits.includes("Gambling Addiction")>> <<if $money >= 50>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #51cf66; color: #51cf66; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #51cf6644; margin: 10px;'>🎰 Spin Again</div>">> <<goto "SlotMachineResult">> <</link>> <</if>> <<if _hasGamblingAddiction && $money >= 50 && (!_result || _result.payout <= 0)>> <!-- Addiction won't let them leave on a loss while they still have chips. Once they win a spin (or go broke), the back button reappears. --> <div style="display: inline-block; background: rgba(255, 107, 107, 0.1); padding: 12px 30px; border-radius: 8px; border: 2px solid #ff6b6b; color: #ff6b6b; font-weight: bold; font-size: 14px; margin: 10px;"> 🎲 Your hands won't leave the lever. You need a win before you can walk away. </div> <<else>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44; margin: 10px;'>← Back to Casino</div>">> <<goto "Casino">> <</link>> <</if>> <</if>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center; text-shadow: 0 0 20px #ff6b6b;">🎲 Gambling Compulsion</h1> <<if $money >= 50>> <!-- Has enough money for at least slots - must gamble --> <div style="padding: 20px; background: linear-gradient(135deg, #4a0000 0%, #1a0000 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 30px rgba(255, 107, 107, 0.5);"> <p style="color: #ffcdd2; font-size: 20px; margin: 0; text-align: center; font-weight: bold;"> The casino lights call to you. Your fingers itch. You NEED to play... just one more time... </p> </div> <!-- Gambling Addiction Notice --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 107, 107, 0.5);"> <h2 style="color: #ff6b6b; text-align: center; margin: 0 0 20px 0; font-size: 28px; text-shadow: 0 0 15px #ff6b6b;">⚠️ Your Addiction Compels You ⚠️</h2> <p style="color: #ffcdd2; font-size: 18px; margin: 0 0 20px 0; text-align: center;"> You have $<<print $money.toLocaleString()>> and your gambling addiction has taken hold. You can't leave until you either win something... or lose everything. </p> <p style="color: #ff9e9e; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> Choose your poison... but you MUST play. </p> </div> <!-- Forced Choice --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <h3 style="color: #ffd700; margin: 0 0 20px 0; text-align: center;">What Will It Be?</h3> <div style="text-align: center;"> <!-- Slot Machine Option (Only option for forced gambling) --> <<if $money >= 50>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; color: #ffd700; padding: 25px 50px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(255, 215, 0, 0.5);'>🎰 Slot Machine<br><span style=\"font-size: 14px;\">($50 per spin)</span></div>">> <<set $forcedGambling = true>> <<goto "SlotMachine">> <</link>> <<else>> <div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #444; color: #888; padding: 25px 50px; border-radius: 10px; text-align: center; font-weight: bold; font-size: 20px; cursor: not-allowed; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>🎰 Slot Machine<br><span style="font-size: 14px;">(Need $50)</span></div> <</if>> </div> </div> <<else>> <!-- Not enough money for any game - can leave --> <div style="padding: 20px; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #888; font-size: 20px; margin: 0; text-align: center; font-weight: bold;"> The casino lights flicker... but your empty pockets break the spell. </p> </div> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #888; text-align: center; margin: 0 0 20px 0; font-size: 28px;">💸 Too Broke to Gamble</h2> <p style="color: #888; font-size: 18px; margin: 0 0 20px 0; text-align: center;"> You have $<<print $money.toLocaleString()>>. You don't have enough money to satisfy your gambling addiction... The compulsion fades as reality sets in. </p> <p style="color: #666; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> You need at least $50 to play the slot machines. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44;'>← Leave Casino (Broke)</div>">> <<set $forcedGambling = false>> <<goto "RedLightDistrict">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Bank">> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Bank")>> <<run $visitedLocations.push("Bank")>> <</if>> /* Check if player is a Criminal and arrest them */ <<if $jobs && $jobs.includes("Criminal")>> <<set $arrestedAtStation = true>> <<goto "CaughtByPolice">> <</if>> <!-- Check business hours (8 AM - 5 PM) --> <<set _currentHour = Math.floor($timeInMinutes / 60) % 24>> <<set _isOpen = _currentHour >= 8 && _currentHour < 17>> <!-- Initialize bank system if not exists --> <<if !$bankAccount>> <<set $bankAccount = { hasAccount: false, balance: 0, atmWithdrawalsToday: 0, lastWithdrawDay: 0 }>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #2ecc71; text-align: center; text-shadow: 0 0 20px #2ecc71;">🏦 Sunfish City Bank</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: white; font-size: 18px; margin: 0;"> A modern banking facility with polished marble floors and professional staff behind secure counters. Digital displays show current rates and services. The atmosphere is quiet and professional. </p> </div> <!-- Business Hours Display --> <<set _displayHour = Math.floor($timeInMinutes / 60) % 24>> <<set _displayMinute = $timeInMinutes % 60>> <div style="background: <<if _isOpen>>#2a3a2a<<else>>#3a2020<</if>>; padding: 15px; border-radius: 10px; margin-bottom: 25px; border: 2px solid <<if _isOpen>>#2ecc71<<else>>#c62828<</if>>; text-align: center;"> <p style="color: <<if _isOpen>>#2ecc71<<else>>#ff6b6b<</if>>; font-size: 18px; font-weight: bold; margin: 0 0 5px 0;"> <<if _isOpen>>🟢 OPEN<<else>>🔴 CLOSED<</if>> </p> <p style="color: #aaa; font-size: 14px; margin: 0;"> Business Hours: 8:00 AM - 5:00 PM<br> Current Time: <<if _displayHour === 0>>12<<elseif _displayHour > 12>><<print _displayHour - 12>><<else>><<print _displayHour>><</if>>:<<if _displayMinute < 10>>0<</if>><<print _displayMinute>> <<if _displayHour < 12>>AM<<else>>PM<</if>> </p> </div> <<if !_isOpen>> <!-- Bank Closed Message --> <div style="background: linear-gradient(135deg, #3a2020 0%, #2a1515 100%); padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #c62828; box-shadow: 0 4px 8px rgba(0,0,0,0.4); text-align: center;"> <h2 style="color: #ff6b6b; margin: 0 0 20px 0;">🔒 Bank is Currently Closed</h2> <p style="color: #ff8787; font-size: 16px; margin: 0 0 20px 0;"> The bank is open from <strong>8:00 AM to 5:00 PM</strong>.<br> Please come back during business hours. </p> <div style="background: #2a2a2a; padding: 20px; border-radius: 8px; border: 2px solid #444; margin-bottom: 20px;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">💡 While the Bank is Closed:</h3> <ul style="color: #aaa; text-align: left; line-height: 1.8; font-size: 15px;"> <li>ATMs are available 24/7 throughout the city ($30,000/day limit)</li> <li>Funds in your account are safe and secure</li> <li>Your bank card works for purchases anytime</li> <li>Check your balance via your phone app (coming soon)</li> </ul> </div> <<if $bankAccount && $bankAccount.hasAccount>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #2ecc71; margin-bottom: 20px;"> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">Your Current Balance:</p> <p style="color: #2ecc71; font-size: 28px; font-weight: bold; margin: 0;">$<<print $bankAccount.balance.toLocaleString()>></p> </div> <</if>> </div> <!-- Navigation when closed --> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44;'>← Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <<else>> <!-- Bank is OPEN - Normal Banking Services --> <<if !$bankAccount.hasAccount>> <!-- No Account - Open Account Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(46, 204, 113, 0.3);"> <h2 style="color: #2ecc71; margin: 0 0 20px 0; text-align: center;">💳 Open a Bank Account</h2> <p style="color: #ccc; font-size: 16px; margin: 0 0 15px 0; text-align: center;"> Welcome to Sunfish City Bank! Open an account today and enjoy secure banking services. </p> <div style="background: #2a2a2a; padding: 20px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #333;"> <h3 style="color: #2ecc71; margin: 0 0 15px 0;">Account Benefits:</h3> <ul style="color: #aaa; font-size: 15px; line-height: 1.8;"> <li>✅ Secure storage for your money</li> <li>✅ Pay for purchases with your bank card</li> <li>✅ Earn 5% more from jobs when paid via direct deposit</li> <li>✅ Access ATMs throughout the city ($30,000/day limit)</li> <li>✅ Check balance anytime via phone app</li> <li>✅ Unlimited fee-free withdrawals at bank teller (8 AM - 5 PM)</li> </ul> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #f39c12;"> <p style="color: #f39c12; font-size: 16px; margin: 0; text-align: center; font-weight: bold;"> ⚠️ One-time account opening fee: $250 </p> </div> <div style="text-align: center;"> <<if $money >= 250>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(46, 204, 113, 0.5); cursor: pointer;'>💳 Open Account ($250)</div>">> <<set $money -= 250>> <<set $bankAccount.hasAccount = true>> <<run setup.achievements.unlock("unlock_bank_account")>> <<goto "Bank">> <</link>> <<else>> <div style='display: inline-block; background: #444; color: #888; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; cursor: not-allowed;'> Not Enough Cash </div> <p style="color: #888; font-size: 14px; margin: 10px 0 0 0; font-style: italic;"> You need $<<print (250 - $money).toLocaleString()>> more cash </p> <</if>> </div> </div> <<else>> <!-- Has Account - Banking Services --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(46, 204, 113, 0.3);"> <h2 style="color: #2ecc71; margin: 0 0 20px 0; text-align: center;">Your Account</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px;"> <div style="text-align: center; background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #333;"> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">Cash on Hand</p> <p style="color: #51cf66; font-size: 24px; font-weight: bold; margin: 0;">$<<print $money.toLocaleString()>></p> </div> <div style="text-align: center; background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #333;"> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">Bank Balance</p> <p style="color: #2ecc71; font-size: 24px; font-weight: bold; margin: 0;">$<<print $bankAccount.balance.toLocaleString()>></p> </div> </div> </div> <!-- Deposit Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(77, 171, 247, 0.3);"> <h3 style="color: #4dabf7; margin: 0 0 15px 0;">💰 Deposit Cash</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 15px 0;"> Deposit your cash into your bank account for safekeeping. </p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px;"> <<if $money >= 100>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(77, 171, 247, 0.3);'>$100</div>">> <<set $money -= 100>> <<set $bankAccount.balance += 100>> <<goto "Bank">> <</link>> <<else>> <div style='background: #2a2a2a; border: 2px solid #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>$100</div> <</if>> <<if $money >= 500>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(77, 171, 247, 0.3);'>$500</div>">> <<set $money -= 500>> <<set $bankAccount.balance += 500>> <<goto "Bank">> <</link>> <<else>> <div style='background: #2a2a2a; border: 2px solid #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>$500</div> <</if>> <<if $money >= 1000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(77, 171, 247, 0.3);'>$1,000</div>">> <<set $money -= 1000>> <<set $bankAccount.balance += 1000>> <<goto "Bank">> <</link>> <<else>> <div style='background: #2a2a2a; border: 2px solid #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>$1,000</div> <</if>> <<if $money >= 5000>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(77, 171, 247, 0.3);'>$5,000</div>">> <<set $money -= 5000>> <<set $bankAccount.balance += 5000>> <<goto "Bank">> <</link>> <<else>> <div style='background: #2a2a2a; border: 2px solid #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>$5,000</div> <</if>> <<if $money > 0>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #2ecc71; color: #2ecc71; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(46, 204, 113, 0.3);'>ALL ($<<print $money.toLocaleString()>>)</div>">> <<set $bankAccount.balance += $money>> <<set $money = 0>> <<goto "Bank">> <</link>> <<else>> <div style='background: #2a2a2a; border: 2px solid #444; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>ALL</div> <</if>> </div> </div> <!-- Bank Teller Withdrawal Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(155, 89, 182, 0.3);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">👤 Bank Teller Withdrawal</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 15px 0;"> Withdraw any amount from your account with no fees or daily limits. </p> <<if $bankAccount.balance > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 8px; border: 2px solid #333; margin-bottom: 15px;"> <p style="color: #888; font-size: 14px; margin: 0 0 10px 0;">Enter withdrawal amount:</p> <div style="display: flex; gap: 10px; align-items: stretch;"> <input type="number" id="tellerWithdrawAmount" min="1" @max="$bankAccount.balance" placeholder="Amount" style="flex: 1; padding: 12px; border-radius: 6px; border: 2px solid #9b59b6; background: #1a1a1a; color: white; font-size: 16px; font-weight: bold;"> <button onclick="withdrawFromTeller()" style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; border: none; padding: 12px 30px; border-radius: 6px; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 10px rgba(155, 89, 182, 0.3);"> Withdraw </button> </div> <p style="color: #888; font-size: 12px; margin: 10px 0 0 0; font-style: italic;"> Max: $<<print $bankAccount.balance.toLocaleString()>> • No fees • No limits </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 8px;"> <button onclick="document.getElementById('tellerWithdrawAmount').value = 100" style="background: #2a2a2a; border: 2px solid #666; color: #aaa; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 14px;"> $100 </button> <button onclick="document.getElementById('tellerWithdrawAmount').value = 500" style="background: #2a2a2a; border: 2px solid #666; color: #aaa; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 14px;"> $500 </button> <button onclick="document.getElementById('tellerWithdrawAmount').value = 1000" style="background: #2a2a2a; border: 2px solid #666; color: #aaa; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 14px;"> $1,000 </button> <button onclick="document.getElementById('tellerWithdrawAmount').value = 5000" style="background: #2a2a2a; border: 2px solid #666; color: #aaa; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 14px;"> $5,000 </button> <button onclick="document.getElementById('tellerWithdrawAmount').value = 10000" style="background: #2a2a2a; border: 2px solid #666; color: #aaa; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 14px;"> $10,000 </button> <button @onclick="'document.getElementById(\'tellerWithdrawAmount\').value = ' + $bankAccount.balance" style="background: #2a2a2a; border: 2px solid #2ecc71; color: #2ecc71; padding: 8px; border-radius: 6px; cursor: pointer; font-size: 14px; font-weight: bold;"> ALL </button> </div> <<else>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #666;"> <p style="color: #888; font-size: 15px; margin: 0; text-align: center;"> Your account balance is $0 </p> </div> <</if>> </div> <<script>> window.withdrawFromTeller = function() { const amount = parseInt(document.getElementById('tellerWithdrawAmount').value); const balance = SugarCube.State.variables.bankAccount.balance; if (!amount || amount <= 0) { alert('Please enter a valid amount'); return; } if (amount > balance) { alert('Insufficient funds. Your balance is $' + balance.toLocaleString()); return; } SugarCube.State.variables.bankAccount.balance -= amount; SugarCube.State.variables.money += amount; SugarCube.Engine.play('Bank'); }; <</script>> <!-- ATM Information --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 2px solid #444; margin-bottom: 25px;"> <h3 style="color: #667eea; margin: 0 0 15px 0; text-align: center;">ℹ️ ATM Locations</h3> <p style="color: #aaa; font-size: 14px; text-align: center; margin: 0;"> ATMs are available 24/7 at various locations throughout the city.<br> <span style="color: #ffc107;">Daily limit: $30,000</span> </p> </div> <</if>> <!-- Navigation when open --> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3), 0 0 20px #667eea44;'>← Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <</if>> <!-- NPCs at Bank --> <<set _npcsHere = setup.getNPCsAtLocation("Bank")>> <h2 style="color: #2ecc71;">People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #1e1e1e; padding: 20px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 0 20px #2ecc7133; margin-bottom: 25px;"> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #2ecc71; transition: all 0.3s;"> <<set _relLevel = setup.getRelationshipLevel(_npc.originalName || _npc.name)>> <<set _relColor = setup.getRelationshipColor(_relLevel)>> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;"> <span style="color: #2ecc71; font-weight: bold; font-size: 16px;"><<print _npc.name>></span> <span @style="'color: ' + _relColor + '; font-size: 13px; font-weight: bold;'"> <<print setup.getRelationshipStatus(_npc.originalName || _npc.name)>> </span> </div> <div style="color: #aaa; font-size: 14px; margin-bottom: 12px;"> <div><strong style="color: #2ecc71;">Job:</strong> <<print _npc.job>></div> <<if _npc.primaryPersonality>> <div><strong style="color: #2ecc71;">Personality:</strong> <<print _npc.primaryPersonality>></div> <</if>> </div> <div style="display: flex; gap: 10px; flex-wrap: wrap;"> <<link "<div style='background: #2ecc71; color: black; padding: 8px 15px; border-radius: 6px; font-weight: bold; font-size: 13px; text-align: center; flex: 1; min-width: 80px;'>Talk</div>">> <<set $talkingToNPC = _npc>> <<goto "NPCTalk">> <</link>> <<link "<div style='background: #444; color: #2ecc71; padding: 8px 15px; border-radius: 6px; border: 2px solid #2ecc71; font-weight: bold; font-size: 13px; text-align: center; flex: 1; min-width: 80px;'>Trade</div>">> <<set $tradingWithNPC = _npc>> <<goto "TradeHub">> <</link>> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 2px solid #444; margin-bottom: 25px;"> <p style="color: #888; text-align: center; margin: 0; font-size: 15px;"> No staff members are currently visible in the bank. </p> </div> <</if>> </div> <</nobr>>
/* ========================================== * BANK SYSTEM INITIALIZATION & FUNCTIONS * ========================================== */ /* Initialize bank account structure */ <<if !$bankAccount>> <<set $bankAccount = { hasAccount: false, balance: 0, atmWithdrawalsToday: 0, lastWithdrawDay: 0 }>> <</if>> /* Reset ATM daily withdrawal limit (call this in daily reset) */ <<set setup.resetATMLimit = function() { var v = State.variables; if (v.bankAccount && v.bankAccount.hasAccount) { v.bankAccount.atmWithdrawalsToday = 0; } }>> /* Check if player can afford with cash + bank */ <<set setup.canAffordTotal = function(amount) { var v = State.variables; var totalFunds = v.money; if (v.bankAccount && v.bankAccount.hasAccount) { totalFunds += v.bankAccount.balance; } return totalFunds >= amount; }>> /* Pay with cash first, then bank card if needed */ <<set setup.payAmount = function(amount, cashOnly) { var v = State.variables; cashOnly = cashOnly || false; /* If cash only or no bank account, must pay with cash */ if (cashOnly || !v.bankAccount || !v.bankAccount.hasAccount) { if (v.money >= amount) { v.money -= amount; return { success: true, method: "cash" }; } return { success: false, method: "none" }; } /* Try to pay with cash first */ if (v.money >= amount) { v.money -= amount; return { success: true, method: "cash" }; } /* Not enough cash, try bank card */ if (v.bankAccount.balance >= amount) { v.bankAccount.balance -= amount; return { success: true, method: "card" }; } /* Not enough in either */ return { success: false, method: "none" }; }>> /* Add money - with 5% bonus if has bank account and using credit */ <<set setup.addMoneyWithBonus = function(amount, useCredit) { var v = State.variables; useCredit = useCredit || false; /* If no bank account or useCredit is false, just add to cash */ if (!v.bankAccount || !v.bankAccount.hasAccount || !useCredit) { v.money += amount; return { total: amount, bonus: 0, method: "cash" }; } /* With bank account and credit, add 5% bonus */ var bonus = Math.floor(amount * 0.05); var total = amount + bonus; v.bankAccount.balance += total; return { total: total, bonus: bonus, method: "credit" }; }>> /* Check if player has a bank account */ <<set setup.hasBankAccount = function() { var v = State.variables; return v.bankAccount && v.bankAccount.hasAccount; }>> /* Get total available funds (cash + bank) */ <<set setup.getTotalFunds = function() { var v = State.variables; var total = v.money; if (v.bankAccount && v.bankAccount.hasAccount) { total += v.bankAccount.balance; } return total; }>>
<<nobr>> <!-- Initialize bank account if not exists --> <<if !$bankAccount>> <<set $bankAccount = { hasAccount: false, balance: 0, atmWithdrawalsToday: 0, lastWithdrawDay: 0 }>> <</if>> <div class="bank-app-wrapper"> <div class="bank-app-device"> <div class="bank-app-notch-container"> <div class="bank-app-notch-base"></div> </div> <div class="bank-app-screen"> <div class="bank-app-statusbar"> <span class="status-left"><<= getTimeString()>></span> <span class="status-right">📶 🔋</span> </div> <div class="bank-app-content"> <<if !$bankAccount.hasAccount>> <!-- No Account --> <div style="text-align: center; padding: 60px 30px;"> <div style="font-size: 64px; margin-bottom: 20px;">🏦</div> <h2 style="color: #888; margin: 0 0 15px 0; font-size: 20px;">No Bank Account</h2> <p style="color: #666; font-size: 14px; line-height: 1.6; margin: 0 0 25px 0;"> Visit Sunfish City Bank in Downtown to open an account and access mobile banking. </p> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #333;"> <p style="color: #888; font-size: 13px; margin: 0;"> 💵 Cash on Hand: <span style="color: #51cf66; font-weight: bold;">$<<print $money.toLocaleString()>></span> </p> </div> </div> <<else>> <!-- Has Account --> <div style="padding: 20px;"> <!-- Header --> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 48px; margin-bottom: 10px;">🏦</div> <h2 style="color: #2ecc71; margin: 0; font-size: 18px;">Sunfish City Bank</h2> </div> <!-- Account Balance --> <div style="background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); padding: 25px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.3);"> <p style="color: rgba(255,255,255,0.8); font-size: 12px; margin: 0 0 5px 0; text-transform: uppercase; letter-spacing: 1px;">Account Balance</p> <p style="color: white; font-size: 32px; font-weight: bold; margin: 0;">$<<print $bankAccount.balance.toLocaleString()>></p> </div> <!-- Cash on Hand --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 15px; border: 2px solid #333;"> <p style="color: #888; font-size: 12px; margin: 0 0 5px 0; text-transform: uppercase; letter-spacing: 1px;">Cash on Hand</p> <p style="color: #51cf66; font-size: 24px; font-weight: bold; margin: 0;">$<<print $money.toLocaleString()>></p> </div> <!-- Total Funds --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #333;"> <p style="color: #888; font-size: 12px; margin: 0 0 5px 0; text-transform: uppercase; letter-spacing: 1px;">Total Funds</p> <p style="color: #4dabf7; font-size: 24px; font-weight: bold; margin: 0;">$<<print ($money + $bankAccount.balance).toLocaleString()>></p> </div> <!-- ATM Daily Limit --> <<set _atmUsed = $bankAccount.atmWithdrawalsToday>> <<set _atmRemaining = Math.max(0, 500 - _atmUsed)>> <<set _atmPercent = Math.min(100, (_atmUsed / 500) * 100)>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; border: 2px solid #333;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> <p style="color: #888; font-size: 12px; margin: 0; text-transform: uppercase; letter-spacing: 1px;">ATM Daily Limit</p> <p style="color: #e91e63; font-size: 12px; margin: 0; font-weight: bold;">$<<print _atmRemaining.toLocaleString()>> / $500</p> </div> <div style="background: #1a1a1a; height: 8px; border-radius: 4px; overflow: hidden;"> <div @style="'background: linear-gradient(90deg, #e91e63 0%, #c2185b 100%); height: 100%; width: ' + _atmPercent + '%; transition: width 0.3s;'"></div> </div> <p style="color: #666; font-size: 11px; margin: 8px 0 0 0; font-style: italic;"> <<if _atmRemaining > 0>> Resets daily at midnight <<else>> ⚠️ Daily limit reached - visit bank teller for unlimited withdrawals <</if>> </p> </div> <!-- Quick Info --> <div style="margin-top: 20px; padding: 15px; background: #1a1a1a; border-radius: 8px; border-left: 4px solid #2ecc71;"> <p style="color: #888; font-size: 12px; margin: 0; line-height: 1.6;"> 💡 <strong style="color: #aaa;">Tip:</strong> Earn 5% more from jobs when paid via direct deposit to your account! </p> </div> </div> <</if>> </div> <div class="bank-app-homebtn"></div> </div> </div> </div> <div style="text-align: center; margin-top: 20px;"> [[← Back to Phone|Phone]] </div> <style> .bank-app-wrapper { display: flex; justify-content: center; align-items: center; padding: 20px; min-height: 100vh; background: #0a0a0a; } .bank-app-device { width: 360px; height: 680px; background: #0a0a0a; border-radius: 42px; padding: 6px; box-shadow: 0 25px 50px rgba(0,0,0,0.9); position: relative; display: flex; flex-direction: column; } .bank-app-notch-container { position: absolute; top: -24px; left: 50%; transform: translateX(-50%); z-index: 100; } .bank-app-notch-base { width: 140px; height: 28px; background: #0a0a0a; border-radius: 0 0 18px 18px; } .bank-app-screen { background: #1a1a1a; border-radius: 36px; flex: 1; overflow-y: auto; overflow-x: hidden; display: flex; flex-direction: column; position: relative; } .bank-app-statusbar { display: flex; justify-content: space-between; align-items: center; padding: 32px 20px 12px 20px; font-size: 12px; color: white; font-weight: 600; position: sticky; top: 0; background: #1a1a1a; z-index: 50; } .status-left { text-align: left; flex: 1; } .status-right { text-align: right; flex: 1; } .bank-app-content { flex: 1; overflow-y: auto; } .bank-app-homebtn { width: 110px; height: 4px; background: rgba(255,255,255,0.5); border-radius: 2px; margin: 8px auto 8px auto; } /* Scrollbar styling */ .bank-app-screen::-webkit-scrollbar { width: 6px; } .bank-app-screen::-webkit-scrollbar-track { background: transparent; } .bank-app-screen::-webkit-scrollbar-thumb { background: #333; border-radius: 3px; } .bank-app-screen::-webkit-scrollbar-thumb:hover { background: #444; } </style> <</nobr>>
<<nobr>> <<run Dialog.close()>> <<set $lastPatrolEndTime = setup.getTotalGameMinutes()>> <<set $onPatrol = false>> <<set $patrolBonuses = []>> <<set $patrolPenalties = []>> <<set $lastLocation = "PoliceBreakRoom">> <<goto "PoliceBreakRoom">> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ATM")>> <<run $visitedLocations.push("ATM")>> <</if>> <!-- Check if player has bank account --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<if !_hasBankAccount>> <<goto $lastLocation>> <</if>> <<set _atmLimitRemaining = Math.max(0, 30000 - ($bankAccount.atmWithdrawalsToday || 0))>> <<set _hasATMAccess = _atmLimitRemaining > 0>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4dabf7; text-align: center;">🏧 ATM</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4dabf7;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> A standard ATM terminal. The screen prompts you to insert your card. </p> </div> <!-- Account Summary --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4dabf7; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #4dabf7; margin: 0 0 20px 0; text-align: center;">💳 Account Summary</h2> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px; text-align: center;">Cash on Hand:</p> <p style="color: #51cf66; margin: 0; font-size: 22px; font-weight: bold; text-align: center;"><<print setup.formatMoney($money)>></p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #4dabf7;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px; text-align: center;">Bank Balance:</p> <p style="color: #4dabf7; margin: 0; font-size: 22px; font-weight: bold; text-align: center;"><<print setup.formatMoney($bankAccount.balance)>></p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px; text-align: center;">ATM Limit Today:</p> <p style="color: #ffc107; margin: 0; font-size: 22px; font-weight: bold; text-align: center;"><<print setup.formatMoney(_atmLimitRemaining)>></p> </div> </div> <div style="text-align: center; padding-top: 10px; border-top: 1px solid #444;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Total Funds:</p> <p style="color: #ffd43b; margin: 0; font-size: 26px; font-weight: bold;"><<print setup.formatMoney($money + $bankAccount.balance)>></p> </div> </div> <!-- ATM Withdrawal Interface --> <<if _hasATMAccess && $bankAccount.balance > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 3px solid #4dabf7; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #4dabf7; margin: 0 0 15px 0; text-align: center;">💵 Quick Withdrawal</h3> <p style="color: #51cf66; font-size: 14px; text-align: center; margin: 0 0 20px 0; font-weight: bold;"> ✓ FREE withdrawals - No fees! </p> <!-- Quick Amount Buttons --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; margin-bottom: 20px;"> <<set _quickAmounts = [100, 500, 1000, 5000, 10000]>> <<for _amount range _quickAmounts>> <<capture _amount>> <<set _canWithdraw = $bankAccount.balance >= _amount && _atmLimitRemaining >= _amount>> <<if _canWithdraw>> <<link `"<div style='background: #51cf66; color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 15px rgba(81, 207, 102, 0.4); transition: all 0.3s;'>💰 $" + _amount.toLocaleString() + "<br><span style='font-size: 12px; opacity: 0.9;'>FREE - No Fee!</span></div>"`>> <<set $bankAccount.balance -= _amount>> <<set $money += _amount>> <<set $bankAccount.atmWithdrawalsToday = ($bankAccount.atmWithdrawalsToday || 0) + _amount>> <<goto "ATM">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 15px; border-radius: 8px; text-align: center; font-weight: bold; border: 2px solid #6b4a4a; cursor: not-allowed;'> 💰 $<<print _amount.toLocaleString()>><br><span style='font-size: 12px;'>(Unavailable)</span> </div> <</if>> <</capture>> <</for>> </div> <!-- Max Withdrawal Button --> <<set _maxWithdrawal = Math.min($bankAccount.balance, _atmLimitRemaining)>> <<if _maxWithdrawal > 0>> <div style="text-align: center; padding-top: 15px; border-top: 2px solid #444;"> <<link `"<div style='display: inline-block; background: linear-gradient(135deg, #51cf66 0%, #40a854 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; box-shadow: 0 0 20px rgba(81, 207, 102, 0.4); font-size: 16px;'>💎 Withdraw Maximum<br><span style='font-size: 14px;'>$" + _maxWithdrawal.toLocaleString() + " (FREE!)</span></div>"`>> <<set $bankAccount.balance -= _maxWithdrawal>> <<set $money += _maxWithdrawal>> <<set $bankAccount.atmWithdrawalsToday = ($bankAccount.atmWithdrawalsToday || 0) + _maxWithdrawal>> <<goto "ATM">> <</link>> </div> <</if>> </div> <<elseif !_hasATMAccess>> <div style="background: linear-gradient(135deg, #3a2020 0%, #2a1515 100%); padding: 25px; border-radius: 12px; border: 3px solid #c62828; margin-bottom: 25px; text-align: center;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">🚫 Daily ATM Limit Reached</h3> <p style="color: #ff8787; margin: 0; font-size: 16px;"> You've withdrawn your maximum daily limit of $30,000.<br> Come back tomorrow for more withdrawals! </p> <p style="color: #aaa; margin: 15px 0 0 0; font-size: 14px; font-style: italic;"> Or visit the bank teller during business hours (8 AM - 5 PM) for unlimited fee-free withdrawals. </p> </div> <<elseif $bankAccount.balance <= 0>> <div style="background: linear-gradient(135deg, #3a2020 0%, #2a1515 100%); padding: 25px; border-radius: 12px; border: 3px solid #c62828; margin-bottom: 25px; text-align: center;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">💸 Insufficient Funds</h3> <p style="color: #ff8787; margin: 0; font-size: 16px;"> Your bank account is empty.<br> Visit the bank teller to make a deposit! </p> </div> <</if>> <!-- ATM Information --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 2px solid #444; margin-bottom: 25px;"> <h3 style="color: #4dabf7; margin: 0 0 15px 0; text-align: center;">ℹ️ ATM Information</h3> <div style="color: #aaa; line-height: 1.8;"> <p style="margin: 5px 0;">• <strong style="color: #51cf66;">FREE</strong> withdrawals - no fees!</p> <p style="margin: 5px 0;">• <strong style="color: #51cf66;">$30,000 daily limit</strong> (resets at midnight)</p> <p style="margin: 5px 0;">• Visit the <strong style="color: #4dabf7;">bank teller</strong> (8 AM - 5 PM) for unlimited withdrawals</p> <p style="margin: 5px 0;">• Deposits can only be made at the bank branch</p> <p style="margin: 5px 0;">• All ATMs share the same daily limit</p> </div> </div> <!-- Navigation --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #4dabf7; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>← Go Back</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Casino")>> <<run $visitedLocations.push("Casino")>> <</if>> <<set $lastLocation = "Casino">> <!-- Check if player has bank account --> <<set _hasBankAccount = $bankAccount && $bankAccount.hasAccount>> <<if !_hasBankAccount>> <<goto "Casino">> <</if>> <<set _atmLimitRemaining = Math.max(0, 25000 - ($bankAccount.atmWithdrawalsToday || 0))>> <<set _hasATMAccess = _atmLimitRemaining > 0>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🏧 Casino ATM</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff1493 0%, #c71585 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1493; box-shadow: 0 0 30px rgba(255, 20, 147, 0.4);"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> A sleek ATM terminal glows in hot pink neon. The screen flickers with casino-themed animations. </p> </div> <!-- Account Summary --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff1493; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff1493; margin: 0 0 20px 0; text-align: center;">💳 Account Summary</h2> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px; text-align: center;">Cash on Hand:</p> <p style="color: #51cf66; margin: 0; font-size: 22px; font-weight: bold; text-align: center;"><<print setup.formatMoney($money)>></p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #667eea;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px; text-align: center;">Bank Balance:</p> <p style="color: #667eea; margin: 0; font-size: 22px; font-weight: bold; text-align: center;"><<print setup.formatMoney($bankAccount.balance)>></p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ff1493;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px; text-align: center;">ATM Limit Today:</p> <p style="color: #ff1493; margin: 0; font-size: 22px; font-weight: bold; text-align: center;"><<print setup.formatMoney(_atmLimitRemaining)>></p> </div> </div> <div style="text-align: center; padding-top: 10px; border-top: 1px solid #444;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Total Funds:</p> <p style="color: #ffd43b; margin: 0; font-size: 26px; font-weight: bold;"><<print setup.formatMoney($money + $bankAccount.balance)>></p> </div> </div> <!-- ATM Withdrawal Interface --> <<if _hasATMAccess && $bankAccount.balance > 0>> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 3px solid #ff1493; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff1493; margin: 0 0 15px 0; text-align: center;">💵 Quick Withdrawal</h3> <p style="color: #51cf66; font-size: 14px; text-align: center; margin: 0 0 20px 0; font-weight: bold;"> ✓ FREE withdrawals - No fees! </p> <!-- Quick Amount Buttons --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px; margin-bottom: 20px;"> <<set _quickAmounts = [100, 500, 1000, 5000, 10000]>> <<for _amount range _quickAmounts>> <<capture _amount>> <<set _canWithdraw = $bankAccount.balance >= _amount && _atmLimitRemaining >= _amount>> <<if _canWithdraw>> <<link `"<div style='background: linear-gradient(135deg, #51cf66 0%, #40a854 100%); color: white; padding: 15px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 0 15px rgba(81, 207, 102, 0.4); transition: all 0.3s;'>💰 $" + _amount.toLocaleString() + "<br><span style='font-size: 12px; opacity: 0.9;'>FREE - No Fee!</span></div>"`>> <<set $bankAccount.balance -= _amount>> <<set $money += _amount>> <<set $bankAccount.atmWithdrawalsToday = ($bankAccount.atmWithdrawalsToday || 0) + _amount>> <<goto "CasinoATM">> <</link>> <<else>> <div style='background: #4a2a2a; color: #c9a8a8; padding: 15px; border-radius: 8px; text-align: center; font-weight: bold; border: 2px solid #6b4a4a; cursor: not-allowed;'> 💰 $<<print _amount.toLocaleString()>><br><span style='font-size: 12px;'>(Unavailable)</span> </div> <</if>> <</capture>> <</for>> </div> <!-- Max Withdrawal Button --> <<set _maxWithdrawal = Math.min($bankAccount.balance, _atmLimitRemaining)>> <<if _maxWithdrawal > 0>> <div style="text-align: center; padding-top: 15px; border-top: 2px solid #444;"> <<link `"<div style='display: inline-block; background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 15px 40px; border-radius: 10px; font-weight: bold; box-shadow: 0 0 20px rgba(255, 215, 0, 0.5); font-size: 16px;'>💎 Withdraw Maximum<br><span style='font-size: 14px;'>$" + _maxWithdrawal.toLocaleString() + " (FREE!)</span></div>"`>> <<set $bankAccount.balance -= _maxWithdrawal>> <<set $money += _maxWithdrawal>> <<set $bankAccount.atmWithdrawalsToday = ($bankAccount.atmWithdrawalsToday || 0) + _maxWithdrawal>> <<goto "CasinoATM">> <</link>> </div> <</if>> </div> <<elseif !_hasATMAccess>> <div style="background: linear-gradient(135deg, #3a2020 0%, #2a1515 100%); padding: 25px; border-radius: 12px; border: 3px solid #c62828; margin-bottom: 25px; text-align: center;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">🚫 Daily ATM Limit Reached</h3> <p style="color: #ff8787; margin: 0; font-size: 16px;"> You've withdrawn your maximum daily limit of $25,000.<br> Come back tomorrow for more withdrawals! </p> <p style="color: #aaa; margin: 15px 0 0 0; font-size: 14px; font-style: italic;"> Or visit the bank teller during business hours (8 AM - 5 PM) for unlimited withdrawals. </p> </div> <<elseif $bankAccount.balance <= 0>> <div style="background: linear-gradient(135deg, #3a2020 0%, #2a1515 100%); padding: 25px; border-radius: 12px; border: 3px solid #c62828; margin-bottom: 25px; text-align: center;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">💸 Insufficient Funds</h3> <p style="color: #ff8787; margin: 0; font-size: 16px;"> Your bank account is empty.<br> Visit the bank during business hours (8 AM - 5 PM) to make a deposit! </p> </div> <</if>> <!-- ATM Information --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 2px solid #444; margin-bottom: 25px;"> <h3 style="color: #ff1493; margin: 0 0 15px 0; text-align: center;">ℹ️ ATM Information</h3> <div style="color: #aaa; line-height: 1.8;"> <p style="margin: 5px 0;">• <strong style="color: #51cf66;">FREE</strong> withdrawals - no fees!</p> <p style="margin: 5px 0;">• <strong style="color: #ff1493;">$25,000 daily limit</strong> (resets at midnight)</p> <p style="margin: 5px 0;">• Visit the <strong style="color: #667eea;">bank teller</strong> (8 AM - 5 PM) for unlimited withdrawals</p> <p style="margin: 5px 0;">• Deposits can only be made at the bank branch during business hours</p> <p style="margin: 5px 0;">• ATMs are available 24/7 for your convenience</p> </div> </div> <!-- Navigation --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ffd700 0%, #d4af37 100%); color: #000; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>← Back to Casino</div>">> <<goto "Casino">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- WorkCompleteTraitResult - Shows result after player chooses to accept or decline trait swap --> <<set _pendingTrait = $pendingWorkTrait>> <<set _conflictingTrait = $pendingWorkTraitConflict>> <<set _gainedWorkTraitName = _pendingTrait ? _pendingTrait.name : "">> <<set _gainedWorkTraitType = _pendingTrait ? _pendingTrait.type : "">> <!-- Process the player's choice --> <<if $workTraitSwapped && _pendingTrait>> <!-- Player chose to replace trait --> <<if _gainedWorkTraitType === "physical">> <<set $physicalTraits.delete(_conflictingTrait)>> <<if !$physicalTraits.includes(_gainedWorkTraitName)>> <<set $physicalTraits.push(_gainedWorkTraitName)>> <</if>> <<elseif _gainedWorkTraitType === "mental">> <<set $mentalTraits.delete(_conflictingTrait)>> <<if !$mentalTraits.includes(_gainedWorkTraitName)>> <<set $mentalTraits.push(_gainedWorkTraitName)>> <</if>> <</if>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #28a745 0%, #20c997 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 6px 12px rgba(0,0,0,0.4); text-align: center; border: 2px solid #28a745;"> <h1 style="color: white; margin: 0 0 10px 0; font-size: 36px;">✅ Shift Complete!</h1> <p style="color: white; margin: 0; font-size: 18px;">You've finished your shift as a <<print $lastWorkJob>></p> </div> <!-- Show trait change result --> <<if $workTraitSwapped && _pendingTrait>> <!-- Trait was replaced --> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 25px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(155, 89, 182, 0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: white; margin: 0 0 15px 0;">🔄 Trait Replaced!</h2> <p style="color: #ffd; font-size: 18px; margin: 0 0 10px 0;"> You've replaced <strong style="color: #ff6b6b;"><<print _conflictingTrait>></strong><br> with <strong style="color: #51cf66;"><<print _gainedWorkTraitName>></strong> </p> <p style="color: #ccc; font-size: 14px; margin: 0;"> <<if _gainedWorkTraitType === "mental">> (Mental Trait) <<elseif _gainedWorkTraitType === "physical">> (Physical Trait) <</if>> </p> </div> <!-- Transformation text for the swap --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; text-align: center;">🔄 Transformation</h3> <<if _gainedWorkTraitType === "mental">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #764ba2;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<set _transformText = "">> <<if typeof setup.getMutuallyExclusiveSwapText === "function">> <<set _transformText = setup.getMutuallyExclusiveSwapText(_conflictingTrait, _gainedWorkTraitName)>> <</if>> <<if _transformText && _transformText.length > 0>> <<print _transformText>> <<else>> The demands of your work have gradually shifted your personality. Where once you were <strong><<print _conflictingTrait>></strong>, you now find yourself becoming increasingly <strong><<print _gainedWorkTraitName>></strong>. The change feels natural, as if this was always who you were meant to be. <</if>> </p> </div> <<elseif _gainedWorkTraitType === "physical">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #28a745;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<set _transformText = "">> <<if typeof setup.getMutuallyExclusiveSwapText === "function">> <<set _transformText = setup.getMutuallyExclusiveSwapText(_conflictingTrait, _gainedWorkTraitName)>> <</if>> <<if _transformText && _transformText.length > 0>> <<print _transformText>> <<else>> The physical nature of your work has reshaped your body. Your <strong><<print _conflictingTrait>></strong> form has transformed, and you now possess a more <strong><<print _gainedWorkTraitName>></strong> physique. You catch your reflection and barely recognize the changes. <</if>> </p> </div> <</if>> </div> <<else>> <!-- Player kept their current trait --> <div style="background: linear-gradient(135deg, #6c757d 0%, #495057 100%); padding: 25px; border-radius: 12px; border: 3px solid #6c757d; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px; text-align: center;"> <h2 style="color: white; margin: 0 0 15px 0;">🛡️ Trait Preserved</h2> <p style="color: #ddd; font-size: 16px; margin: 0;"> You resisted the change and kept your <strong style="color: #ffd43b;"><<print _conflictingTrait>></strong> trait. </p> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0; font-style: italic;"> The potential for <strong><<print _gainedWorkTraitName>></strong> fades away... </p> </div> <</if>> <!-- Include earnings summary --> <<include "WorkCompleteEarnings">> </div> <!-- Clean up temporary variables --> <<unset $pendingWorkTrait>> <<unset $pendingWorkTraitConflict>> <<unset $workTraitSwapped>> <<set $lastWorkProcessed = false>> <</nobr>>
<<nobr>> <!-- Earnings Display Section --> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #28a745; margin-top: 0; font-size: 24px; border-bottom: 3px solid #28a745; padding-bottom: 10px;">💰 Earnings</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-top: 15px;"> <!-- Base Earnings --> <div style="display: flex; justify-content: space-between; margin-bottom: 10px;"> <span style="color: #ccc;">Base Pay ($lastWorkJob - $lastWorkHours hours):</span> <span style="color: #51cf66; font-weight: bold;">$<<print $lastWorkBaseEarnings>></span> </div> <!-- Pearl Bonus if active --> <<if $lastWorkPearlActive>> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; padding: 8px; background: #2a1a3a; border-radius: 6px; border: 1px solid #9b59b6;"> <span style="color: #d4a5ff;">🦪 Pearl of Abundance (+50%):</span> <span style="color: #d4a5ff; font-weight: bold;">+$<<print $lastWorkPearlBonus>></span> </div> <</if>> <!-- ===== SKILL TREE: Hourly Pay Bonus Display ===== --> <<if $lastWorkSkillTreeBonus && $lastWorkSkillTreeBonus > 0>> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; padding: 8px; background: #1a2a1a; border-radius: 6px; border: 1px solid #9C27B0;"> <span style="color: #CE93D8;">⭐ Skill Tree Bonus (+<<print setup.skillTree.getEffect("hourlyPayBonus")>>%):</span> <span style="color: #CE93D8; font-weight: bold;">+$<<print $lastWorkSkillTreeBonus>></span> </div> <</if>> <!-- ===== BUFF: Food Money Bonus Display ===== --> <<if $lastWorkFoodMoneyBonus && $lastWorkFoodMoneyBonus > 0>> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; padding: 8px; background: #2a2a1a; border-radius: 6px; border: 1px solid #f59f00;"> <span style="color: #ffd43b;">🍽️ Food Buff Bonus:</span> <span style="color: #ffd43b; font-weight: bold;">+$<<print $lastWorkFoodMoneyBonus>></span> </div> <</if>> <!-- Bank Direct Deposit if applicable --> <<if $lastWorkHasBankAccount>> <div style="border-top: 2px solid #444; margin: 15px 0; padding-top: 15px;"> <div style="display: flex; justify-content: space-between; margin-bottom: 10px;"> <span style="color: #ccc;">Subtotal:</span> <span style="color: #51cf66; font-weight: bold;">$<<print $lastWorkBaseEarnings + ($lastWorkPearlBonus || 0) + ($lastWorkSkillTreeBonus || 0) + ($lastWorkFoodMoneyBonus || 0)>></span> </div> <div style="display: flex; justify-content: space-between; margin-bottom: 10px; padding: 8px; background: #1a2a3a; border-radius: 6px; border: 1px solid #17a2b8;"> <span style="color: #4dabf7;">🏦 Direct Deposit Bonus (+5%):</span> <span style="color: #4dabf7; font-weight: bold;">+$<<print $lastWorkCreditBonus>></span> </div> </div> <div style="border-top: 2px solid #28a745; margin-top: 15px; padding-top: 15px;"> <div style="display: flex; justify-content: space-between;"> <span style="color: #28a745; font-size: 18px; font-weight: bold;">Total Deposited to Bank:</span> <span style="color: #28a745; font-size: 20px; font-weight: bold;">$<<print $lastWorkTotalDeposited>></span> </div> <p style="color: #888; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> Bank Balance: $<<print $bankAccount.balance>> </p> </div> <<else>> <div style="border-top: 2px solid #28a745; margin-top: 15px; padding-top: 15px;"> <div style="display: flex; justify-content: space-between;"> <span style="color: #28a745; font-size: 18px; font-weight: bold;">Total Cash Received:</span> <span style="color: #28a745; font-size: 20px; font-weight: bold;">$<<print $lastWorkBaseEarnings + ($lastWorkPearlBonus || 0) + ($lastWorkSkillTreeBonus || 0) + ($lastWorkFoodMoneyBonus || 0)>></span> </div> <p style="color: #888; font-size: 14px; margin: 10px 0 0 0; text-align: center;"> Cash on Hand: $<<print $money>> </p> </div> <div style="background: #3a3a1a; padding: 12px; border-radius: 6px; margin-top: 15px; border: 1px solid #ffc107;"> <p style="color: #ffc107; margin: 0; font-size: 14px; text-align: center;"> 💡 Open a bank account for a 5% direct deposit bonus! </p> </div> <</if>> </div> </div> <!-- Continue Button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>Continue</div>">> <<set $lastWorkTraitChanges = []>> <<set $lastWorkProcessed = false>> <<set $lastWorkPaymentHandled = false>> <<goto $lastLocation || "Downtown">> <</link>> </div> <</nobr>>
/* ============================================== */ /* DREAM STATE CHARACTER CREATION SYSTEM */ /* ============================================== */ /* Initialize Dream State Variables */ <<set setup.initializeDreamState = function() { var v = State.variables; /* Starting trade points */ v.dreamTradePoints = 150; v.dreamStartingPoints = 150; /* Player's dream selections (before finalization) */ v.dreamPlayer = { firstName: "Water", lastName: "Bottle", gender: null, bodyParts: { gender: null, chest: null, butt: null, genitals: null }, appearance: { skinTone: "pale", hairColor: "Black", hairLength: "short", age: "Adult" }, physicalTraits: [], mentalTraits: [], skills: [], negativeTraits: [] /* Negative traits taken for extra points */ }; /* Track completed trades (for undo functionality) */ v.dreamTradeHistory = []; /* Initialize dream NPCs */ v.dreamNPCs = []; return true; }>> /* Create Dream NPC (simplified version without stats) */ <<set setup.createDreamNPC = function(config) { var hairLengthTrait = config.hairLength === "short" ? "Short Hair" : "Long Hair"; var allPhysicalTraits = config.physicalTraits ? config.physicalTraits.slice() : []; if (!allPhysicalTraits.includes(hairLengthTrait)) { allPhysicalTraits.push(hairLengthTrait); } var npc = { name: config.name, gender: config.gender, bodyParts: { gender: config.gender, chest: config.chest || "flat", butt: config.butt || "flat", genitals: config.genitals || (config.gender === "male" ? "penis" : "vagina") }, appearance: { skinTone: config.skinTone || "pale", hairColor: config.hairColor || "Black", hairLength: config.hairLength || "short", age: config.age || "Adult" }, physicalTraits: allPhysicalTraits, mentalTraits: config.mentalTraits || [], skills: config.skills || [], jobs: config.jobs || [], isDreamNPC: true /* Flag to identify dream NPCs */ }; return npc; }>> /* Initialize the 3 Dream NPCs */ <<set setup.initializeDreamNPCs = function() { var v = State.variables; v.dreamNPCs = []; /* NPC 1: Bilian Asstown */ v.dreamNPCs.push(setup.createDreamNPC({ name: "Bilian Asstown", gender: "male", chest: "medium", butt: "large", genitals: "penis", skinTone: "pale", hairColor: "Platinum Blonde", hairLength: "long", age: "Adult", physicalTraits: ["Detail-Oriented", "Pierced", "Quick", "Sarcastic"], mentalTraits: ["Analytical", "Charming", "Direct", "Outgoing", "Sly", "Witty", "Unlucky", "Unskilled"], skills: ["Quick Learner", "Cleaning", "Dancing", "Driving", "Guitar", "Hair Styling", "High Heels Proficient", "Makeup", "Modeling", "Piano"], jobs: [] })); /* NPC 2: Placeholder (to be defined later) */ /* v.dreamNPCs.push(setup.createDreamNPC({...})); */ /* NPC 3: Placeholder (to be defined later) */ /* v.dreamNPCs.push(setup.createDreamNPC({...})); */ return v.dreamNPCs; }>> /* Calculate the trade value of an item (uses existing getTraitValue) */ <<set setup.getDreamTradeValue = function(type, name, size) { /* Use existing trait value system */ return setup.getTraitValue(type, name, size); }>> /* Calculate total value of player's current dream selections */ <<set setup.calculateDreamPlayerValue = function() { var v = State.variables; var dp = v.dreamPlayer; var totalValue = 0; /* Body parts */ if (dp.bodyParts.chest) { totalValue += setup.getDreamTradeValue("bodyPart", "chest", dp.bodyParts.chest); } if (dp.bodyParts.butt) { totalValue += setup.getDreamTradeValue("bodyPart", "butt", dp.bodyParts.butt); } if (dp.bodyParts.genitals) { totalValue += setup.getDreamTradeValue("bodyPart", "genitals", dp.bodyParts.genitals); } /* Physical traits */ dp.physicalTraits.forEach(function(trait) { totalValue += setup.getDreamTradeValue("physical", trait); }); /* Mental traits */ dp.mentalTraits.forEach(function(trait) { totalValue += setup.getDreamTradeValue("mental", trait); }); /* Skills */ dp.skills.forEach(function(skill) { totalValue += setup.getDreamTradeValue("skill", skill); }); return totalValue; }>> /* Get value of a specific item from dream NPC */ <<set setup.getDreamNPCItemValue = function(npc, type, item) { if (type === "bodyPart") { var size = npc.bodyParts[item]; return setup.getDreamTradeValue("bodyPart", item, size); } else if (type === "physical") { return setup.getDreamTradeValue("physical", item); } else if (type === "mental") { return setup.getDreamTradeValue("mental", item); } else if (type === "skill") { return setup.getDreamTradeValue("skill", item); } else if (type === "name") { return 50; /* Fixed value for names */ } else if (type === "appearance") { return 10; /* Fixed value for appearance items */ } return 0; }>> /* Execute a dream trade */ <<set setup.executeDreamTrade = function(npcIndex, playerOffer, npcOffer) { var v = State.variables; var npc = v.dreamNPCs[npcIndex]; var dp = v.dreamPlayer; /* Calculate values */ var playerOfferValue = 0; var npcOfferValue = 0; /* Calculate player offer value */ playerOffer.forEach(function(item) { if (item.type === "points") { playerOfferValue += item.value; } else { playerOfferValue += setup.getDreamNPCItemValue(dp, item.type, item.name); } }); /* Calculate NPC offer value */ npcOffer.forEach(function(item) { npcOfferValue += setup.getDreamNPCItemValue(npc, item.type, item.name); }); /* Check if trade is valid (player must offer equal or greater value) */ if (playerOfferValue < npcOfferValue) { return { success: false, reason: "Insufficient value offered" }; } /* Record the trade for undo */ var tradeRecord = { npcIndex: npcIndex, npcName: npc.name, playerOffer: JSON.parse(JSON.stringify(playerOffer)), npcOffer: JSON.parse(JSON.stringify(npcOffer)), playerOfferValue: playerOfferValue, npcOfferValue: npcOfferValue, timestamp: Date.now() }; /* Execute the trade */ /* Remove from player, add to NPC */ playerOffer.forEach(function(item) { if (item.type === "points") { v.dreamTradePoints -= item.value; } else if (item.type === "bodyPart") { /* Swap body parts */ var playerValue = dp.bodyParts[item.name]; tradeRecord.playerOriginal = tradeRecord.playerOriginal || {}; tradeRecord.playerOriginal[item.name] = playerValue; } else if (item.type === "physical") { var idx = dp.physicalTraits.indexOf(item.name); if (idx > -1) dp.physicalTraits.splice(idx, 1); } else if (item.type === "mental") { var idx = dp.mentalTraits.indexOf(item.name); if (idx > -1) dp.mentalTraits.splice(idx, 1); } else if (item.type === "skill") { var idx = dp.skills.indexOf(item.name); if (idx > -1) dp.skills.splice(idx, 1); } else if (item.type === "name") { tradeRecord.playerOriginalName = { firstName: dp.firstName, lastName: dp.lastName }; } }); /* Add to player, remove from NPC */ npcOffer.forEach(function(item) { if (item.type === "bodyPart") { var npcValue = npc.bodyParts[item.name]; /* Store NPC's original for undo */ tradeRecord.npcOriginal = tradeRecord.npcOriginal || {}; tradeRecord.npcOriginal[item.name] = npcValue; /* Swap */ var temp = dp.bodyParts[item.name]; dp.bodyParts[item.name] = npcValue; npc.bodyParts[item.name] = temp; } else if (item.type === "physical") { if (!dp.physicalTraits.includes(item.name)) { dp.physicalTraits.push(item.name); } var idx = npc.physicalTraits.indexOf(item.name); if (idx > -1) npc.physicalTraits.splice(idx, 1); } else if (item.type === "mental") { if (!dp.mentalTraits.includes(item.name)) { dp.mentalTraits.push(item.name); } var idx = npc.mentalTraits.indexOf(item.name); if (idx > -1) npc.mentalTraits.splice(idx, 1); } else if (item.type === "skill") { if (!dp.skills.includes(item.name)) { dp.skills.push(item.name); } var idx = npc.skills.indexOf(item.name); if (idx > -1) npc.skills.splice(idx, 1); } else if (item.type === "name") { /* Parse NPC name */ var nameParts = npc.name.split(" "); if (item.which === "first") { dp.firstName = nameParts[0]; npc.name = tradeRecord.playerOriginalName.firstName + " " + nameParts.slice(1).join(" "); } else if (item.which === "last") { dp.lastName = nameParts.slice(1).join(" "); npc.name = nameParts[0] + " " + tradeRecord.playerOriginalName.lastName; } else if (item.which === "full") { dp.firstName = nameParts[0]; dp.lastName = nameParts.slice(1).join(" "); npc.name = tradeRecord.playerOriginalName.firstName + " " + tradeRecord.playerOriginalName.lastName; } } else if (item.type === "appearance") { var npcValue = npc.appearance[item.name]; tradeRecord.npcOriginalAppearance = tradeRecord.npcOriginalAppearance || {}; tradeRecord.npcOriginalAppearance[item.name] = npcValue; tradeRecord.playerOriginalAppearance = tradeRecord.playerOriginalAppearance || {}; tradeRecord.playerOriginalAppearance[item.name] = dp.appearance[item.name]; /* Swap appearance */ var temp = dp.appearance[item.name]; dp.appearance[item.name] = npcValue; npc.appearance[item.name] = temp; /* Handle hair length trait */ if (item.name === "hairLength") { /* Remove old hair length trait */ var oldTrait = temp === "short" ? "Short Hair" : "Long Hair"; var newTrait = npcValue === "short" ? "Short Hair" : "Long Hair"; var oldIdx = dp.physicalTraits.indexOf(oldTrait); if (oldIdx > -1) dp.physicalTraits.splice(oldIdx, 1); if (!dp.physicalTraits.includes(newTrait)) { dp.physicalTraits.push(newTrait); } } } else if (item.type === "job") { if (!dp.jobs) dp.jobs = []; if (!dp.jobs.includes(item.name)) { dp.jobs.push(item.name); } var idx = npc.jobs.indexOf(item.name); if (idx > -1) npc.jobs.splice(idx, 1); } }); /* Refund excess points */ var excessPoints = playerOfferValue - npcOfferValue; if (excessPoints > 0) { v.dreamTradePoints += excessPoints; tradeRecord.refundedPoints = excessPoints; } /* Save trade to history */ v.dreamTradeHistory.push(tradeRecord); return { success: true, playerOfferValue: playerOfferValue, npcOfferValue: npcOfferValue, refundedPoints: excessPoints, tradeIndex: v.dreamTradeHistory.length - 1 }; }>> /* Undo a dream trade */ <<set setup.undoDreamTrade = function(tradeIndex) { var v = State.variables; if (tradeIndex < 0 || tradeIndex >= v.dreamTradeHistory.length) { return { success: false, reason: "Invalid trade index" }; } var trade = v.dreamTradeHistory[tradeIndex]; var npc = v.dreamNPCs[trade.npcIndex]; var dp = v.dreamPlayer; /* Reverse the trade */ /* Return points spent */ trade.playerOffer.forEach(function(item) { if (item.type === "points") { v.dreamTradePoints += item.value; } }); /* Remove refunded points */ if (trade.refundedPoints) { v.dreamTradePoints -= trade.refundedPoints; } /* Reverse body part swaps */ if (trade.npcOriginal) { for (var partName in trade.npcOriginal) { /* Swap back */ var temp = dp.bodyParts[partName]; dp.bodyParts[partName] = npc.bodyParts[partName]; npc.bodyParts[partName] = temp; } } /* Reverse appearance swaps */ if (trade.npcOriginalAppearance) { for (var appName in trade.npcOriginalAppearance) { var temp = dp.appearance[appName]; dp.appearance[appName] = npc.appearance[appName]; npc.appearance[appName] = temp; /* Handle hair length trait */ if (appName === "hairLength") { var oldTrait = dp.appearance[appName] === "short" ? "Short Hair" : "Long Hair"; var newTrait = npc.appearance[appName] === "short" ? "Short Hair" : "Long Hair"; /* Remove current, add back original */ var idx = dp.physicalTraits.indexOf(newTrait); if (idx > -1) dp.physicalTraits.splice(idx, 1); if (!dp.physicalTraits.includes(oldTrait)) { dp.physicalTraits.push(oldTrait); } } } } /* Reverse name swap */ if (trade.playerOriginalName) { var currentPlayerFirst = dp.firstName; var currentPlayerLast = dp.lastName; /* Find which name parts were traded */ trade.npcOffer.forEach(function(item) { if (item.type === "name") { if (item.which === "first" || item.which === "full") { dp.firstName = trade.playerOriginalName.firstName; } if (item.which === "last" || item.which === "full") { dp.lastName = trade.playerOriginalName.lastName; } } }); /* Restore NPC name */ var npcNameParts = npc.name.split(" "); /* This is complex - simplified version */ npc.name = trade.npcOffer.find(function(i) { return i.type === "name"; }) ? (dp.firstName !== trade.playerOriginalName.firstName ? currentPlayerFirst : npcNameParts[0]) + " " + (dp.lastName !== trade.playerOriginalName.lastName ? currentPlayerLast : npcNameParts.slice(1).join(" ")) : npc.name; } /* Return traits to NPC, remove from player */ trade.npcOffer.forEach(function(item) { if (item.type === "physical") { var idx = dp.physicalTraits.indexOf(item.name); if (idx > -1) dp.physicalTraits.splice(idx, 1); if (!npc.physicalTraits.includes(item.name)) { npc.physicalTraits.push(item.name); } } else if (item.type === "mental") { var idx = dp.mentalTraits.indexOf(item.name); if (idx > -1) dp.mentalTraits.splice(idx, 1); if (!npc.mentalTraits.includes(item.name)) { npc.mentalTraits.push(item.name); } } else if (item.type === "skill") { var idx = dp.skills.indexOf(item.name); if (idx > -1) dp.skills.splice(idx, 1); if (!npc.skills.includes(item.name)) { npc.skills.push(item.name); } } else if (item.type === "job") { if (dp.jobs) { var idx = dp.jobs.indexOf(item.name); if (idx > -1) dp.jobs.splice(idx, 1); } if (!npc.jobs.includes(item.name)) { npc.jobs.push(item.name); } } }); /* Return player's traded traits */ trade.playerOffer.forEach(function(item) { if (item.type === "physical") { if (!dp.physicalTraits.includes(item.name)) { dp.physicalTraits.push(item.name); } } else if (item.type === "mental") { if (!dp.mentalTraits.includes(item.name)) { dp.mentalTraits.push(item.name); } } else if (item.type === "skill") { if (!dp.skills.includes(item.name)) { dp.skills.push(item.name); } } }); /* Remove from history */ v.dreamTradeHistory.splice(tradeIndex, 1); return { success: true }; }>> /* Finalize dream state - transfer to actual player */ <<set setup.finalizeDreamState = function() { var v = State.variables; var dp = v.dreamPlayer; /* Transfer name */ v.firstName = dp.firstName; v.lastName = dp.lastName; /* Transfer body parts */ v.bodyParts = { gender: dp.bodyParts.gender, chest: dp.bodyParts.chest, butt: dp.bodyParts.butt, genitals: dp.bodyParts.genitals }; /* Transfer appearance */ v.appearance = { skinTone: dp.appearance.skinTone, hairColor: dp.appearance.hairColor, hairLength: dp.appearance.hairLength, hairStyle: "messy", age: dp.appearance.age }; /* Transfer traits */ v.physicalTraits = dp.physicalTraits.slice(); v.mentalTraits = dp.mentalTraits.slice(); v.skills = dp.skills.slice(); /* Set pronouns based on gender */ if (dp.bodyParts.gender === "female") { v.playerPronouns = "she/her"; } else if (dp.bodyParts.gender === "male") { v.playerPronouns = "he/him"; } else { v.playerPronouns = "they/them"; } /* Convert remaining points to money ($10 per point) */ v.money = (v.money || 0) + (v.dreamTradePoints * 10); /* Initialize other required variables */ v.stats = { charisma: 5, dexterity: 5, strength: 5, intelligence: 5 }; v.statMaxCaps = { charisma: 100, dexterity: 100, strength: 100, intelligence: 100 }; /* Set jobs from trades, or unemployed */ if (dp.jobs && dp.jobs.length > 0) { v.jobs = dp.jobs.slice(); v.homeless = false; } else { v.jobs = []; v.homeless = true; } /* Initialize other game variables */ v.maxTraits = 100; /* Clean up dream state */ delete v.dreamPlayer; delete v.dreamNPCs; delete v.dreamTradeHistory; delete v.dreamTradePoints; delete v.dreamStartingPoints; return { success: true, startingMoney: v.money }; }>> /* Get list of negative traits player can take for extra points */ <<set setup.getNegativeTraitsForPoints = function() { return { physical: [ { name: "Blemished", points: 20 }, { name: "Clumsy", points: 30 }, { name: "Overweight", points: 30 }, { name: "Plain", points: 15 }, { name: "Slow", points: 28 }, { name: "Stiff", points: 25 }, { name: "Ugly", points: 40 }, { name: "Underweight", points: 28 }, { name: "Weak", points: 35 } ], mental: [ { name: "Arrogant", points: 35 }, { name: "Awkward", points: 10 }, { name: "Cowardly", points: 38 }, { name: "Dull", points: 38 }, { name: "Foolish", points: 40 }, { name: "Forgetful", points: 25 }, { name: "Impatient", points: 28 }, { name: "Insecure", points: 25 }, { name: "Lazy", points: 38 }, { name: "Rude", points: 30 }, { name: "Selfish", points: 30 }, { name: "Short Tempered", points: 28 }, { name: "Slow Learner", points: 30 }, { name: "Unlucky", points: 28 } ] }; }>> /* Add negative trait and gain points */ <<set setup.addNegativeTraitForPoints = function(trait, type, points) { var v = State.variables; var dp = v.dreamPlayer; if (type === "physical") { if (!dp.physicalTraits.includes(trait)) { dp.physicalTraits.push(trait); dp.negativeTraits.push({ name: trait, type: type, points: points }); v.dreamTradePoints += points; return true; } } else if (type === "mental") { if (!dp.mentalTraits.includes(trait)) { dp.mentalTraits.push(trait); dp.negativeTraits.push({ name: trait, type: type, points: points }); v.dreamTradePoints += points; return true; } } return false; }>> /* Remove negative trait and lose points */ <<set setup.removeNegativeTraitForPoints = function(trait, type, points) { var v = State.variables; var dp = v.dreamPlayer; /* Check if we have enough points to remove */ if (v.dreamTradePoints < points) { return false; } if (type === "physical") { var idx = dp.physicalTraits.indexOf(trait); if (idx > -1) { dp.physicalTraits.splice(idx, 1); var negIdx = dp.negativeTraits.findIndex(function(t) { return t.name === trait; }); if (negIdx > -1) dp.negativeTraits.splice(negIdx, 1); v.dreamTradePoints -= points; return true; } } else if (type === "mental") { var idx = dp.mentalTraits.indexOf(trait); if (idx > -1) { dp.mentalTraits.splice(idx, 1); var negIdx = dp.negativeTraits.findIndex(function(t) { return t.name === trait; }); if (negIdx > -1) dp.negativeTraits.splice(negIdx, 1); v.dreamTradePoints -= points; return true; } } return false; }>>
/* ============================================== */ /* DREAM STATE CHARACTER CREATION SYSTEM */ /* ============================================== */ /* Initialize Dream State Variables */ <<set setup.initializeDreamState = function() { var v = State.variables; /* Starting trade points */ v.dreamTradePoints = 150; v.dreamStartingPoints = 150; /* Player's dream selections (before finalization) */ v.dreamPlayer = { firstName: "Water", lastName: "Bottle", gender: null, bodyParts: { gender: null, chest: null, butt: null, genitals: null }, appearance: { skinTone: "pale", hairColor: "Black", hairLength: "short", age: "Adult" }, physicalTraits: [], mentalTraits: [], skills: [], jobs: [], /* Jobs acquired from spirits */ negativeTraits: [] /* Negative traits taken for extra points */ }; /* Track completed trades (for undo functionality) */ v.dreamTradeHistory = []; /* Initialize dream NPCs */ v.dreamNPCs = []; return true; }>> /* Create Dream NPC (simplified version without stats) */ <<set setup.createDreamNPC = function(config) { var hairLengthTrait = config.hairLength === "short" ? "Short Hair" : "Long Hair"; var allPhysicalTraits = config.physicalTraits ? config.physicalTraits.slice() : []; if (!allPhysicalTraits.includes(hairLengthTrait)) { allPhysicalTraits.push(hairLengthTrait); } var npc = { name: config.name, gender: config.gender, bodyParts: { gender: config.gender, chest: config.chest || "flat", butt: config.butt || "flat", genitals: config.genitals || (config.gender === "male" ? "penis" : "vagina") }, appearance: { skinTone: config.skinTone || "pale", hairColor: config.hairColor || "Black", hairLength: config.hairLength || "short", age: config.age || "Adult" }, physicalTraits: allPhysicalTraits, mentalTraits: config.mentalTraits || [], skills: config.skills || [], jobs: config.jobs || [], isDreamNPC: true /* Flag to identify dream NPCs */ }; return npc; }>> /* Initialize the 3 Dream NPCs */ <<set setup.initializeDreamNPCs = function() { var v = State.variables; v.dreamNPCs = []; /* NPC 1: Mercy Velvet */ v.dreamNPCs.push(setup.createDreamNPC({ name: "Mercy Velvet", gender: "male", chest: "large", butt: "large", genitals: "penis", skinTone: "pale", hairColor: "Platinum Blonde", hairLength: "long", age: "Adult", physicalTraits: ["Detail-Oriented", "Pierced", "Quick", "Sarcastic"], mentalTraits: ["Analytical", "Charming", "Direct", "Outgoing", "Sly", "Witty"], skills: ["Quick Learner", "Cleaning", "Dancing", "Driving", "Guitar", "Hair Styling", "High Heels Proficient", "Makeup", "Modeling", "Piano", "Definitely not a Vampire"], jobs: ["Beauty Salon Stylist"] })); /* NPC 2: No Problem */ v.dreamNPCs.push(setup.createDreamNPC({ name: "No Problem", gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "big penis", skinTone: "tan", hairColor: "Red", hairLength: "short", age: "Mature Adult", physicalTraits: ["Athletic Build", "Broad-Shouldered", "Muscular", "Strong", "Sturdy", "Tall", "Scarred"], mentalTraits: ["Humorous", "Brave", "Competitive", "Determined", "Focused", "High Stamina", "Negotiator", "Optimistic", "Resourceful", "Shrewd", "Thoughtful", "Workaholic", "Dominant"], skills: ["Baking", "Forklift Certified", "Heavy Lifting", "Inventory Management", "Swimmer", "Were-Creature"], jobs: ["Dock Worker"] })); /* NPC 3: Damn lol */ v.dreamNPCs.push(setup.createDreamNPC({ name: "Damn lol", gender: "female", chest: "flat", butt: "flat", genitals: "loose vagina", skinTone: "dark", hairColor: "Black", hairLength: "short", age: "Mature Adult", physicalTraits: ["Attractive", "Graceful", "Mature", "Sharp Features", "Soft", "Short", "Tattooed"], mentalTraits: ["Bookworm", "Considerate", "Empathetic", "Honest", "Sly", "Steadfast", "Goth"], skills: ["Combat", "Art", "Cooking", "Lock Picking", "Medicine", "Painting", "Photography", "Retail", "Sexually Skilled", "Singing", "Social Media", "Trading", "Yoga"], jobs: ["Barista"] })); /* NPC 4: Sam Handwich */ v.dreamNPCs.push(setup.createDreamNPC({ name: "Sam Handwich", gender: "female", chest: "flat", butt: "medium", genitals: "vagina", skinTone: "pale", hairColor: "Brown", hairLength: "long", age: "Adult", physicalTraits: [], mentalTraits: [], skills: [], jobs: [] })); return v.dreamNPCs; }>> /* Calculate the trade value of an item (uses existing getTraitValue) */ <<set setup.getDreamTradeValue = function(type, name, size) { /* Use existing trait value system */ return setup.getTraitValue(type, name, size); }>> /* Calculate total value of player's current dream selections */ <<set setup.calculateDreamPlayerValue = function() { var v = State.variables; var dp = v.dreamPlayer; var totalValue = 0; /* Body parts */ if (dp.bodyParts.chest) { totalValue += setup.getDreamTradeValue("bodyPart", "chest", dp.bodyParts.chest); } if (dp.bodyParts.butt) { totalValue += setup.getDreamTradeValue("bodyPart", "butt", dp.bodyParts.butt); } if (dp.bodyParts.genitals) { totalValue += setup.getDreamTradeValue("bodyPart", "genitals", dp.bodyParts.genitals); } /* Physical traits */ dp.physicalTraits.forEach(function(trait) { totalValue += setup.getDreamTradeValue("physical", trait); }); /* Mental traits */ dp.mentalTraits.forEach(function(trait) { totalValue += setup.getDreamTradeValue("mental", trait); }); /* Skills */ dp.skills.forEach(function(skill) { totalValue += setup.getDreamTradeValue("skill", skill); }); return totalValue; }>> /* Get value of a specific item from dream NPC */ <<set setup.getDreamNPCItemValue = function(npc, type, item) { if (type === "bodyPart") { var size = npc.bodyParts[item]; return setup.getDreamTradeValue("bodyPart", item, size); } else if (type === "physical") { return setup.getDreamTradeValue("physical", item); } else if (type === "mental") { return setup.getDreamTradeValue("mental", item); } else if (type === "skill") { return setup.getDreamTradeValue("skill", item); } else if (type === "job") { return setup.getDreamTradeValue("job", item); } else if (type === "name") { return 0; /* Names are free to trade */ } else if (type === "appearance") { return 10; /* Fixed value for appearance items */ } return 0; }>> /* Execute a dream trade */ <<set setup.executeDreamTrade = function(npcIndex, playerOffer, npcOffer) { var v = State.variables; var npc = v.dreamNPCs[npcIndex]; var dp = v.dreamPlayer; /* Calculate values */ var playerOfferValue = 0; var npcOfferValue = 0; /* Calculate player offer value */ playerOffer.forEach(function(item) { if (item.type === "points") { playerOfferValue += item.value; } else { playerOfferValue += setup.getDreamNPCItemValue(dp, item.type, item.name); } }); /* Calculate NPC offer value */ npcOffer.forEach(function(item) { npcOfferValue += setup.getDreamNPCItemValue(npc, item.type, item.name); }); /* Check if trade is valid (player must offer equal or greater value) */ if (playerOfferValue < npcOfferValue) { return { success: false, reason: "Insufficient value offered" }; } /* Record the trade for undo */ var tradeRecord = { npcIndex: npcIndex, npcName: npc.name, playerOffer: JSON.parse(JSON.stringify(playerOffer)), npcOffer: JSON.parse(JSON.stringify(npcOffer)), playerOfferValue: playerOfferValue, npcOfferValue: npcOfferValue, timestamp: Date.now() }; /* ALWAYS save player's original name (with fallback defaults) */ tradeRecord.playerOriginalName = { firstName: dp.firstName || "Water", lastName: dp.lastName || "Bottle" }; /* Also ensure dp has firstName/lastName defined */ if (!dp.firstName) dp.firstName = "Water"; if (!dp.lastName) dp.lastName = "Bottle"; /* Execute the trade */ /* Remove from player, add to NPC */ playerOffer.forEach(function(item) { if (item.type === "points") { v.dreamTradePoints -= item.value; } else if (item.type === "bodyPart") { /* Swap body parts */ var playerValue = dp.bodyParts[item.name]; tradeRecord.playerOriginal = tradeRecord.playerOriginal || {}; tradeRecord.playerOriginal[item.name] = playerValue; } else if (item.type === "physical") { var idx = dp.physicalTraits.indexOf(item.name); if (idx > -1) dp.physicalTraits.splice(idx, 1); } else if (item.type === "mental") { var idx = dp.mentalTraits.indexOf(item.name); if (idx > -1) dp.mentalTraits.splice(idx, 1); } else if (item.type === "skill") { var idx = dp.skills.indexOf(item.name); if (idx > -1) dp.skills.splice(idx, 1); } else if (item.type === "name") { /* Already saved above if needed */ } }); /* Add to player, remove from NPC */ npcOffer.forEach(function(item) { if (item.type === "bodyPart") { var npcValue = npc.bodyParts[item.name]; /* Store NPC's original for undo */ tradeRecord.npcOriginal = tradeRecord.npcOriginal || {}; tradeRecord.npcOriginal[item.name] = npcValue; /* Swap */ var temp = dp.bodyParts[item.name]; dp.bodyParts[item.name] = npcValue; npc.bodyParts[item.name] = temp; } else if (item.type === "physical") { if (!dp.physicalTraits.includes(item.name)) { dp.physicalTraits.push(item.name); } var idx = npc.physicalTraits.indexOf(item.name); if (idx > -1) npc.physicalTraits.splice(idx, 1); } else if (item.type === "mental") { if (!dp.mentalTraits.includes(item.name)) { dp.mentalTraits.push(item.name); } var idx = npc.mentalTraits.indexOf(item.name); if (idx > -1) npc.mentalTraits.splice(idx, 1); } else if (item.type === "skill") { if (!dp.skills.includes(item.name)) { dp.skills.push(item.name); } var idx = npc.skills.indexOf(item.name); if (idx > -1) npc.skills.splice(idx, 1); } else if (item.type === "job") { /* Jobs are swapped, not stacked - player can only have one job */ if (!dp.jobs) dp.jobs = []; /* Store the job we're receiving */ var receivedJob = item.name; /* Get player's old job from the item (passed from passage) */ var givenJob = item.playerOldJob || null; /* Store for undo */ tradeRecord.playerOriginalJob = givenJob; /* Clear player's current jobs and set the new one */ dp.jobs = [receivedJob]; /* Remove received job from NPC */ var idx = npc.jobs.indexOf(receivedJob); if (idx > -1) npc.jobs.splice(idx, 1); /* Give player's old job to NPC (if they had one that wasn't Unemployed) */ if (givenJob && givenJob !== "Unemployed" && !npc.jobs.includes(givenJob)) { npc.jobs.push(givenJob); } } else if (item.type === "name") { /* Parse NPC name */ var nameParts = npc.name.split(" "); var playerFirstName = tradeRecord.playerOriginalName ? tradeRecord.playerOriginalName.firstName : (dp.firstName || "Water"); var playerLastName = tradeRecord.playerOriginalName ? tradeRecord.playerOriginalName.lastName : (dp.lastName || "Bottle"); if (item.which === "first") { dp.firstName = nameParts[0]; npc.name = playerFirstName + " " + nameParts.slice(1).join(" "); } else if (item.which === "last") { dp.lastName = nameParts.slice(1).join(" "); npc.name = nameParts[0] + " " + playerLastName; } else if (item.which === "full") { dp.firstName = nameParts[0]; dp.lastName = nameParts.slice(1).join(" "); npc.name = playerFirstName + " " + playerLastName; } } else if (item.type === "appearance") { var npcValue = npc.appearance[item.name]; tradeRecord.npcOriginalAppearance = tradeRecord.npcOriginalAppearance || {}; tradeRecord.npcOriginalAppearance[item.name] = npcValue; tradeRecord.playerOriginalAppearance = tradeRecord.playerOriginalAppearance || {}; tradeRecord.playerOriginalAppearance[item.name] = dp.appearance[item.name]; /* Swap appearance */ var temp = dp.appearance[item.name]; dp.appearance[item.name] = npcValue; npc.appearance[item.name] = temp; /* Handle hair length trait */ if (item.name === "hairLength") { /* Remove old hair length trait */ var oldTrait = temp === "short" ? "Short Hair" : "Long Hair"; var newTrait = npcValue === "short" ? "Short Hair" : "Long Hair"; var oldIdx = dp.physicalTraits.indexOf(oldTrait); if (oldIdx > -1) dp.physicalTraits.splice(oldIdx, 1); if (!dp.physicalTraits.includes(newTrait)) { dp.physicalTraits.push(newTrait); } } } else if (item.type === "job") { if (!dp.jobs) dp.jobs = []; if (!dp.jobs.includes(item.name)) { dp.jobs.push(item.name); } var idx = npc.jobs.indexOf(item.name); if (idx > -1) npc.jobs.splice(idx, 1); } }); /* Refund excess points */ var excessPoints = playerOfferValue - npcOfferValue; if (excessPoints > 0) { v.dreamTradePoints += excessPoints; tradeRecord.refundedPoints = excessPoints; } /* Save trade to history */ v.dreamTradeHistory.push(tradeRecord); return { success: true, playerOfferValue: playerOfferValue, npcOfferValue: npcOfferValue, refundedPoints: excessPoints, tradeIndex: v.dreamTradeHistory.length - 1 }; }>> /* Undo a dream trade */ <<set setup.undoDreamTrade = function(tradeIndex) { var v = State.variables; if (tradeIndex < 0 || tradeIndex >= v.dreamTradeHistory.length) { return { success: false, reason: "Invalid trade index" }; } var trade = v.dreamTradeHistory[tradeIndex]; var npc = v.dreamNPCs[trade.npcIndex]; var dp = v.dreamPlayer; /* Reverse the trade */ /* Return points spent */ trade.playerOffer.forEach(function(item) { if (item.type === "points") { v.dreamTradePoints += item.value; } }); /* Remove refunded points */ if (trade.refundedPoints) { v.dreamTradePoints -= trade.refundedPoints; } /* Reverse body part swaps */ if (trade.npcOriginal) { for (var partName in trade.npcOriginal) { /* Swap back */ var temp = dp.bodyParts[partName]; dp.bodyParts[partName] = npc.bodyParts[partName]; npc.bodyParts[partName] = temp; } } /* Reverse appearance swaps */ if (trade.npcOriginalAppearance) { for (var appName in trade.npcOriginalAppearance) { var temp = dp.appearance[appName]; dp.appearance[appName] = npc.appearance[appName]; npc.appearance[appName] = temp; /* Handle hair length trait */ if (appName === "hairLength") { var oldTrait = dp.appearance[appName] === "short" ? "Short Hair" : "Long Hair"; var newTrait = npc.appearance[appName] === "short" ? "Short Hair" : "Long Hair"; /* Remove current, add back original */ var idx = dp.physicalTraits.indexOf(newTrait); if (idx > -1) dp.physicalTraits.splice(idx, 1); if (!dp.physicalTraits.includes(oldTrait)) { dp.physicalTraits.push(oldTrait); } } } } /* Reverse name swap */ if (trade.playerOriginalName) { var currentPlayerFirst = dp.firstName; var currentPlayerLast = dp.lastName; /* Find which name parts were traded */ trade.npcOffer.forEach(function(item) { if (item.type === "name") { if (item.which === "first" || item.which === "full") { dp.firstName = trade.playerOriginalName.firstName; } if (item.which === "last" || item.which === "full") { dp.lastName = trade.playerOriginalName.lastName; } } }); /* Restore NPC name */ var npcNameParts = npc.name.split(" "); /* This is complex - simplified version */ npc.name = trade.npcOffer.find(function(i) { return i.type === "name"; }) ? (dp.firstName !== trade.playerOriginalName.firstName ? currentPlayerFirst : npcNameParts[0]) + " " + (dp.lastName !== trade.playerOriginalName.lastName ? currentPlayerLast : npcNameParts.slice(1).join(" ")) : npc.name; } /* Return traits to NPC, remove from player */ trade.npcOffer.forEach(function(item) { if (item.type === "physical") { var idx = dp.physicalTraits.indexOf(item.name); if (idx > -1) dp.physicalTraits.splice(idx, 1); if (!npc.physicalTraits.includes(item.name)) { npc.physicalTraits.push(item.name); } } else if (item.type === "mental") { var idx = dp.mentalTraits.indexOf(item.name); if (idx > -1) dp.mentalTraits.splice(idx, 1); if (!npc.mentalTraits.includes(item.name)) { npc.mentalTraits.push(item.name); } } else if (item.type === "skill") { var idx = dp.skills.indexOf(item.name); if (idx > -1) dp.skills.splice(idx, 1); if (!npc.skills.includes(item.name)) { npc.skills.push(item.name); } } else if (item.type === "job") { /* Return received job to NPC */ var receivedJob = item.name; if (!npc.jobs.includes(receivedJob)) { npc.jobs.push(receivedJob); } /* Restore player's original job (from tradeRecord) */ var originalJob = trade.playerOriginalJob || item.playerOldJob; if (originalJob && originalJob !== "Unemployed") { dp.jobs = [originalJob]; /* Remove from NPC if we gave it to them */ var idx = npc.jobs.indexOf(originalJob); if (idx > -1) npc.jobs.splice(idx, 1); } else { /* Player was unemployed */ dp.jobs = []; } } }); /* Return player's traded traits (physical, mental, skill only - jobs handled above) */ trade.playerOffer.forEach(function(item) { if (item.type === "physical") { if (!dp.physicalTraits.includes(item.name)) { dp.physicalTraits.push(item.name); } } else if (item.type === "mental") { if (!dp.mentalTraits.includes(item.name)) { dp.mentalTraits.push(item.name); } } else if (item.type === "skill") { if (!dp.skills.includes(item.name)) { dp.skills.push(item.name); } } /* Jobs are handled in npcOffer section above */ }); /* Remove from history */ v.dreamTradeHistory.splice(tradeIndex, 1); return { success: true }; }>> /* Finalize dream state - transfer to actual player */ <<set setup.finalizeDreamState = function() { var v = State.variables; var dp = v.dreamPlayer; /* Transfer name */ v.firstName = dp.firstName; v.lastName = dp.lastName; /* Transfer body parts */ v.bodyParts = { gender: dp.bodyParts.gender, chest: dp.bodyParts.chest, butt: dp.bodyParts.butt, genitals: dp.bodyParts.genitals }; /* Transfer appearance */ v.appearance = { skinTone: dp.appearance.skinTone, hairColor: dp.appearance.hairColor, hairLength: dp.appearance.hairLength, hairStyle: "messy", age: dp.appearance.age }; /* Transfer traits */ v.physicalTraits = dp.physicalTraits.slice(); v.mentalTraits = dp.mentalTraits.slice(); v.skills = dp.skills.slice(); /* Convert remaining points to money ($10 per point) */ v.money = (v.money || 0) + (v.dreamTradePoints * 10); /* Initialize other required variables */ v.stats = { charisma: 5, dexterity: 5, strength: 5, intelligence: 5 }; v.statMaxCaps = { charisma: 100, dexterity: 100, strength: 100, intelligence: 100 }; /* Set jobs from trades, or unemployed */ if (dp.jobs && dp.jobs.length > 0) { v.jobs = dp.jobs.slice(); v.homeless = false; } else { v.jobs = []; v.homeless = true; } /* Initialize other game variables */ v.maxTraits = 100; /* Clean up dream state */ delete v.dreamPlayer; delete v.dreamNPCs; delete v.dreamTradeHistory; delete v.dreamTradePoints; delete v.dreamStartingPoints; return { success: true, startingMoney: v.money }; }>> /* Get list of negative traits player can take for extra points */ <<set setup.getNegativeTraitsForPoints = function() { return { physical: [ { name: "Awkward", points: 5 }, { name: "Clumsy", points: 15 }, { name: "Overweight", points: 15 }, { name: "Plain", points: 8 }, { name: "Slow", points: 14 }, { name: "Stiff", points: 13 }, { name: "Ugly", points: 20 }, { name: "Underweight", points: 14 } ], mental: [ { name: "Arrogant", points: 18 }, { name: "Cowardly", points: 19 }, { name: "Dull", points: 19 }, { name: "Foolish", points: 20 }, { name: "Forgetful", points: 13 }, { name: "Lazy", points: 19 }, { name: "Unlucky", points: 70 }, { name: "Unskilled", points: 50 } ] }; }>> /* Add negative trait and gain points */ <<set setup.addNegativeTraitForPoints = function(trait, type, points) { var v = State.variables; var dp = v.dreamPlayer; if (type === "physical") { if (!dp.physicalTraits.includes(trait)) { dp.physicalTraits.push(trait); dp.negativeTraits.push({ name: trait, type: type, points: points }); v.dreamTradePoints += points; return true; } } else if (type === "mental") { if (!dp.mentalTraits.includes(trait)) { dp.mentalTraits.push(trait); dp.negativeTraits.push({ name: trait, type: type, points: points }); v.dreamTradePoints += points; return true; } } return false; }>> /* Remove negative trait and lose points */ <<set setup.removeNegativeTraitForPoints = function(trait, type, points) { var v = State.variables; var dp = v.dreamPlayer; /* Check if we have enough points to remove */ if (v.dreamTradePoints < points) { return false; } if (type === "physical") { var idx = dp.physicalTraits.indexOf(trait); if (idx > -1) { dp.physicalTraits.splice(idx, 1); var negIdx = dp.negativeTraits.findIndex(function(t) { return t.name === trait; }); if (negIdx > -1) dp.negativeTraits.splice(negIdx, 1); v.dreamTradePoints -= points; return true; } } else if (type === "mental") { var idx = dp.mentalTraits.indexOf(trait); if (idx > -1) { dp.mentalTraits.splice(idx, 1); var negIdx = dp.negativeTraits.findIndex(function(t) { return t.name === trait; }); if (negIdx > -1) dp.negativeTraits.splice(negIdx, 1); v.dreamTradePoints -= points; return true; } } return false; }>>
/* DreamStateStyles - Shared CSS for all dream state passages */ <style> /* Dream State Animations */ @keyframes dreamPulse { 0%, 100% { text-shadow: 0 0 10px #7dd3fc, 0 0 20px #7dd3fc, 0 0 30px #7dd3fc; opacity: 0.9; } 50% { text-shadow: 0 0 20px #7dd3fc, 0 0 40px #7dd3fc, 0 0 60px #7dd3fc, 0 0 80px #3b82f6; opacity: 1; } } @keyframes dreamFloat { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-10px); } } @keyframes dreamFade { 0% { opacity: 0; transform: translateY(20px); } 100% { opacity: 1; transform: translateY(0); } } @keyframes voidSwirl { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes starTwinkle { 0%, 100% { opacity: 0.3; } 50% { opacity: 1; } } @keyframes ghostFloat { 0%, 100% { transform: translateY(0px) scale(1); opacity: 0.9; } 50% { transform: translateY(-8px) scale(1.02); opacity: 1; } } @keyframes spiritGlow { 0%, 100% { box-shadow: 0 0 20px rgba(192, 132, 252, 0.4); } 50% { box-shadow: 0 0 40px rgba(192, 132, 252, 0.7), 0 0 60px rgba(125, 211, 252, 0.3); } } .dream-container { background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2e 50%, #0a1a2e 100%); min-height: 100vh; padding: 30px 20px; position: relative; overflow: hidden; } .dream-container::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-image: radial-gradient(2px 2px at 20px 30px, white, transparent), radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.8), transparent), radial-gradient(1px 1px at 90px 40px, white, transparent), radial-gradient(2px 2px at 130px 80px, rgba(255,255,255,0.6), transparent), radial-gradient(1px 1px at 160px 120px, white, transparent); background-repeat: repeat; background-size: 200px 200px; animation: starTwinkle 4s ease-in-out infinite; pointer-events: none; } .dream-title { color: #c084fc; font-size: 36px; text-align: center; text-shadow: 0 0 20px #c084fc, 0 0 40px #a855f7; margin-bottom: 30px; letter-spacing: 2px; } .dream-points-display { background: linear-gradient(135deg, rgba(192, 132, 252, 0.3) 0%, rgba(125, 211, 252, 0.3) 100%); border: 3px solid #c084fc; border-radius: 15px; padding: 20px; text-align: center; margin: 0 auto 30px auto; max-width: 400px; box-shadow: 0 0 30px rgba(192, 132, 252, 0.4); } .dream-points-label { color: #c084fc; font-size: 18px; margin-bottom: 10px; } .dream-points-value { color: #7dd3fc; font-size: 48px; font-weight: bold; text-shadow: 0 0 20px #7dd3fc; animation: dreamPulse 2s ease-in-out infinite; } .dream-section { background: rgba(10, 10, 30, 0.9); border: 2px solid rgba(125, 211, 252, 0.3); border-radius: 15px; padding: 25px; margin: 20px auto; max-width: 900px; box-shadow: 0 0 20px rgba(125, 211, 252, 0.15); } .dream-section-title { color: #7dd3fc; font-size: 24px; margin: 0 0 20px 0; padding-bottom: 10px; border-bottom: 2px solid rgba(125, 211, 252, 0.3); text-shadow: 0 0 10px #7dd3fc; } .dream-option-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; } .dream-option { background: rgba(20, 20, 40, 0.8); border: 2px solid rgba(125, 211, 252, 0.3); border-radius: 10px; padding: 15px; cursor: pointer; transition: all 0.3s ease; text-align: center; } .dream-option:hover { border-color: #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.3); transform: translateY(-3px); } .dream-option.selected { border-color: #c084fc; background: rgba(192, 132, 252, 0.2); box-shadow: 0 0 25px rgba(192, 132, 252, 0.4); } .dream-option-label { color: #ccc; font-size: 18px; font-weight: bold; } .dream-option.selected .dream-option-label { color: #c084fc; } .dream-option-desc { color: #888; font-size: 13px; margin-top: 8px; } .dream-negative-trait { background: rgba(40, 20, 20, 0.8); border: 2px solid rgba(255, 107, 107, 0.3); border-radius: 10px; padding: 12px 15px; display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; transition: all 0.3s ease; cursor: pointer; white-space: nowrap; } .dream-negative-trait:hover { border-color: #ff6b6b; box-shadow: 0 0 15px rgba(255, 107, 107, 0.2); } .dream-negative-trait.taken { background: rgba(255, 107, 107, 0.2); border-color: #ff6b6b; } .dream-negative-name { color: #ff6b6b; font-weight: bold; font-size: 16px; } .dream-negative-points { color: #51cf66; font-weight: bold; font-size: 16px; } .dream-button { background: linear-gradient(135deg, rgba(125, 211, 252, 0.3) 0%, rgba(192, 132, 252, 0.3) 100%); border: 2px solid #7dd3fc; color: #7dd3fc; padding: 15px 40px; border-radius: 25px; font-size: 18px; font-weight: bold; cursor: pointer; transition: all 0.3s ease; text-shadow: 0 0 10px #7dd3fc; box-shadow: 0 0 20px rgba(125, 211, 252, 0.3); display: inline-block; } .dream-button:hover { background: linear-gradient(135deg, rgba(125, 211, 252, 0.5) 0%, rgba(192, 132, 252, 0.5) 100%); box-shadow: 0 0 40px rgba(125, 211, 252, 0.5); transform: scale(1.05); } .dream-button.disabled { opacity: 0.4; cursor: not-allowed; } .dream-voice { color: #7dd3fc; font-size: 18px; text-align: center; font-style: italic; margin: 15px 0; text-shadow: 0 0 10px rgba(125, 211, 252, 0.5); } .dream-voice-emphasis { color: #c084fc; font-weight: bold; text-shadow: 0 0 15px #c084fc, 0 0 30px #a855f7; } .dream-current-body { background: rgba(20, 20, 40, 0.8); border: 2px solid rgba(192, 132, 252, 0.4); border-radius: 10px; padding: 15px; margin-top: 15px; } .dream-body-item { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid rgba(125, 211, 252, 0.1); color: #ccc; } .dream-body-item:last-child { border-bottom: none; } .dream-body-label { color: #888; } .dream-body-value { color: #c084fc; font-weight: bold; } .dream-divider { height: 2px; background: linear-gradient(90deg, transparent, #7dd3fc, #c084fc, #7dd3fc, transparent); margin: 30px 0; opacity: 0.5; } /* Spirit NPC Cards */ .spirit-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; max-width: 1200px; margin: 0 auto 30px auto; } .spirit-card { background: rgba(20, 10, 40, 0.95); border: 3px solid rgba(192, 132, 252, 0.5); border-radius: 20px; padding: 20px; animation: ghostFloat 5s ease-in-out infinite; box-shadow: 0 0 25px rgba(192, 132, 252, 0.4); } .spirit-card:nth-child(2) { animation-delay: 0.5s; } .spirit-card:nth-child(3) { animation-delay: 1s; } .spirit-name { color: #c084fc; font-size: 24px; text-align: center; margin: 0 0 15px 0; text-shadow: 0 0 15px #c084fc; } .spirit-section { margin-bottom: 15px; } .spirit-section-title { color: #7dd3fc; font-size: 14px; font-weight: bold; margin-bottom: 8px; padding-bottom: 5px; border-bottom: 1px solid rgba(125, 211, 252, 0.3); } .spirit-trait-list { display: flex; flex-wrap: wrap; gap: 6px; } .spirit-trait { background: rgba(125, 211, 252, 0.15); border: 1px solid rgba(125, 211, 252, 0.4); color: #ccc; padding: 4px 10px; border-radius: 12px; font-size: 12px; cursor: pointer; transition: all 0.2s ease; white-space: nowrap; } .spirit-trait:hover { background: rgba(125, 211, 252, 0.3); border-color: #7dd3fc; color: #fff; } .spirit-trait .trait-value { color: #51cf66; font-weight: bold; margin-left: 5px; } .spirit-body-info { background: rgba(30, 20, 50, 0.8); border-radius: 10px; padding: 10px; font-size: 13px; color: #aaa; } .spirit-body-row { display: flex; justify-content: space-between; padding: 4px 0; } .spirit-body-value { color: #c084fc; font-weight: bold; } /* Trade History */ .trade-history-item { background: rgba(20, 20, 40, 0.8); border: 2px solid rgba(192, 132, 252, 0.3); border-radius: 10px; padding: 15px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } .trade-history-info { flex: 1; } .trade-history-npc { color: #c084fc; font-weight: bold; font-size: 16px; } .trade-history-details { color: #aaa; font-size: 13px; margin-top: 5px; } .undo-button { background: rgba(255, 107, 107, 0.2); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 8px 15px; border-radius: 15px; cursor: pointer; font-weight: bold; transition: all 0.2s ease; } .undo-button:hover { background: rgba(255, 107, 107, 0.4); } /* Player traits display */ .your-trait { background: rgba(81, 207, 102, 0.15); border: 1px solid rgba(81, 207, 102, 0.4); color: #ccc; padding: 4px 10px; border-radius: 12px; font-size: 12px; display: inline-block; margin: 3px; white-space: nowrap; } /* Point conversion info */ .conversion-info { background: rgba(255, 193, 7, 0.1); border: 2px solid rgba(255, 193, 7, 0.4); border-radius: 10px; padding: 15px; text-align: center; margin-top: 20px; } .conversion-text { color: #ffc107; font-size: 16px; } .conversion-amount { color: #51cf66; font-size: 24px; font-weight: bold; text-shadow: 0 0 10px rgba(81, 207, 102, 0.5); } /* Summary page styles */ .summary-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } .summary-item { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid rgba(125, 211, 252, 0.1); } .summary-item:last-child { border-bottom: none; } .summary-label { color: #888; font-size: 16px; } .summary-value { color: #c084fc; font-weight: bold; font-size: 16px; } .trait-tag { display: inline-block; padding: 6px 14px; border-radius: 20px; font-size: 14px; margin: 4px; font-weight: 500; white-space: nowrap; } .trait-physical { background: rgba(81, 207, 102, 0.2); border: 1px solid rgba(81, 207, 102, 0.5); color: #51cf66; } .trait-mental { background: rgba(155, 89, 182, 0.2); border: 1px solid rgba(155, 89, 182, 0.5); color: #9b59b6; } .trait-skill { background: rgba(255, 193, 7, 0.2); border: 1px solid rgba(255, 193, 7, 0.5); color: #ffc107; } .trait-negative { background: rgba(255, 107, 107, 0.2); border: 1px solid rgba(255, 107, 107, 0.5); color: #ff6b6b; } .money-display { background: linear-gradient(135deg, rgba(81, 207, 102, 0.3) 0%, rgba(40, 167, 69, 0.3) 100%); border: 3px solid #51cf66; border-radius: 15px; padding: 25px; text-align: center; margin: 25px auto; max-width: 400px; box-shadow: 0 0 30px rgba(81, 207, 102, 0.3); } .money-label { color: #51cf66; font-size: 18px; margin-bottom: 10px; } .money-value { color: #51cf66; font-size: 48px; font-weight: bold; text-shadow: 0 0 20px rgba(81, 207, 102, 0.5); } .money-detail { color: #aaa; font-size: 14px; margin-top: 10px; } .warning-box { background: rgba(255, 193, 7, 0.1); border: 2px solid rgba(255, 193, 7, 0.5); border-radius: 10px; padding: 20px; margin: 20px auto; max-width: 600px; text-align: center; } .warning-text { color: #ffc107; font-size: 16px; } </style>
<<nobr>> /* Initialize Dream State */ <<run setup.initializeDreamState()>> <<run setup.initializeDreamNPCs()>> <style> /* Dream State Animations - Optimized for mobile performance */ @keyframes dreamPulse { 0%, 100% { opacity: 0.85; } 50% { opacity: 1; } } @keyframes dreamFloat { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-8px); } } @keyframes dreamFade { 0% { opacity: 0; transform: translateY(15px); } 100% { opacity: 1; transform: translateY(0); } } .dream-container { background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2e 50%, #0a1a2e 100%); min-height: 100vh; padding: 40px 20px; position: relative; overflow: hidden; } .dream-container::before { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-image: radial-gradient(1px 1px at 20px 30px, rgba(255,255,255,0.7), transparent), radial-gradient(1px 1px at 80px 60px, rgba(255,255,255,0.5), transparent), radial-gradient(1px 1px at 140px 90px, rgba(255,255,255,0.6), transparent); background-repeat: repeat; background-size: 180px 120px; opacity: 0.6; pointer-events: none; } .dream-voice { color: #7dd3fc; font-size: 22px; line-height: 2; text-align: center; text-shadow: 0 0 15px #7dd3fc; font-style: italic; letter-spacing: 1px; } .dream-voice-emphasis { color: #c084fc; font-weight: bold; text-shadow: 0 0 12px #c084fc; } .dream-title { color: #c084fc; font-size: 42px; text-align: center; animation: dreamFloat 4s ease-in-out infinite; text-shadow: 0 0 20px #c084fc, 0 0 35px #a855f7; margin-bottom: 40px; letter-spacing: 3px; will-change: transform; } .dream-section { background: rgba(10, 10, 30, 0.85); border: 2px solid rgba(125, 211, 252, 0.3); border-radius: 20px; padding: 30px; margin: 30px auto; max-width: 800px; animation: dreamFade 0.8s ease-out; box-shadow: 0 0 20px rgba(125, 211, 252, 0.15); } .dream-button { background: linear-gradient(135deg, rgba(125, 211, 252, 0.3) 0%, rgba(192, 132, 252, 0.3) 100%); border: 2px solid #7dd3fc; color: #7dd3fc; padding: 20px 50px; border-radius: 30px; font-size: 20px; font-weight: bold; cursor: pointer; transition: transform 0.2s ease, box-shadow 0.2s ease; text-shadow: 0 0 10px #7dd3fc; box-shadow: 0 0 15px rgba(125, 211, 252, 0.25); display: inline-block; } .dream-button:hover { box-shadow: 0 0 25px rgba(125, 211, 252, 0.4); transform: scale(1.03); } .dream-divider { height: 2px; background: linear-gradient(90deg, transparent, #7dd3fc, #c084fc, #7dd3fc, transparent); margin: 30px 0; opacity: 0.5; } </style> <div class="dream-container"> <h1 class="dream-title">☽ ✧ ☾</h1> <div class="dream-section" style="animation-delay: 0.2s;"> <p class="dream-voice"> You drift... formless... nameless... through an endless void of starlight and shadow... </p> </div> <div class="dream-section" style="animation-delay: 0.5s;"> <p class="dream-voice"> A presence stirs in the darkness. Ancient. Unknowable. Its voice echoes not in your ears, but in the very fabric of your being... </p> </div> <div class="dream-divider"></div> <div class="dream-section" style="animation-delay: 0.8s;"> <p class="dream-voice"> <span class="dream-voice-emphasis">"Wanderer..."</span> </p> <p class="dream-voice"> <span class="dream-voice-emphasis">"The Island of the Sunfish awaits..."</span> </p> <p class="dream-voice"> <span class="dream-voice-emphasis">"...where dreams may become reality."</span> </p> </div> <div class="dream-divider"></div> <div class="dream-section" style="animation-delay: 1.1s;"> <p class="dream-voice"> In this land where you shall dwell, a <span class="dream-voice-emphasis">strange phenomenon</span> permeates all things... </p> <p class="dream-voice"> The boundaries between souls grow thin. What defines <span class="dream-voice-emphasis">you</span> — your body, your mind, your very essence — becomes... <span class="dream-voice-emphasis">mutable</span>. </p> </div> <div class="dream-section" style="animation-delay: 1.4s;"> <p class="dream-voice"> Those who walk these shores may <span class="dream-voice-emphasis">trade</span> pieces of themselves with others — whether it be the shape of their flesh, the nature of their thoughts, or the skills etched into their souls. </p> <p class="dream-voice"> Physical... mental... it matters not. All can be <span class="dream-voice-emphasis">exchanged</span>. </p> </div> <div class="dream-section" style="animation-delay: 1.7s;"> <p class="dream-voice"> Some resist this pull with iron will, clinging to their original selves. A rare few possess the strength to reject all change entirely... </p> <p class="dream-voice"> But most? Most <span class="dream-voice-emphasis">succumb</span>. The desire to trade, to transform, to become <span class="dream-voice-emphasis">something new</span>... it is intoxicating. </p> </div> <div class="dream-divider"></div> <div class="dream-section" style="animation-delay: 2s;"> <p class="dream-voice"> <span class="dream-voice-emphasis">"You, wanderer, are different."</span> </p> <p class="dream-voice"> You possess the <span class="dream-voice-emphasis">gift of choice</span>. Where others are swept along by the current of change, you may <span class="dream-voice-emphasis">direct your own transformation</span>. </p> <p class="dream-voice"> Use this power wisely... or recklessly. The choice, as always, is <span class="dream-voice-emphasis">yours</span>. </p> </div> <div class="dream-divider"></div> <div class="dream-section" style="animation-delay: 2.3s;"> <p class="dream-voice"> <span class="dream-voice-emphasis">"But first... you must remember who you are."</span> </p> <p class="dream-voice"> <span class="dream-voice-emphasis">"Or perhaps... decide who you wish to become."</span> </p> </div> <div class="dream-section" style="animation-delay: 2.6s;"> <p class="dream-voice"> Four spirits linger here at the threshold between worlds. They carry with them fragments of identity — traits, skills, even names — that they may trade with you before you awaken... </p> <p class="dream-voice"> What you carry into the waking world... <span class="dream-voice-emphasis">will define your journey</span>. </p> </div> <div style="text-align: center; margin-top: 50px; animation: dreamFade 1s ease-out; animation-delay: 3s; animation-fill-mode: backwards;"> <<link "<span class='dream-button'>✧ Awaken Your Consciousness ✧</span>">> <<goto "DreamGenderSelect">> <</link>> </div> <!-- Quick Start Option --> <div style="text-align: center; margin-top: 30px; animation: dreamFade 1s ease-out; animation-delay: 3.3s; animation-fill-mode: backwards;"> <p style="color: #666; font-size: 14px; margin-bottom: 15px;">— or —</p> <<link "<span style='background: linear-gradient(135deg, rgba(100, 100, 100, 0.3) 0%, rgba(80, 80, 80, 0.3) 100%); border: 2px solid #666; color: #888; padding: 12px 30px; border-radius: 20px; font-size: 16px; cursor: pointer; display: inline-block;'>⚡ Quick Start</span>">> <<set $money = 1500>> <<set $firstName = "Water">> <<set $lastName = "Bottle">> <<set $appearance = { skinTone: "pale", hairColor: "Black", hairLength: "short", hairStyle: "messy", age: "Adult" }>> <<set $bodyParts = { gender: "male", chest: "flat masculine", butt: "flat masculine", genitals: "small penis" }>> <<set $stats = { charisma: 5, dexterity: 5, strength: 5, intelligence: 5 }>> <<set $physicalTraits = []>> <<set $mentalTraits = []>> <<set $skills = []>> <<set $jobs = []>> <<set $negativeTraits = []>> <<set $homeless = true>> <<set $visitedLocations = []>> <<run setup.achievements.unlock("first_character")>> <<goto "Alleyway">> <</link>> <p style="color: #555; font-size: 12px; margin-top: 10px;">Skip character creation (default male, $1,500)</p> </div> </div> <</nobr>>
<<nobr>> /* Define refresh function once using JavaScript - avoids widget redefinition issues */ <<run setup.refreshDreamSelections = function() { $("#points-display").empty().wiki("$dreamTradePoints"); $("#gender-options").empty().wiki('<<include "DreamGenderOptions">>'); $("#appearance-options").empty().wiki('<<include "DreamAppearanceOptions">>'); $("#negative-traits").empty().wiki('<<include "DreamNegativeTraits">>'); $("#identity-summary").empty().wiki('<<include "DreamIdentitySummary">>'); $("#continue-button").empty().wiki('<<include "DreamContinueButton">>'); }; >> <<include "DreamStateStyles">> <div class="dream-container"> <h1 class="dream-title">☽ Shape Your Form ☾</h1> <!-- Trade Points Display --> <div class="dream-points-display"> <div class="dream-points-label">✧ Essence Points ✧</div> <div class="dream-points-value"><span id="points-display">$dreamTradePoints</span></div> </div> <p class="dream-voice"> "Before you meet the spirits who dwell here... you must first define the vessel you shall inhabit..." </p> <!-- Gender Selection --> <div class="dream-section"> <h2 class="dream-section-title">⚧ Your Form</h2> <span id="gender-options"><<include "DreamGenderOptions">></span> </div> <!-- Appearance Selection --> <div class="dream-section"> <h2 class="dream-section-title">✨ Your Appearance</h2> <span id="appearance-options"><<include "DreamAppearanceOptions">></span> </div> <!-- Negative Traits for Bonus Points --> <div class="dream-section"> <h2 class="dream-section-title" style="color: #ff6b6b; border-color: rgba(255, 107, 107, 0.3);">⚠️ Burden Your Soul (Optional)</h2> <p class="dream-voice" style="color: #ff6b6b;"> "Accept these flaws... and gain additional essence to shape your destiny..." </p> <span id="negative-traits"><<include "DreamNegativeTraits">></span> </div> <!-- Current Identity Summary --> <div class="dream-section"> <h2 class="dream-section-title">👤 Your Current Identity</h2> <span id="identity-summary"><<include "DreamIdentitySummary">></span> </div> <!-- Navigation --> <div style="text-align: center; margin-top: 40px; display: flex; justify-content: center; gap: 20px;"> <<link "<span class='dream-button' style='border-color: #888; color: #888;'>← Back</span>">> <<goto "DreamIntro">> <</link>> <span id="continue-button"><<include "DreamContinueButton">></span> </div> </div> <</nobr>>
<<nobr>> <div class="dream-option-grid"> <<link "<div class='dream-option <<if $dreamPlayer.bodyParts.gender === \"male\">>selected<</if>>'><div class='dream-option-label'>♂ Male</div><div class='dream-option-desc'>Small penis, Flat masculine chest, Flat masculine butt</div></div>">> <<set $dreamPlayer.bodyParts.gender = "male">> <<set $dreamPlayer.bodyParts.genitals = "small penis">> <<set $dreamPlayer.bodyParts.chest = "flat masculine">> <<set $dreamPlayer.bodyParts.butt = "flat masculine">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.bodyParts.gender === \"female\">>selected<</if>>'><div class='dream-option-label'>♀ Female</div><div class='dream-option-desc'>Tight vagina, Flat chest, Flat butt</div></div>">> <<set $dreamPlayer.bodyParts.gender = "female">> <<set $dreamPlayer.bodyParts.genitals = "tight vagina">> <<set $dreamPlayer.bodyParts.chest = "flat">> <<set $dreamPlayer.bodyParts.butt = "flat">> <<run setup.refreshDreamSelections()>> <</link>> </div> <!-- Show current body if gender selected --> <<if $dreamPlayer.bodyParts.gender>> <div class="dream-current-body"> <div class="dream-body-item"> <span class="dream-body-label">Gender:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.gender.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Chest:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.chest.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Butt:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.butt.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Genitals:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.genitals.toUpperFirst()>></span> </div> </div> <</if>> <</nobr>>
<<nobr>> <!-- Skin Tone --> <div style="margin-bottom: 20px;"> <div style="color: #aaa; margin-bottom: 10px; font-size: 16px;">Skin Tone:</div> <div class="dream-option-grid" style="grid-template-columns: repeat(3, 1fr);"> <<link "<div class='dream-option <<if $dreamPlayer.appearance.skinTone === \"pale\">>selected<</if>>'><div class='dream-option-label'>Pale</div></div>">> <<set $dreamPlayer.appearance.skinTone = "pale">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.appearance.skinTone === \"tan\">>selected<</if>>'><div class='dream-option-label'>Tan</div></div>">> <<set $dreamPlayer.appearance.skinTone = "tan">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.appearance.skinTone === \"dark\">>selected<</if>>'><div class='dream-option-label'>Dark</div></div>">> <<set $dreamPlayer.appearance.skinTone = "dark">> <<run setup.refreshDreamSelections()>> <</link>> </div> </div> <!-- Hair Color --> <div style="margin-bottom: 20px;"> <div style="color: #aaa; margin-bottom: 10px; font-size: 16px;">Hair Color:</div> <div class="dream-option-grid" style="grid-template-columns: repeat(4, 1fr);"> <<link "<div class='dream-option <<if $dreamPlayer.appearance.hairColor === \"Black\">>selected<</if>>'><div class='dream-option-label'>Black</div></div>">> <<set $dreamPlayer.appearance.hairColor = "Black">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.appearance.hairColor === \"Brown\">>selected<</if>>'><div class='dream-option-label'>Brown</div></div>">> <<set $dreamPlayer.appearance.hairColor = "Brown">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.appearance.hairColor === \"Blonde\">>selected<</if>>'><div class='dream-option-label'>Blonde</div></div>">> <<set $dreamPlayer.appearance.hairColor = "Blonde">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.appearance.hairColor === \"Red\">>selected<</if>>'><div class='dream-option-label'>Red</div></div>">> <<set $dreamPlayer.appearance.hairColor = "Red">> <<run setup.refreshDreamSelections()>> <</link>> </div> </div> <!-- Age --> <div style="margin-bottom: 0;"> <div style="color: #aaa; margin-bottom: 10px; font-size: 16px;">Age:</div> <div class="dream-option-grid" style="grid-template-columns: repeat(2, 1fr);"> <<link "<div class='dream-option <<if $dreamPlayer.appearance.age === \"Adult\">>selected<</if>>'><div class='dream-option-label'>Adult</div></div>">> <<set $dreamPlayer.appearance.age = "Adult">> <<run setup.refreshDreamSelections()>> <</link>> <<link "<div class='dream-option <<if $dreamPlayer.appearance.age === \"Mature Adult\">>selected<</if>>'><div class='dream-option-label'>Mature Adult</div></div>">> <<set $dreamPlayer.appearance.age = "Mature Adult">> <<run setup.refreshDreamSelections()>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _negTraits = setup.getNegativeTraitsForPoints()>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <!-- Physical Negatives --> <div> <h3 style="color: #51cf66; margin: 0 0 15px 0; font-size: 18px;">💪 Physical Flaws</h3> <<for _trait range _negTraits.physical>> <<capture _trait>> <<set _isTaken = $dreamPlayer.negativeTraits.some(function(t) { return t.name === _trait.name; })>> <<if _isTaken>> <<link "<div class='dream-negative-trait taken'><span class='dream-negative-name'><<print _trait.name>></span><span style='color: #ff6b6b;'>✕ Remove</span></div>">> <<run setup.removeNegativeTraitForPoints(_trait.name, "physical", _trait.points)>> <<run setup.refreshDreamSelections()>> <</link>> <<else>> <<link "<div class='dream-negative-trait'><span class='dream-negative-name'><<print _trait.name>></span><span class='dream-negative-points'>+<<print _trait.points>> pts</span></div>">> <<run setup.addNegativeTraitForPoints(_trait.name, "physical", _trait.points)>> <<run setup.refreshDreamSelections()>> <</link>> <</if>> <</capture>> <</for>> </div> <!-- Mental Negatives --> <div> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 18px;">🧠 Mental Flaws</h3> <<for _trait range _negTraits.mental>> <<capture _trait>> <<set _isTaken = $dreamPlayer.negativeTraits.some(function(t) { return t.name === _trait.name; })>> <<if _isTaken>> <<link "<div class='dream-negative-trait taken'><span class='dream-negative-name'><<print _trait.name>></span><span style='color: #ff6b6b;'>✕ Remove</span></div>">> <<run setup.removeNegativeTraitForPoints(_trait.name, "mental", _trait.points)>> <<run setup.refreshDreamSelections()>> <</link>> <<else>> <<link "<div class='dream-negative-trait'><span class='dream-negative-name'><<print _trait.name>></span><span class='dream-negative-points'>+<<print _trait.points>> pts</span></div>">> <<run setup.addNegativeTraitForPoints(_trait.name, "mental", _trait.points)>> <<run setup.refreshDreamSelections()>> <</link>> <</if>> <</capture>> <</for>> </div> </div> <!-- Currently taken negatives summary --> <<if $dreamPlayer.negativeTraits.length > 0>> <div style="margin-top: 20px; padding: 15px; background: rgba(255, 107, 107, 0.1); border-radius: 10px; border: 1px solid rgba(255, 107, 107, 0.3);"> <div style="color: #ff6b6b; font-weight: bold; margin-bottom: 10px;">Accepted Burdens:</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _neg range $dreamPlayer.negativeTraits>> <span style="background: rgba(255, 107, 107, 0.2); color: #ff6b6b; padding: 5px 12px; border-radius: 15px; font-size: 14px;"> <<print _neg.name>> (+<<print _neg.points>>) </span> <</for>> </div> <<set _totalNegPoints = $dreamPlayer.negativeTraits.reduce(function(sum, t) { return sum + t.points; }, 0)>> <div style="color: #51cf66; margin-top: 10px; font-weight: bold;"> Total Bonus: +<<print _totalNegPoints>> points </div> </div> <</if>> <</nobr>>
<<nobr>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <div> <div class="dream-body-item"> <span class="dream-body-label">Name:</span> <span class="dream-body-value">$dreamPlayer.firstName $dreamPlayer.lastName</span> </div> <div class="dream-body-item"> <span class="dream-body-label">Skin:</span> <span class="dream-body-value"><<print $dreamPlayer.appearance.skinTone.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Hair:</span> <span class="dream-body-value"><<print $dreamPlayer.appearance.hairColor>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Age:</span> <span class="dream-body-value"><<print $dreamPlayer.appearance.age>></span> </div> </div> <div> <<if $dreamPlayer.bodyParts.gender>> <div class="dream-body-item"> <span class="dream-body-label">Gender:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.gender.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Chest:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.chest.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Butt:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.butt.toUpperFirst()>></span> </div> <div class="dream-body-item"> <span class="dream-body-label">Genitals:</span> <span class="dream-body-value"><<print $dreamPlayer.bodyParts.genitals.toUpperFirst()>></span> </div> <<else>> <div style="color: #888; font-style: italic; padding: 20px; text-align: center;"> Select a gender above... </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<if $dreamPlayer.bodyParts.gender>> <<link "<span class='dream-button'>Meet the Spirits ✧</span>">> /* Set initial hair length trait based on gender */ <<if $dreamPlayer.bodyParts.gender === "female">> <<set $dreamPlayer.appearance.hairLength = "long">> <<if !$dreamPlayer.physicalTraits.includes("Long Hair")>> <<run $dreamPlayer.physicalTraits.push("Long Hair")>> <</if>> <<else>> <<set $dreamPlayer.appearance.hairLength = "short">> <<if !$dreamPlayer.physicalTraits.includes("Short Hair")>> <<run $dreamPlayer.physicalTraits.push("Short Hair")>> <</if>> <</if>> <<goto "DreamTrading">> <</link>> <<else>> <span class='dream-button disabled'>Select Gender First</span> <</if>> <</nobr>>
<<nobr>> <style> /* Dream State Animations */ @keyframes dreamPulse { 0%, 100% { text-shadow: 0 0 10px #7dd3fc, 0 0 20px #7dd3fc, 0 0 30px #7dd3fc; opacity: 0.9; } 50% { text-shadow: 0 0 20px #7dd3fc, 0 0 40px #7dd3fc, 0 0 60px #7dd3fc; opacity: 1; } } @keyframes voidSwirl { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes ghostFloat { 0%, 100% { transform: translateY(0px) scale(1); opacity: 0.9; } 50% { transform: translateY(-8px) scale(1.02); opacity: 1; } } @keyframes spiritGlow { 0%, 100% { box-shadow: 0 0 20px rgba(192, 132, 252, 0.4); } 50% { box-shadow: 0 0 40px rgba(192, 132, 252, 0.7), 0 0 60px rgba(125, 211, 252, 0.3); } } .dream-container { background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2e 50%, #0a1a2e 100%); min-height: 100vh; padding: 30px 20px; position: relative; } .dream-title { color: #c084fc; font-size: 36px; text-align: center; text-shadow: 0 0 20px #c084fc, 0 0 40px #a855f7; margin-bottom: 20px; } .dream-points-display { background: linear-gradient(135deg, rgba(192, 132, 252, 0.3) 0%, rgba(125, 211, 252, 0.3) 100%); border: 3px solid #c084fc; border-radius: 15px; padding: 15px 30px; text-align: center; margin: 0 auto 25px auto; max-width: 350px; box-shadow: 0 0 30px rgba(192, 132, 252, 0.4); display: flex; justify-content: space-between; align-items: center; } .dream-points-label { color: #c084fc; font-size: 16px; } .dream-points-value { color: #7dd3fc; font-size: 36px; font-weight: bold; text-shadow: 0 0 15px #7dd3fc; animation: dreamPulse 2s ease-in-out infinite; } .spirit-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; max-width: 1200px; margin: 0 auto 30px auto; } .spirit-card { background: rgba(20, 10, 40, 0.95); border: 3px solid rgba(192, 132, 252, 0.5); border-radius: 20px; padding: 20px; animation: ghostFloat 5s ease-in-out infinite; box-shadow: 0 0 25px rgba(192, 132, 252, 0.4); } .spirit-card:nth-child(2) { animation-delay: 0.5s; } .spirit-card:nth-child(3) { animation-delay: 1s; } .spirit-card:nth-child(4) { animation-delay: 1.5s; } .spirit-name { color: #c084fc; font-size: 24px; text-align: center; margin: 0 0 15px 0; text-shadow: 0 0 15px #c084fc; } .spirit-section { margin-bottom: 15px; } .spirit-section-title { color: #7dd3fc; font-size: 14px; font-weight: bold; margin-bottom: 8px; padding-bottom: 5px; border-bottom: 1px solid rgba(125, 211, 252, 0.3); } .spirit-trait-list { display: flex; flex-wrap: wrap; gap: 6px; } .spirit-trait { background: rgba(125, 211, 252, 0.15); border: 1px solid rgba(125, 211, 252, 0.4); color: #ccc; padding: 4px 10px; border-radius: 12px; font-size: 12px; cursor: pointer; transition: all 0.2s ease; white-space: nowrap; } .spirit-trait:hover { background: rgba(125, 211, 252, 0.3); border-color: #7dd3fc; color: #fff; } .spirit-trait .trait-value { color: #51cf66; font-weight: bold; margin-left: 5px; } .spirit-body-info { background: rgba(30, 20, 50, 0.8); border-radius: 10px; padding: 10px; font-size: 13px; color: #aaa; } .spirit-body-row { display: flex; justify-content: space-between; padding: 4px 0; } .spirit-body-value { color: #c084fc; font-weight: bold; } .trade-button { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border: 2px solid #7dd3fc; color: white; padding: 12px 25px; border-radius: 20px; font-weight: bold; cursor: pointer; width: 100%; margin-top: 15px; transition: all 0.3s ease; } .trade-button:hover { box-shadow: 0 0 25px rgba(125, 211, 252, 0.5); transform: scale(1.02); } .dream-section { background: rgba(10, 10, 30, 0.8); border: 2px solid rgba(125, 211, 252, 0.3); border-radius: 15px; padding: 20px; margin: 20px auto; max-width: 1000px; } .dream-section-title { color: #7dd3fc; font-size: 22px; margin: 0 0 15px 0; text-shadow: 0 0 10px rgba(125, 211, 252, 0.5); } .trade-history-item { background: rgba(20, 20, 40, 0.8); border: 2px solid rgba(192, 132, 252, 0.3); border-radius: 10px; padding: 15px; margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } .trade-history-info { flex: 1; } .trade-history-npc { color: #c084fc; font-weight: bold; font-size: 16px; } .trade-history-details { color: #aaa; font-size: 13px; margin-top: 5px; } .undo-button { background: rgba(255, 107, 107, 0.2); border: 2px solid #ff6b6b; color: #ff6b6b; padding: 8px 15px; border-radius: 15px; cursor: pointer; font-weight: bold; transition: all 0.2s ease; } .undo-button:hover { background: rgba(255, 107, 107, 0.4); } .dream-button { background: linear-gradient(135deg, rgba(125, 211, 252, 0.3) 0%, rgba(192, 132, 252, 0.3) 100%); border: 2px solid #7dd3fc; color: #7dd3fc; padding: 15px 40px; border-radius: 25px; font-size: 18px; font-weight: bold; cursor: pointer; transition: all 0.3s ease; text-shadow: 0 0 10px #7dd3fc; display: inline-block; } .dream-button:hover { background: linear-gradient(135deg, rgba(125, 211, 252, 0.5) 0%, rgba(192, 132, 252, 0.5) 100%); box-shadow: 0 0 40px rgba(125, 211, 252, 0.5); } .dream-voice { color: #7dd3fc; font-size: 18px; text-align: center; font-style: italic; margin: 20px 0; text-shadow: 0 0 10px rgba(125, 211, 252, 0.5); } .player-traits-section { background: rgba(30, 30, 50, 0.8); border: 2px solid rgba(81, 207, 102, 0.4); border-radius: 10px; padding: 15px; margin-top: 15px; } .player-traits-title { color: #51cf66; font-size: 16px; font-weight: bold; margin-bottom: 10px; } .your-trait { background: rgba(81, 207, 102, 0.15); border: 1px solid rgba(81, 207, 102, 0.4); color: #ccc; padding: 4px 10px; border-radius: 12px; font-size: 12px; display: inline-block; margin: 3px; white-space: nowrap; } .conversion-info { background: rgba(255, 193, 7, 0.1); border: 2px solid rgba(255, 193, 7, 0.4); border-radius: 10px; padding: 15px; text-align: center; margin-top: 20px; } .conversion-text { color: #ffc107; font-size: 16px; } .conversion-amount { color: #51cf66; font-size: 24px; font-weight: bold; text-shadow: 0 0 10px rgba(81, 207, 102, 0.5); } </style> <div class="dream-container"> <h1 class="dream-title">☽ The Spirits Await ☾</h1> <!-- Trade Points Display --> <div class="dream-points-display"> <span class="dream-points-label">✧ Essence Points ✧</span> <span class="dream-points-value">$dreamTradePoints</span> </div> <p class="dream-voice"> "These spirits carry fragments of identity they may trade with you. Click on any trait to acquire it..." </p> <!-- Spirit NPCs --> <div class="spirit-container"> <<for _i = 0; _i < $dreamNPCs.length; _i++>> <<set _spirit = $dreamNPCs[_i]>> <<capture _i, _spirit>> <div class="spirit-card"> <h3 class="spirit-name"><<print _spirit.name>></h3> <!-- Body Info --> <div class="spirit-section"> <div class="spirit-section-title">🫀 Physical Form</div> <div class="spirit-body-info"> <div class="spirit-body-row"> <span>Gender:</span> <span class="spirit-body-value"><<print _spirit.bodyParts.gender.toUpperFirst()>></span> </div> <div class="spirit-body-row"> <span>Chest:</span> <<set _chestValue = setup.getDreamTradeValue("bodyPart", "chest", _spirit.bodyParts.chest)>> <span class="spirit-body-value"><<print _spirit.bodyParts.chest.toUpperFirst()>> <span style="color: #51cf66;">(<<print _chestValue>>)</span></span> </div> <div class="spirit-body-row"> <span>Butt:</span> <<set _buttValue = setup.getDreamTradeValue("bodyPart", "butt", _spirit.bodyParts.butt)>> <span class="spirit-body-value"><<print _spirit.bodyParts.butt.toUpperFirst()>> <span style="color: #51cf66;">(<<print _buttValue>>)</span></span> </div> <div class="spirit-body-row"> <span>Hair:</span> <span class="spirit-body-value"><<print _spirit.appearance.hairLength.toUpperFirst()>> <<print _spirit.appearance.hairColor>></span> </div> </div> <!-- Trade body parts buttons --> <div style="display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap;"> <<if $dreamPlayer.bodyParts.chest !== _spirit.bodyParts.chest>> <<set _chestCost = setup.getDreamTradeValue("bodyPart", "chest", _spirit.bodyParts.chest)>> <<set _playerChestValue = setup.getDreamTradeValue("bodyPart", "chest", $dreamPlayer.bodyParts.chest)>> <<set _netCost = _chestCost - _playerChestValue>> <<if $dreamTradePoints >= _netCost || _netCost <= 0>> <<link "<span class='spirit-trait'>Swap Chest <span class='trait-value'><<if _netCost > 0>>-<<print _netCost>><<elseif _netCost < 0>>+<<print Math.abs(_netCost)>><<else>>±0<</if>></span></span>">> <<set _calcChestCost = setup.getDreamTradeValue("bodyPart", "chest", _spirit.bodyParts.chest)>> <<set _calcPlayerChestValue = setup.getDreamTradeValue("bodyPart", "chest", $dreamPlayer.bodyParts.chest)>> <<set _calcNetCost = _calcChestCost - _calcPlayerChestValue>> <<set _playerOffer = [{type: "points", value: Math.max(0, _calcNetCost)}, {type: "bodyPart", name: "chest"}]>> <<set _npcOffer = [{type: "bodyPart", name: "chest"}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <</if>> <</if>> <<if $dreamPlayer.bodyParts.butt !== _spirit.bodyParts.butt>> <<set _buttCost = setup.getDreamTradeValue("bodyPart", "butt", _spirit.bodyParts.butt)>> <<set _playerButtValue = setup.getDreamTradeValue("bodyPart", "butt", $dreamPlayer.bodyParts.butt)>> <<set _netCost = _buttCost - _playerButtValue>> <<if $dreamTradePoints >= _netCost || _netCost <= 0>> <<link "<span class='spirit-trait'>Swap Butt <span class='trait-value'><<if _netCost > 0>>-<<print _netCost>><<elseif _netCost < 0>>+<<print Math.abs(_netCost)>><<else>>±0<</if>></span></span>">> <<set _calcButtCost = setup.getDreamTradeValue("bodyPart", "butt", _spirit.bodyParts.butt)>> <<set _calcPlayerButtValue = setup.getDreamTradeValue("bodyPart", "butt", $dreamPlayer.bodyParts.butt)>> <<set _calcNetCost = _calcButtCost - _calcPlayerButtValue>> <<set _playerOffer = [{type: "points", value: Math.max(0, _calcNetCost)}, {type: "bodyPart", name: "butt"}]>> <<set _npcOffer = [{type: "bodyPart", name: "butt"}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <</if>> <</if>> <<if $dreamPlayer.appearance.hairLength !== _spirit.appearance.hairLength || $dreamPlayer.appearance.hairColor !== _spirit.appearance.hairColor>> <<link "<span class='spirit-trait'>Swap Hair <span class='trait-value'>±0</span></span>">> <<set _playerOffer = [{type: "appearance", name: "hairLength"}, {type: "appearance", name: "hairColor"}]>> <<set _npcOffer = [{type: "appearance", name: "hairLength"}, {type: "appearance", name: "hairColor"}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <</if>> </div> </div> <!-- Physical Traits --> <<set _displayPhysical = _spirit.physicalTraits.filter(function(t) { return t !== "Short Hair" && t !== "Long Hair"; })>> <<if _displayPhysical.length > 0>> <div class="spirit-section"> <div class="spirit-section-title">💪 Physical Traits</div> <div class="spirit-trait-list"> <<for _trait range _displayPhysical>> <<capture _trait>> <<set _traitValue = setup.getDreamTradeValue("physical", _trait)>> <<if !$dreamPlayer.physicalTraits.includes(_trait) && $dreamTradePoints >= _traitValue>> <<link "<span class='spirit-trait'><<print _trait>> <span class='trait-value'>-<<print _traitValue>></span></span>">> <<set _calcValue = setup.getDreamTradeValue("physical", _trait)>> <<set _playerOffer = [{type: "points", value: _calcValue}]>> <<set _npcOffer = [{type: "physical", name: _trait}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <<elseif $dreamPlayer.physicalTraits.includes(_trait)>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed;"><<print _trait>> ✓</span> <<else>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed;"><<print _trait>> <span style="color: #ff6b6b;"><<print _traitValue>></span></span> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- Mental Traits --> <<if _spirit.mentalTraits.length > 0>> <div class="spirit-section"> <div class="spirit-section-title">🧠 Mental Traits</div> <div class="spirit-trait-list"> <<for _trait range _spirit.mentalTraits>> <<capture _trait>> <<set _traitValue = setup.getDreamTradeValue("mental", _trait)>> <<if !$dreamPlayer.mentalTraits.includes(_trait) && $dreamTradePoints >= _traitValue>> <<link "<span class='spirit-trait'><<print _trait>> <span class='trait-value'><<if _traitValue >= 0>>-<<print _traitValue>><<else>>+<<print Math.abs(_traitValue)>><</if>></span></span>">> <<set _calcValue = setup.getDreamTradeValue("mental", _trait)>> <<set _playerOffer = [{type: "points", value: Math.max(0, _calcValue)}]>> <<set _npcOffer = [{type: "mental", name: _trait}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <<elseif $dreamPlayer.mentalTraits.includes(_trait)>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed;"><<print _trait>> ✓</span> <<else>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed;"><<print _trait>> <span style="color: #ff6b6b;"><<print _traitValue>></span></span> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- Skills --> <<if _spirit.skills.length > 0>> <div class="spirit-section"> <div class="spirit-section-title">🎯 Skills</div> <div class="spirit-trait-list"> <<for _skill range _spirit.skills>> <<capture _skill>> <<set _skillValue = setup.getDreamTradeValue("skill", _skill)>> <<if !$dreamPlayer.skills.includes(_skill) && $dreamTradePoints >= _skillValue>> <<link "<span class='spirit-trait'><<print _skill>> <span class='trait-value'>-<<print _skillValue>></span></span>">> <<set _calcValue = setup.getDreamTradeValue("skill", _skill)>> <<set _playerOffer = [{type: "points", value: _calcValue}]>> <<set _npcOffer = [{type: "skill", name: _skill}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <<elseif $dreamPlayer.skills.includes(_skill)>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed;"><<print _skill>> ✓</span> <<else>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed;"><<print _skill>> <span style="color: #ff6b6b;"><<print _skillValue>></span></span> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- Jobs (Swap - mutually exclusive) --> <<if _spirit.jobs && _spirit.jobs.length > 0>> <div class="spirit-section"> <div class="spirit-section-title">💼 Job (Swap)</div> <div class="spirit-trait-list"> <<for _job range _spirit.jobs>> <<capture _job>> <<set _npcJobValue = setup.getDreamTradeValue("job", _job)>> <<set _playerJob = ($dreamPlayer.jobs && $dreamPlayer.jobs.length > 0) ? $dreamPlayer.jobs[0] : "Unemployed">> <<set _playerJobValue = (_playerJob !== "Unemployed") ? setup.getDreamTradeValue("job", _playerJob) : 0>> /* Net cost: what you pay after accounting for your job's value */ <<set _netCost = Math.max(0, _npcJobValue) - Math.max(0, _playerJobValue)>> <<set _alreadyHas = $dreamPlayer.jobs && $dreamPlayer.jobs.includes(_job)>> <<if _alreadyHas>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed; border-color: rgba(23, 162, 184, 0.4); background: rgba(23, 162, 184, 0.15);"><<print _job>> ✓</span> <<elseif $dreamTradePoints >= _netCost || _netCost <= 0>> <<link "<span class='spirit-trait' style='border-color: rgba(23, 162, 184, 0.4); background: rgba(23, 162, 184, 0.15);'><<print _playerJob>> ↔ <<print _job>> <span class='trait-value'><<if _netCost > 0>>-<<print _netCost>><<elseif _netCost < 0>>+<<print Math.abs(_netCost)>><<else>>±0<</if>></span></span>">> /* Recalculate at click time */ <<set _calcNpcJobValue = setup.getDreamTradeValue("job", _job)>> <<set _calcPlayerJob = ($dreamPlayer.jobs && $dreamPlayer.jobs.length > 0) ? $dreamPlayer.jobs[0] : "Unemployed">> <<set _calcPlayerJobValue = (_calcPlayerJob !== "Unemployed") ? setup.getDreamTradeValue("job", _calcPlayerJob) : 0>> <<set _calcNetCost = Math.max(0, _calcNpcJobValue) - Math.max(0, _calcPlayerJobValue)>> /* Only pass points - job swap is handled separately */ <<set _playerOffer = [{type: "points", value: Math.max(0, _calcNetCost)}]>> <<set _npcOffer = [{type: "job", name: _job, playerOldJob: _calcPlayerJob}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <<else>> <span class="spirit-trait" style="opacity: 0.4; cursor: not-allowed; border-color: rgba(23, 162, 184, 0.4); background: rgba(23, 162, 184, 0.15);"><<print _playerJob>> ↔ <<print _job>> <span style="color: #ff6b6b;"><<print _netCost>></span></span> <</if>> <</capture>> <</for>> </div> </div> <</if>> <!-- Name Trade --> <div class="spirit-section"> <div class="spirit-section-title">👤 Name</div> <<set _nameParts = _spirit.name.split(" ")>> <<set _firstName = _nameParts[0]>> <<set _lastName = _nameParts.slice(1).join(" ")>> <div style="display: flex; gap: 8px; flex-wrap: wrap;"> <<if $dreamPlayer.firstName !== _firstName>> <<link "<span class='spirit-trait'>First: <<print _firstName>> <span class='trait-value' style='color: #7dd3fc;'>FREE</span></span>">> <<set _playerOffer = []>> <<set _npcOffer = [{type: "name", which: "first"}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <</if>> <<if $dreamPlayer.lastName !== _lastName>> <<link "<span class='spirit-trait'>Last: <<print _lastName>> <span class='trait-value' style='color: #7dd3fc;'>FREE</span></span>">> <<set _playerOffer = []>> <<set _npcOffer = [{type: "name", which: "last"}]>> <<run setup.executeDreamTrade(_i, _playerOffer, _npcOffer)>> <<goto "DreamTrading">> <</link>> <</if>> </div> </div> </div> <</capture>> <</for>> </div> <!-- Trade History / Undo Section --> <<if $dreamTradeHistory.length > 0>> <div class="dream-section"> <h3 class="dream-section-title">📜 Trade History (Click to Undo)</h3> <<for _j = $dreamTradeHistory.length - 1; _j >= 0; _j-->> <<set _trade = $dreamTradeHistory[_j]>> <<capture _j, _trade>> <div class="trade-history-item"> <div class="trade-history-info"> <div class="trade-history-npc">Trade #<<print _j + 1>> with <<print _trade.npcName>></div> <div class="trade-history-details"> Spent: <<print _trade.playerOfferValue>> pts | Received: <<print _trade.npcOfferValue>> value <<if _trade.refundedPoints > 0>> | Refunded: <<print _trade.refundedPoints>> pts <</if>> </div> </div> <<link "<span class='undo-button'>↩ Undo</span>">> <<run setup.undoDreamTrade(_j)>> <<goto "DreamTrading">> <</link>> </div> <</capture>> <</for>> </div> <</if>> <!-- Your Current Build --> <div class="dream-section"> <h3 class="dream-section-title">✨ Your Current Form</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;"> <div> <div style="color: #c084fc; font-weight: bold; margin-bottom: 10px;">Identity</div> <div style="color: #ccc; font-size: 14px; line-height: 1.8;"> <strong>Name:</strong> $dreamPlayer.firstName $dreamPlayer.lastName<br> <strong>Gender:</strong> <<print $dreamPlayer.bodyParts.gender.toUpperFirst()>><br> <strong>Chest:</strong> <<print $dreamPlayer.bodyParts.chest.toUpperFirst()>><br> <strong>Butt:</strong> <<print $dreamPlayer.bodyParts.butt.toUpperFirst()>><br> <strong>Hair:</strong> <<print $dreamPlayer.appearance.hairLength.toUpperFirst()>> <<print $dreamPlayer.appearance.hairColor>><br> <<if $dreamPlayer.jobs && $dreamPlayer.jobs.length > 0>> <strong>Job:</strong> <<print $dreamPlayer.jobs.join(", ")>> <<else>> <strong>Job:</strong> <span style="color: #888;">Unemployed</span> <</if>> </div> </div> <div> <<if $dreamPlayer.physicalTraits.length > 0 || $dreamPlayer.mentalTraits.length > 0 || $dreamPlayer.skills.length > 0>> <<set _displayPlayerPhysical = $dreamPlayer.physicalTraits.filter(function(t) { return t !== "Short Hair" && t !== "Long Hair"; })>> <<if _displayPlayerPhysical.length > 0>> <div style="margin-bottom: 10px;"> <div style="color: #51cf66; font-weight: bold; margin-bottom: 5px; font-size: 14px;">Physical:</div> <<for _t range _displayPlayerPhysical>> <span class="your-trait"><<print _t>></span> <</for>> </div> <</if>> <<if $dreamPlayer.mentalTraits.length > 0>> <div style="margin-bottom: 10px;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 5px; font-size: 14px;">Mental:</div> <<for _t range $dreamPlayer.mentalTraits>> <span class="your-trait" style="border-color: rgba(155, 89, 182, 0.4); background: rgba(155, 89, 182, 0.15);"><<print _t>></span> <</for>> </div> <</if>> <<if $dreamPlayer.skills.length > 0>> <div style="margin-bottom: 10px;"> <div style="color: #ffc107; font-weight: bold; margin-bottom: 5px; font-size: 14px;">Skills:</div> <<for _s range $dreamPlayer.skills>> <span class="your-trait" style="border-color: rgba(255, 193, 7, 0.4); background: rgba(255, 193, 7, 0.15);"><<print _s>></span> <</for>> </div> <</if>> <<if $dreamPlayer.jobs && $dreamPlayer.jobs.length > 0>> <div> <div style="color: #17a2b8; font-weight: bold; margin-bottom: 5px; font-size: 14px;">Jobs:</div> <<for _j range $dreamPlayer.jobs>> <span class="your-trait" style="border-color: rgba(23, 162, 184, 0.4); background: rgba(23, 162, 184, 0.15);"><<print _j>></span> <</for>> </div> <</if>> <<else>> <div style="color: #888; font-style: italic;">No traits or skills acquired yet...</div> <</if>> </div> </div> </div> <!-- Point Conversion Info --> <div class="conversion-info"> <div class="conversion-text"> Remaining points will convert to starting money: </div> <div class="conversion-amount"> $<<print $dreamTradePoints * 10>> </div> <div style="color: #888; font-size: 14px; margin-top: 5px;"> (<<print $dreamTradePoints>> points × $10 each) </div> </div> <!-- Navigation --> <div style="text-align: center; margin-top: 40px; display: flex; justify-content: center; gap: 20px;"> <<link "<span class='dream-button' style='border-color: #888; color: #888;'>← Back to Form</span>">> <<goto "DreamGenderSelect">> <</link>> <<link "<span class='dream-button'>Finalize & Awaken ✧</span>">> <<goto "DreamSummary">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes dreamPulse { 0%, 100% { text-shadow: 0 0 10px #7dd3fc, 0 0 20px #7dd3fc; opacity: 0.9; } 50% { text-shadow: 0 0 20px #7dd3fc, 0 0 40px #7dd3fc, 0 0 60px #7dd3fc; opacity: 1; } } @keyframes voidSwirl { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes fadeAwaken { 0% { opacity: 1; } 50% { opacity: 0; } 100% { opacity: 1; background: #1a1a1a; } } .dream-container { background: linear-gradient(135deg, #0a0a1a 0%, #1a0a2e 50%, #0a1a2e 100%); min-height: 100vh; padding: 30px 20px; } .dream-title { color: #c084fc; font-size: 36px; text-align: center; text-shadow: 0 0 20px #c084fc, 0 0 40px #a855f7; margin-bottom: 30px; } .dream-section { background: rgba(10, 10, 30, 0.9); border: 2px solid rgba(125, 211, 252, 0.3); border-radius: 15px; padding: 25px; margin: 20px auto; max-width: 800px; box-shadow: 0 0 20px rgba(125, 211, 252, 0.15); } .dream-section-title { color: #7dd3fc; font-size: 22px; margin: 0 0 20px 0; padding-bottom: 10px; border-bottom: 2px solid rgba(125, 211, 252, 0.3); text-shadow: 0 0 10px rgba(125, 211, 252, 0.5); } .summary-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; } .summary-item { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid rgba(125, 211, 252, 0.1); } .summary-item:last-child { border-bottom: none; } .summary-label { color: #888; font-size: 16px; } .summary-value { color: #c084fc; font-weight: bold; font-size: 16px; } .trait-tag { display: inline-block; padding: 6px 14px; border-radius: 20px; font-size: 14px; margin: 4px; font-weight: 500; } .trait-physical { background: rgba(81, 207, 102, 0.2); border: 1px solid rgba(81, 207, 102, 0.5); color: #51cf66; } .trait-mental { background: rgba(155, 89, 182, 0.2); border: 1px solid rgba(155, 89, 182, 0.5); color: #9b59b6; } .trait-skill { background: rgba(255, 193, 7, 0.2); border: 1px solid rgba(255, 193, 7, 0.5); color: #ffc107; } .trait-job { background: rgba(23, 162, 184, 0.2); border: 1px solid rgba(23, 162, 184, 0.5); color: #17a2b8; } .trait-negative { background: rgba(255, 107, 107, 0.2); border: 1px solid rgba(255, 107, 107, 0.5); color: #ff6b6b; } .money-display { background: linear-gradient(135deg, rgba(81, 207, 102, 0.3) 0%, rgba(40, 167, 69, 0.3) 100%); border: 3px solid #51cf66; border-radius: 15px; padding: 25px; text-align: center; margin: 25px auto; max-width: 400px; box-shadow: 0 0 30px rgba(81, 207, 102, 0.3); } .money-label { color: #51cf66; font-size: 18px; margin-bottom: 10px; } .money-value { color: #51cf66; font-size: 48px; font-weight: bold; text-shadow: 0 0 20px rgba(81, 207, 102, 0.5); } .money-detail { color: #aaa; font-size: 14px; margin-top: 10px; } .dream-voice { color: #7dd3fc; font-size: 20px; text-align: center; font-style: italic; margin: 30px 0; animation: dreamPulse 3s ease-in-out infinite; line-height: 1.8; } .dream-voice-emphasis { color: #c084fc; font-weight: bold; } .dream-button { background: linear-gradient(135deg, rgba(125, 211, 252, 0.3) 0%, rgba(192, 132, 252, 0.3) 100%); border: 2px solid #7dd3fc; color: #7dd3fc; padding: 18px 50px; border-radius: 30px; font-size: 20px; font-weight: bold; cursor: pointer; transition: all 0.3s ease; text-shadow: 0 0 10px #7dd3fc; display: inline-block; } .dream-button:hover { background: linear-gradient(135deg, rgba(125, 211, 252, 0.5) 0%, rgba(192, 132, 252, 0.5) 100%); box-shadow: 0 0 40px rgba(125, 211, 252, 0.5), 0 0 60px rgba(192, 132, 252, 0.3); transform: scale(1.05); } .dream-button.awaken { background: linear-gradient(135deg, rgba(192, 132, 252, 0.4) 0%, rgba(255, 193, 7, 0.4) 100%); border-color: #c084fc; color: #fff; font-size: 24px; padding: 20px 60px; } .warning-box { background: rgba(255, 193, 7, 0.1); border: 2px solid rgba(255, 193, 7, 0.5); border-radius: 10px; padding: 20px; margin: 20px auto; max-width: 600px; text-align: center; } .warning-text { color: #ffc107; font-size: 16px; } .divider { height: 2px; background: linear-gradient(90deg, transparent, #7dd3fc, #c084fc, #7dd3fc, transparent); margin: 30px 0; opacity: 0.5; } </style> <div class="dream-container"> <h1 class="dream-title">☽ Your New Self ☾</h1> <p class="dream-voice"> "Behold the form you shall carry into the waking world..." </p> <!-- Identity Section --> <div class="dream-section"> <h2 class="dream-section-title">👤 Identity</h2> <div class="summary-grid"> <div> <div class="summary-item"> <span class="summary-label">Name:</span> <span class="summary-value">$dreamPlayer.firstName $dreamPlayer.lastName</span> </div> <div class="summary-item"> <span class="summary-label">Gender:</span> <span class="summary-value"><<print $dreamPlayer.bodyParts.gender.toUpperFirst()>></span> </div> <div class="summary-item"> <span class="summary-label">Age:</span> <span class="summary-value"><<print $dreamPlayer.appearance.age>></span> </div> </div> <div> <div class="summary-item"> <span class="summary-label">Skin:</span> <span class="summary-value"><<print $dreamPlayer.appearance.skinTone.toUpperFirst()>></span> </div> <div class="summary-item"> <span class="summary-label">Hair:</span> <span class="summary-value"><<print $dreamPlayer.appearance.hairLength.toUpperFirst()>> <<print $dreamPlayer.appearance.hairColor>></span> </div> </div> </div> </div> <!-- Body Section --> <div class="dream-section"> <h2 class="dream-section-title">🫀 Physical Form</h2> <div class="summary-grid"> <div> <div class="summary-item"> <span class="summary-label">Chest:</span> <span class="summary-value"><<print $dreamPlayer.bodyParts.chest.toUpperFirst()>></span> </div> <div class="summary-item"> <span class="summary-label">Butt:</span> <span class="summary-value"><<print $dreamPlayer.bodyParts.butt.toUpperFirst()>></span> </div> </div> <div> <div class="summary-item"> <span class="summary-label">Genitals:</span> <span class="summary-value"><<print $dreamPlayer.bodyParts.genitals.toUpperFirst()>></span> </div> </div> </div> </div> <!-- Traits Section --> <<set _displayPhysical = $dreamPlayer.physicalTraits.filter(function(t) { return t !== "Short Hair" && t !== "Long Hair"; })>> <<set _positiveTraits = _displayPhysical.filter(function(t) { return !$dreamPlayer.negativeTraits.some(function(n) { return n.name === t; }); })>> <<set _negTraitsPhysical = $dreamPlayer.negativeTraits.filter(function(t) { return t.type === "physical"; })>> <<set _negTraitsMental = $dreamPlayer.negativeTraits.filter(function(t) { return t.type === "mental"; })>> <<set _positiveMental = $dreamPlayer.mentalTraits.filter(function(t) { return !$dreamPlayer.negativeTraits.some(function(n) { return n.name === t; }); })>> <<if _positiveTraits.length > 0 || _positiveMental.length > 0 || $dreamPlayer.skills.length > 0 || ($dreamPlayer.jobs && $dreamPlayer.jobs.length > 0)>> <div class="dream-section"> <h2 class="dream-section-title">✨ Acquired Traits & Skills</h2> <<if _positiveTraits.length > 0>> <div style="margin-bottom: 20px;"> <div style="color: #51cf66; font-weight: bold; margin-bottom: 10px; font-size: 16px;">💪 Physical Traits:</div> <div> <<for _t range _positiveTraits>> <span class="trait-tag trait-physical"><<print _t>></span> <</for>> </div> </div> <</if>> <<if _positiveMental.length > 0>> <div style="margin-bottom: 20px;"> <div style="color: #9b59b6; font-weight: bold; margin-bottom: 10px; font-size: 16px;">🧠 Mental Traits:</div> <div> <<for _t range _positiveMental>> <span class="trait-tag trait-mental"><<print _t>></span> <</for>> </div> </div> <</if>> <<if $dreamPlayer.skills.length > 0>> <div style="margin-bottom: 20px;"> <div style="color: #ffc107; font-weight: bold; margin-bottom: 10px; font-size: 16px;">🎯 Skills:</div> <div> <<for _s range $dreamPlayer.skills>> <span class="trait-tag trait-skill"><<print _s>></span> <</for>> </div> </div> <</if>> <<if $dreamPlayer.jobs && $dreamPlayer.jobs.length > 0>> <div> <div style="color: #17a2b8; font-weight: bold; margin-bottom: 10px; font-size: 16px;">💼 Jobs:</div> <div> <<for _j range $dreamPlayer.jobs>> <span class="trait-tag trait-job"><<print _j>></span> <</for>> </div> </div> <</if>> </div> <</if>> <!-- Negative Traits Section --> <<if $dreamPlayer.negativeTraits.length > 0>> <div class="dream-section" style="border-color: rgba(255, 107, 107, 0.3);"> <h2 class="dream-section-title" style="color: #ff6b6b; border-color: rgba(255, 107, 107, 0.3);">⚠️ Burdens Accepted</h2> <div> <<for _neg range $dreamPlayer.negativeTraits>> <span class="trait-tag trait-negative"><<print _neg.name>></span> <</for>> </div> </div> <</if>> <div class="divider"></div> <!-- Starting Money --> <div class="money-display"> <div class="money-label">💰 Starting Funds</div> <div class="money-value">$<<print $dreamTradePoints * 10>></div> <div class="money-detail"> <<print $dreamTradePoints>> essence points × $10 each </div> </div> <!-- Warning Box --> <div class="warning-box"> <div class="warning-text"> ⚠️ Once you awaken, these choices become permanent.<br> You will remember nothing of this dream. </div> </div> <div class="divider"></div> <p class="dream-voice"> <span class="dream-voice-emphasis">"Are you ready to begin your journey, wanderer?"</span> </p> <!-- Navigation --> <div style="text-align: center; margin-top: 40px; display: flex; justify-content: center; gap: 30px; flex-wrap: wrap;"> <<link "<span class='dream-button' style='border-color: #888; color: #888;'>← Return to Trading</span>">> <<goto "DreamTrading">> <</link>> <<link "<span class='dream-button awaken'>✧ Awaken ✧</span>">> /* Finalize the dream state and transfer to actual player */ <<run setup.finalizeDreamState()>> /* Skip time advancement on first passage */ <<set $skipTimeAdvancement = true>> /* Unlock first achievement */ <<run setup.achievements.unlock("first_character")>> /* Go to the awakening/alleyway */ <<goto "DreamAwakening">> <</link>> </div> <</nobr>>
<<nobr>> <style> @keyframes fadeFromDream { 0% { background: #0a0a1a; opacity: 0; } 30% { background: #0a0a1a; opacity: 1; } 70% { background: #0a0a1a; opacity: 1; } 100% { background: #1a1a1a; opacity: 1; } } @keyframes textFadeIn { 0% { opacity: 0; transform: translateY(20px); } 100% { opacity: 1; transform: translateY(0); } } @keyframes pulseGlow { 0%, 100% { text-shadow: 0 0 10px rgba(125, 211, 252, 0.5); } 50% { text-shadow: 0 0 30px rgba(125, 211, 252, 0.8), 0 0 50px rgba(192, 132, 252, 0.4); } } .awakening-container { background: #0a0a1a; min-height: 100vh; padding: 40px 20px; animation: fadeFromDream 4s ease-out forwards; display: flex; flex-direction: column; justify-content: center; align-items: center; } .awakening-text { color: #7dd3fc; font-size: 24px; text-align: center; font-style: italic; line-height: 2; max-width: 700px; animation: textFadeIn 2s ease-out; } .awakening-text.delayed-1 { animation-delay: 1s; animation-fill-mode: backwards; } .awakening-text.delayed-2 { animation-delay: 2.5s; animation-fill-mode: backwards; } .awakening-text.delayed-3 { animation-delay: 4s; animation-fill-mode: backwards; } .awakening-emphasis { color: #c084fc; font-weight: bold; animation: pulseGlow 2s ease-in-out infinite; } .awakening-divider { height: 2px; width: 200px; background: linear-gradient(90deg, transparent, #7dd3fc, transparent); margin: 40px 0; animation: textFadeIn 2s ease-out; animation-delay: 3s; animation-fill-mode: backwards; } .awakening-button { background: linear-gradient(135deg, rgba(125, 211, 252, 0.2) 0%, rgba(192, 132, 252, 0.2) 100%); border: 2px solid #7dd3fc; color: #7dd3fc; padding: 18px 50px; border-radius: 30px; font-size: 20px; font-weight: bold; cursor: pointer; transition: all 0.3s ease; animation: textFadeIn 2s ease-out; animation-delay: 5s; animation-fill-mode: backwards; } .awakening-button:hover { background: linear-gradient(135deg, rgba(125, 211, 252, 0.4) 0%, rgba(192, 132, 252, 0.4) 100%); box-shadow: 0 0 30px rgba(125, 211, 252, 0.5); transform: scale(1.05); } .fade-to-reality { color: #aaa; font-size: 18px; margin-top: 30px; animation: textFadeIn 2s ease-out; animation-delay: 4.5s; animation-fill-mode: backwards; } </style> <div class="awakening-container"> <p class="awakening-text"> The voice fades... the void dissolves... </p> <p class="awakening-text delayed-1"> You feel yourself <span class="awakening-emphasis">falling</span>... drifting through layers of consciousness... </p> <div class="awakening-divider"></div> <p class="awakening-text delayed-2"> The dream slips away like water through your fingers. <br> You grasp at fragments — <span class="awakening-emphasis">spirits</span>, <span class="awakening-emphasis">trades</span>, <span class="awakening-emphasis">transformations</span> — <br> but they dissolve into mist... </p> <p class="awakening-text delayed-3"> All that remains is a single whisper: <br><br> <span class="awakening-emphasis">"The Island of the Sunfish awaits..."</span> </p> <p class="fade-to-reality"> ...and then you open your eyes. </p> <div style="margin-top: 50px;"> <<link "<span class='awakening-button'>Open Your Eyes</span>">> <<goto "Alleyway">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Safety check - make sure the function exists and _stream is defined --> <<if _stream && typeof setup.getTrendDisplay === "function">> <<set _trendInfo = setup.getTrendDisplay(_stream.category)>> <<set _hour = $gameTime ? $gameTime.hour : Math.floor(($timeInMinutes || 0) / 60) % 24>> <!-- Determine time slot name --> <<if _hour >= 6 && _hour < 12>> <<set _timeSlot = "Morning">> <<set _timeIcon = "🌅">> <<elseif _hour >= 12 && _hour < 18>> <<set _timeSlot = "Afternoon">> <<set _timeIcon = "☀️">> <<elseif _hour >= 18 && _hour < 24>> <<set _timeSlot = "Prime Time">> <<set _timeIcon = "🌆">> <<else>> <<set _timeSlot = "Late Night">> <<set _timeIcon = "🌙">> <</if>> <<if _trendInfo && _trendInfo.descriptions && _trendInfo.descriptions.length > 0>> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); padding: 20px; border-radius: 12px; border: 3px solid #e94560; box-shadow: 0 4px 15px rgba(233, 69, 96, 0.3); margin-bottom: 25px;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <h2 style="color: #e94560; margin: 0; font-size: 20px;">📊 What's Trending</h2> <div style="background: #0f3460; padding: 8px 15px; border-radius: 20px; border: 2px solid #e94560;"> <span style="color: #ffd; font-size: 14px;"><<= _timeIcon>> <<= _timeSlot>></span> </div> </div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _i = 0; _i < _trendInfo.descriptions.length; _i++>> <<set _desc = _trendInfo.descriptions[_i]>> <<if _i === 0>> <!-- Primary trend --> <div style="background: linear-gradient(135deg, #e94560 0%, #ff6b6b 100%); padding: 10px 18px; border-radius: 25px; color: white; font-weight: bold; font-size: 14px; animation: pulse-trend 2s infinite;"> <<= _desc>> </div> <<else>> <!-- Secondary trends --> <div style="background: #0f3460; padding: 8px 15px; border-radius: 20px; color: #ffd; font-size: 13px; border: 2px solid #e94560;"> <<= _desc>> </div> <</if>> <</for>> </div> <p style="color: #aaa; font-size: 12px; margin: 15px 0 0 0; font-style: italic;"> 💡 Trending actions get bonus viewers, engagement, and tips! Trends change daily. </p> </div> <</if>> <</if>> <style> @keyframes pulse-trend { 0%, 100% { box-shadow: 0 0 10px rgba(233, 69, 96, 0.5); } 50% { box-shadow: 0 0 20px rgba(233, 69, 96, 0.8); } } </style> <</nobr>>
<<nobr>> /* Check if player has completed character creation - redirect if not */ <<if !setup.achievements.isUnlocked("first_character")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ff6b6b; border-radius: 15px; padding: 40px; max-width: 500px; text-align: center; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="font-size: 64px; margin-bottom: 20px;">🔒</div> <h2 style="color: #ff6b6b; margin: 0 0 15px 0;">Achievements Locked</h2> <p style="color: #aaa; font-size: 16px; margin: 0 0 25px 0;"> You must complete character creation first to access achievements. </p> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); display: inline-block;'>Start Game</div>">> <<goto "Start">> <</link>> </div> </div> <<else>> <<set _achColor = "#ffd700">> <<set _stats = setup.achievements.getStats()>> <<set _stStats = setup.skillTree.getStats()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Return to Game Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044; display: inline-block;'>← Return to Game</div>">> <<goto $lastLocation>> <</link>> </div> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, <<= _achColor>> 0%, <<= _achColor>>aa 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid <<= _achColor>>; box-shadow: 0 0 20px <<= _achColor>>66;"> <h1 style="color: #1a1a1a; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(255,255,255,0.3);">🏆 Achievements</h1> </div> <!-- Skill Tree Button --> <div style="text-align: center; margin-bottom: 25px;"> <<link "<div style='background: linear-gradient(135deg, #9C27B0 0%, #673AB7 100%); border: 3px solid #CE93D8; color: white; padding: 18px 40px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 25px rgba(156,39,176,0.5); display: inline-block;'>✨ Open Skill Tree ✨</div>">> <<goto "SkillTree">> <</link>> <div style="color: #888; font-size: 14px; margin-top: 10px;">Spend your <span style="color: #CE93D8; font-weight: bold;"><<= _stStats.availablePoints>></span> points on permanent upgrades!</div> </div> <!-- Stats Summary --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; border-radius: 15px; padding: 20px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044;"> <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; text-align: center;"> <div> <div style="color: #ffd700; font-size: 32px; font-weight: bold;"><<= _stats.unlocked>>/<<= _stats.total>></div> <div style="color: #aaa; font-size: 14px;">Unlocked</div> </div> <div> <div style="color: #ffd700; font-size: 32px; font-weight: bold;"><<= _stats.percentage>>%</div> <div style="color: #aaa; font-size: 14px;">Complete</div> </div> <div> <div style="color: #ffd700; font-size: 32px; font-weight: bold;"><<= _stats.points>></div> <div style="color: #aaa; font-size: 14px;">Points</div> </div> </div> </div> <!-- Achievement List --> <div style="max-width: 900px; margin: 0 auto;"> <<for _ach range setup.achievements.list>> <<set _tierInfo = setup.achievements.tiers[_ach.tier]>> <<if _ach.unlocked>> <!-- Unlocked Achievement --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid <<= _tierInfo.color>>; border-radius: 15px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<= _tierInfo.color>>44;"> <div style="display: flex; align-items: center; gap: 20px;"> <div style="font-size: 48px; flex-shrink: 0;"><<= _tierInfo.icon>></div> <div style="flex-grow: 1;"> <div style="color: <<= _tierInfo.color>>; font-size: 20px; font-weight: bold; margin-bottom: 5px;"><<= _ach.name>></div> <div style="color: #ccc; font-size: 14px; margin-bottom: 8px;"><<= _ach.description>></div> <div style="display: flex; gap: 15px; font-size: 12px;"> <span style="color: #888;">Tier: <span style="color: <<= _tierInfo.color>>;text-transform: capitalize;"><<= _ach.tier>></span></span> <span style="color: #888;">Points: <span style="color: #ffd700;"><<= _ach.points>></span></span> </div> </div> </div> </div> <<else>> <!-- Locked Achievement --> <div style="background: linear-gradient(135deg, #1a1a1a 0%, #0d0d0d 100%); border: 3px solid #333; border-radius: 15px; padding: 20px; margin-bottom: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.6); opacity: 0.6;"> <div style="display: flex; align-items: center; gap: 20px;"> <div style="font-size: 48px; flex-shrink: 0; filter: grayscale(100%);">🔒</div> <div style="flex-grow: 1;"> <div style="color: #666; font-size: 20px; font-weight: bold; margin-bottom: 5px;">???</div> <div style="color: #555; font-size: 14px; margin-bottom: 8px; font-style: italic;"><<= _ach.hint>></div> <div style="display: flex; gap: 15px; font-size: 12px;"> <span style="color: #444;">Tier: <span style="color: #666; text-transform: capitalize;"><<= _ach.tier>></span></span> <span style="color: #444;">Points: <span style="color: #666;"><<= _ach.points>></span></span> </div> </div> </div> </div> <</if>> <</for>> </div> <!-- Return to Game Button (Bottom) --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #ffd70044; display: inline-block;'>← Return to Game</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<if !$questTab>><<set $questTab = "active">><</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Back</div>">><<goto $lastLocation>><</link>> </div> <h1 style="color: #3498db; text-align: center; margin: 0 0 20px 0;">📜 Quests</h1> <!-- Tab Navigation --> <<set _activeBg = ($questTab === "active") ? "#4dabf7" : "linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)">> <<set _activeShadow = ($questTab === "active") ? "0 4px 8px rgba(0,0,0,0.4), 0 0 15px #4dabf788" : "0 4px 8px rgba(0,0,0,0.4)">> <<set _completedBg = ($questTab === "completed") ? "#51cf66" : "linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)">> <<set _completedShadow = ($questTab === "completed") ? "0 4px 8px rgba(0,0,0,0.4), 0 0 15px #51cf6688" : "0 4px 8px rgba(0,0,0,0.4)">> <<set _discoveredBg = ($questTab === "all") ? "#f0ad4e" : "linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)">> <<set _discoveredShadow = ($questTab === "all") ? "0 4px 8px rgba(0,0,0,0.4), 0 0 15px #f0ad4e88" : "0 4px 8px rgba(0,0,0,0.4)">> <div style="display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center;"> <<link "<div id='questTabActive' style='border: 3px solid #4dabf7; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>📋 Active</div>">><<set $questTab = "active">><<goto "Quests">><</link>> <<link "<div id='questTabCompleted' style='border: 3px solid #51cf66; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>✅ Completed</div>">><<set $questTab = "completed">><<goto "Quests">><</link>> <<link "<div id='questTabAll' style='border: 3px solid #f0ad4e; color: white; padding: 12px 20px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'>📜 All</div>">><<set $questTab = "all">><<goto "Quests">><</link>> </div> <<script>> $(function() { var qt = State.variables.questTab || "active"; var tabs = { active: {id: "questTabActive", bg: "#4dabf7", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(77,171,247,0.53)"}, completed: {id: "questTabCompleted", bg: "#51cf66", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(81,207,102,0.53)"}, all: {id: "questTabAll", bg: "#f0ad4e", shadow: "0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(240,173,78,0.53)"} }; Object.keys(tabs).forEach(function(key) { var el = document.getElementById(tabs[key].id); if (!el) return; if (key === qt) { el.style.background = tabs[key].bg; el.style.boxShadow = tabs[key].shadow; } else { el.style.background = "linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)"; el.style.boxShadow = "0 4px 8px rgba(0,0,0,0.4)"; } }); }); <</script>> <!-- Tab Content --> <<if $questTab === "active">><<set _tabColor = "#4dabf7">><<elseif $questTab === "completed">><<set _tabColor = "#51cf66">><<elseif $questTab === "all">><<set _tabColor = "#f0ad4e">><<else>><<set _tabColor = "#4dabf7">><</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _tabColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _tabColor>>44;"> <<if $questTab === "active">> <<include "QuestTabActive">> <<elseif $questTab === "completed">> <<include "QuestTabCompleted">> <<elseif $questTab === "all">> <<include "QuestTabAll">> <</if>> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Back</div>">><<goto $lastLocation>><</link>> </div> </div> <</nobr>>
<<nobr>> <<set _categoryIcons = {exploration: "🗺️", social: "💬", work: "💼", combat: "⚔️", mystery: "🔍", transformation: "✨"}>> <<set _activeIds = Object.keys($questData.active)>> <<if _activeIds.length === 0>> <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 12px; padding: 40px 20px; text-align: center;"> <p style="color: #666; font-size: 18px; margin: 0 0 10px 0;">No active quests</p> <p style="color: #555; font-size: 14px; margin: 0;">Discover quests by exploring the city, talking to NPCs, and trying new activities.</p> </div> <<else>> /* Main Quests */ <<set _hasMain = false>> <<for _qi = 0; _qi < _activeIds.length; _qi++>> <<set _qid = _activeIds[_qi]>> <<set _qdef = setup.quests[_qid]>> <<if _qdef && _qdef.type === "main">><<set _hasMain = true>><</if>> <</for>> <<if _hasMain>> <div style="color: #f0ad4e; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">⭐ Main Quests</div> <<for _qi = 0; _qi < _activeIds.length; _qi++>> <<set _qid = _activeIds[_qi]>> <<set _qdef = setup.quests[_qid]>> <<if _qdef && _qdef.type === "main">> <<set _qactive = $questData.active[_qid]>> <<set _qstep = _qdef.steps[_qactive.step]>> <<set _qicon = _categoryIcons[_qdef.category] || "📋">> <<set _qprogress = setup.questSystem.getProgressText(_qid)>> <div style="background: #2a2a2a; border: 2px solid #f0ad4e; border-radius: 10px; padding: 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div style="color: #f0ad4e; font-weight: bold; font-size: 15px;"><<= _qicon>> <<= _qdef.name>></div> <div style="color: #888; font-size: 12px;">Day <<= _qactive.startedDay>></div> </div> <div style="color: #ccc; font-size: 13px; margin-top: 8px;"><<= _qdef.description>></div> <<if _qstep>> <div style="color: #4dabf7; font-size: 13px; margin-top: 8px; padding: 8px; background: #1a1a2e; border-radius: 6px; border-left: 3px solid #4dabf7;"> ▶ <<= _qstep.description>> <<if _qprogress>> <span style="color: #51cf66; font-weight: bold;">(<<= _qprogress>>)</span><</if>> </div> <</if>> <<if _qactive.inventory && _qactive.inventory.length > 0>> <div style="margin-top: 8px; font-size: 12px; color: #b197fc;"> 🎒 Items: <<for _ii = 0; _ii < _qactive.inventory.length; _ii++>><<set _itemDef = _qdef.items ? _qdef.items[_qactive.inventory[_ii]] : null>><<if _ii > 0>>, <</if>><<= _itemDef ? _itemDef.name : _qactive.inventory[_ii]>><</for>> </div> <</if>> <<if _qdef.involvedNPCs && _qdef.involvedNPCs.length > 0>> <div style="margin-top: 5px; font-size: 12px; color: #888;">👤 Involved: <<= _qdef.involvedNPCs.join(", ")>></div> <</if>> </div> <</if>> <</for>> <</if>> /* Side Quests */ <<set _hasSide = false>> <<for _qi = 0; _qi < _activeIds.length; _qi++>> <<set _qid = _activeIds[_qi]>> <<set _qdef = setup.quests[_qid]>> <<if _qdef && _qdef.type === "side">><<set _hasSide = true>><</if>> <</for>> <<if _hasSide>> <div style="color: #4dabf7; font-weight: bold; font-size: 16px; margin: 15px 0 10px 0; border-bottom: 1px solid #444; padding-bottom: 8px;">📋 Side Quests</div> <<for _qi = 0; _qi < _activeIds.length; _qi++>> <<set _qid = _activeIds[_qi]>> <<set _qdef = setup.quests[_qid]>> <<if _qdef && _qdef.type === "side">> <<set _qactive = $questData.active[_qid]>> <<set _qstep = _qdef.steps[_qactive.step]>> <<set _qicon = _categoryIcons[_qdef.category] || "📋">> <<set _qprogress = setup.questSystem.getProgressText(_qid)>> <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 10px; padding: 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div style="color: #4dabf7; font-weight: bold; font-size: 14px;"><<= _qicon>> <<= _qdef.name>></div> <div style="color: #888; font-size: 12px;">Day <<= _qactive.startedDay>></div> </div> <<if _qstep>> <div style="color: #ccc; font-size: 13px; margin-top: 8px; padding: 8px; background: #1a1a2e; border-radius: 6px; border-left: 3px solid #4dabf7;"> ▶ <<= _qstep.description>> <<if _qprogress>> <span style="color: #51cf66; font-weight: bold;">(<<= _qprogress>>)</span><</if>> </div> <</if>> <<if _qactive.inventory && _qactive.inventory.length > 0>> <div style="margin-top: 8px; font-size: 12px; color: #b197fc;"> 🎒 Items: <<for _ii = 0; _ii < _qactive.inventory.length; _ii++>><<set _itemDef = _qdef.items ? _qdef.items[_qactive.inventory[_ii]] : null>><<if _ii > 0>>, <</if>><<= _itemDef ? _itemDef.name : _qactive.inventory[_ii]>><</for>> </div> <</if>> </div> <</if>> <</for>> <</if>> <</if>> <</nobr>>
<<nobr>> <<set _completedIds = Object.keys($questData.completed)>> <<if _completedIds.length === 0>> <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 12px; padding: 40px 20px; text-align: center;"> <p style="color: #666; font-size: 18px; margin: 0 0 10px 0;">No completed quests</p> <p style="color: #555; font-size: 14px; margin: 0;">Complete quests to see your accomplishments here.</p> </div> <<else>> <<for _ci = 0; _ci < _completedIds.length; _ci++>> <<set _cid = _completedIds[_ci]>> <<set _cdef = setup.quests[_cid]>> <<if _cdef>> <<set _cdata = $questData.completed[_cid]>> <<set _coutcome = (_cdata.outcomeId && _cdef.outcomes && _cdef.outcomes[_cdata.outcomeId]) ? _cdef.outcomes[_cdata.outcomeId] : null>> <<set _crewards = _coutcome ? _coutcome.rewards : (_cdef.rewards || {})>> <div style="background: #2a2a2a; border: 1px solid #51cf66; border-radius: 10px; padding: 15px; margin-bottom: 10px; opacity: 0.85;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div style="color: #51cf66; font-weight: bold; font-size: 14px;">✅ <<= _cdef.name>></div> <div style="color: #888; font-size: 12px;">Completed Day <<= _cdata.completedDay>></div> </div> <<if _coutcome && _coutcome.description>> <div style="color: #aaa; font-size: 13px; margin-top: 6px; font-style: italic;"><<= _coutcome.description>></div> <</if>> <div style="color: #888; font-size: 12px; margin-top: 6px;"> <<if _crewards.money>>💰 $<<= _crewards.money>> <</if>> <<if _crewards.traits && _crewards.traits.length > 0>>✨ <<= _crewards.traits.length>> trait(s) <</if>> <<if _crewards.unlocks && _crewards.unlocks.length > 0>>🔓 <<= _crewards.unlocks.length>> unlock(s)<</if>> </div> </div> <</if>> <</for>> <</if>> <</nobr>>
<<nobr>> <<set _activeIds = Object.keys($questData.active)>> <<set _completedIds = Object.keys($questData.completed)>> <<if _activeIds.length === 0 && _completedIds.length === 0>> <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 12px; padding: 40px 20px; text-align: center;"> <p style="color: #666; font-size: 18px; margin: 0 0 10px 0;">No quests yet</p> <p style="color: #555; font-size: 14px; margin: 0;">Talk to NPCs and explore the city to find quests.</p> </div> <<else>> <<set _categoryIcons = {exploration: "🗺️", social: "💬", work: "💼", combat: "⚔️", mystery: "🔍", transformation: "✨"}>> /* Active Quests */ <<if _activeIds.length > 0>> <div style="color: #4dabf7; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">📋 Active</div> <<for _qi = 0; _qi < _activeIds.length; _qi++>> <<set _qid = _activeIds[_qi]>> <<set _qdef = setup.quests[_qid]>> <<if _qdef>> <<set _qactive = $questData.active[_qid]>> <<set _qstep = _qdef.steps[_qactive.step]>> <<set _qicon = _categoryIcons[_qdef.category] || "📋">> <<set _qborder = _qdef.type === "main" ? "#f0ad4e" : "#444">> <div style="background: #2a2a2a; border: 2px solid <<= _qborder>>; border-radius: 10px; padding: 15px; margin-bottom: 10px;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div style="color: #4dabf7; font-weight: bold; font-size: 14px;"><<= _qicon>> <<= _qdef.name>></div> <div style="color: #888; font-size: 12px;">Day <<= _qactive.startedDay>></div> </div> <<if _qstep>> <div style="color: #ccc; font-size: 13px; margin-top: 8px; padding: 8px; background: #1a1a2e; border-radius: 6px; border-left: 3px solid #4dabf7;"> ▶ <<= _qstep.description>> </div> <</if>> </div> <</if>> <</for>> <</if>> /* Completed Quests */ <<if _completedIds.length > 0>> <div style="color: #51cf66; font-weight: bold; font-size: 16px; margin: 15px 0 10px 0; border-bottom: 1px solid #444; padding-bottom: 8px;">✅ Completed</div> <<for _ci = 0; _ci < _completedIds.length; _ci++>> <<set _cid = _completedIds[_ci]>> <<set _cdef = setup.quests[_cid]>> <<if _cdef>> <<set _cdata = $questData.completed[_cid]>> <div style="background: #2a2a2a; border: 1px solid #51cf66; border-radius: 10px; padding: 15px; margin-bottom: 10px; opacity: 0.85;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div style="color: #51cf66; font-weight: bold; font-size: 14px;">✅ <<= _cdef.name>></div> <div style="color: #888; font-size: 12px;">Completed Day <<= _cdata.completedDay>></div> </div> </div> <</if>> <</for>> <</if>> <</if>> <</nobr>>
<<set _stats = setup.skillTree.getStats()>> <div id="st-page"> <div id="st-header"> <div id="st-back"><<link "← Back">><<goto "Achievements">><</link>></div> <div id="st-info">⭐ <<= _stats.availablePoints>> Available | <<= _stats.spentPoints>> Spent | <<= _stats.unlocked>>/<<= _stats.total>> Unlocked</div> <div id="st-btns"></div> </div> <div id="st-help">Drag to pan • Scroll/Pinch to zoom • Tap gold nodes to buy</div> <div id="st-viewport"> <svg id="st-svg"></svg> <div id="st-nodes"></div> </div> <div id="st-tooltip"></div> </div> <<script>> $(document).one(":passageend", function() { var vp = document.getElementById("st-viewport"); var svg = document.getElementById("st-svg"); var nodesDiv = document.getElementById("st-nodes"); var tooltip = document.getElementById("st-tooltip"); var btns = document.getElementById("st-btns"); var zoom = 0.25; var panX = 0; var panY = 0; var dragging = false; var dragStartX, dragStartY, panStartX, panStartY; btns.innerHTML = '<button class="st-btn" id="st-zin">+</button>' + '<button class="st-btn" id="st-zout">−</button>' + '<button class="st-btn" id="st-center">⌾</button>'; /* STAR LAYOUT - Center at 2500,2000 */ /* Each branch radiates outward in its own direction */ /* MASSIVE spacing: 500px+ between all nodes */ var cx = 2500; var cy = 3000; var positions = { /* === 5 STARTING BRANCHES - TRUE STAR PATTERN === */ /* TRADING: Goes UP-LEFT (northwest diagonal) */ "skill_2": {x: cx - 500, y: cy - 500}, /* RELATIONSHIPS: Near center-north */ "skill_3": {x: cx, y: cy - 400}, /* CRIME: Goes DOWN-LEFT (southwest diagonal) */ "skill_4": {x: cx - 500, y: cy + 1200}, /* MONEY: Goes DOWN-RIGHT (southeast) */ "skill_5": {x: cx + 600, y: cy + 800}, /* SEXY: Goes UP-RIGHT (northeast) */ "skill_33": {x: cx + 600, y: cy - 400}, /* === TRADING BRANCH - continues UP-LEFT diagonal === */ "skill_6": {x: cx - 1100, y: cy - 700}, "skill_18": {x: cx - 1100, y: cy - 1100}, "skill_19": {x: cx - 1100, y: cy - 1500}, "skill_21": {x: cx - 1700, y: cy - 700}, "skill_23": {x: cx - 1700, y: cy - 1100}, "skill_20": {x: cx - 1700, y: cy - 1500}, /* === CRIME BRANCH - continues DOWN-LEFT diagonal === */ "skill_15": {x: cx - 1100, y: cy + 1400}, "skill_16": {x: cx - 1100, y: cy + 1800}, "skill_17": {x: cx - 1100, y: cy + 2200}, "skill_36": {x: cx - 1100, y: cy + 2600}, "skill_28": {x: cx - 1700, y: cy + 1400}, "skill_27": {x: cx - 1700, y: cy + 1800}, "skill_29": {x: cx - 1700, y: cy + 2200}, "skill_37": {x: cx - 1700, y: cy + 2600}, /* === MONEY BRANCH - continues DOWN-RIGHT === */ "skill_12": {x: cx + 1100, y: cy + 600}, "skill_13": {x: cx + 1100, y: cy + 1000}, "skill_14": {x: cx + 1100, y: cy + 1400}, "skill_32": {x: cx + 1100, y: cy + 1800}, "skill_22": {x: cx + 1700, y: cy + 800}, "skill_26": {x: cx + 2300, y: cy + 800}, /* Selling sub (from skill_12) */ "skill_7": {x: cx + 1700, y: cy + 600}, "skill_10": {x: cx + 2300, y: cy + 400}, "skill_11": {x: cx + 2300, y: cy + 600}, "skill_30": {x: cx + 2900, y: cy + 600}, /* Slots sub (from skill_13) */ "skill_8": {x: cx + 1700, y: cy + 1000}, "skill_34": {x: cx + 2300, y: cy + 900}, "skill_40": {x: cx + 2300, y: cy + 1200}, /* Streaming sub (from skill_14) */ "skill_9": {x: cx + 1700, y: cy + 1400}, "skill_24": {x: cx + 2300, y: cy + 1300}, "skill_25": {x: cx + 2300, y: cy + 1600}, /* Tomes sub (from skill_32) */ "skill_31": {x: cx + 1700, y: cy + 1800}, "skill_39": {x: cx + 2300, y: cy + 1800}, /* === RELATIONSHIPS BRANCH (expanded) === */ "skill_77": {x: cx - 600, y: cy - 200}, "skill_78": {x: cx + 900, y: cy - 700}, "skill_79": {x: cx + 500, y: cy}, "skill_80": {x: cx + 600, y: cy - 900}, /* === SEXY BRANCH - continues UP-RIGHT === */ "skill_41": {x: cx + 1100, y: cy - 700}, "skill_43": {x: cx + 1100, y: cy - 300}, "skill_42": {x: cx + 1700, y: cy - 700}, /* === FISHING BRANCH - goes DUE NORTH === */ "skill_45": {x: cx, y: cy - 800}, "skill_46": {x: cx - 300, y: cy - 1400}, "skill_47": {x: cx - 300, y: cy - 2000}, "skill_48": {x: cx + 600, y: cy - 1400}, "skill_49": {x: cx + 600, y: cy - 2000}, "skill_50": {x: cx + 300, y: cy - 1400}, "skill_51": {x: cx + 300, y: cy - 2000}, "skill_52": {x: cx + 1200, y: cy - 1400}, "skill_53": {x: cx, y: cy - 2000}, /* === HOME BRANCH - between Trading and Crime (due left) === */ "skill_54": {x: cx - 600, y: cy + 50}, "skill_55": {x: cx - 1200, y: cy + 50}, "skill_56": {x: cx - 1800, y: cy + 50}, "skill_57": {x: cx - 2400, y: cy + 50}, "skill_58": {x: cx - 1800, y: cy + 500}, "skill_59": {x: cx - 2400, y: cy + 500}, "skill_60": {x: cx - 2400, y: cy + 1000}, "skill_61": {x: cx - 1800, y: cy - 400}, /* === GARDENING BRANCH - off Homebuyer, above Crime === */ "skill_73": {x: cx - 1200, y: cy + 550}, "skill_74": {x: cx - 1200, y: cy + 1000}, "skill_75": {x: cx - 1800, y: cy + 1000}, "skill_76": {x: cx - 700, y: cy + 1000}, /* === JOB BRANCH (offshoot from Money, goes far down-right) === */ /* Trait Hours chain */ "skill_65": {x: cx + 600, y: cy + 2400}, "skill_66": {x: cx + 600, y: cy + 2900}, "skill_67": {x: cx + 600, y: cy + 3400}, /* Tip bonus */ "skill_68": {x: cx + 1200, y: cy + 2400}, /* Promotion chain */ "skill_69": {x: cx, y: cy + 2400}, "skill_70": {x: cx, y: cy + 2900}, "skill_71": {x: cx, y: cy + 3400}, /* Side job */ "skill_72": {x: cx + 1200, y: cy + 2900}, /* === ENDURANCE BRANCH - goes RIGHT past Money lines === */ "skill_62": {x: cx + 1600, y: cy - 200}, "skill_63": {x: cx + 2200, y: cy - 600}, "skill_64": {x: cx + 2200, y: cy + 200}, /* === SECRETS - FAR BOTTOM CENTER === */ "skill_35": {x: cx, y: cy + 400}, "skill_38": {x: cx, y: cy + 800}, /* === HIDDEN === */ }; function applyTransform() { var t = "translate(" + panX + "px," + panY + "px) scale(" + zoom + ")"; nodesDiv.style.transform = t; svg.style.transform = t; } function drawLines() { svg.innerHTML = ""; var skills = setup.skillTree.skills; for (var id in skills) { var s = skills[id]; var p2 = positions[id]; if (!p2 || !s.requires) continue; for (var i = 0; i < s.requires.length; i++) { var p1 = positions[s.requires[i]]; if (!p1) continue; var lit = setup.skillTree.isUnlocked(s.requires[i]); var line = document.createElementNS("http://www.w3.org/2000/svg", "line"); line.setAttribute("x1", p1.x + 75); line.setAttribute("y1", p1.y + 50); line.setAttribute("x2", p2.x + 75); line.setAttribute("y2", p2.y + 50); line.setAttribute("class", lit ? "st-line-lit" : "st-line-dim"); svg.appendChild(line); } } } function drawNodes() { nodesDiv.innerHTML = ""; var skills = setup.skillTree.skills; for (var id in skills) { var s = skills[id]; var p = positions[id]; if (!p) continue; var unlocked = setup.skillTree.isUnlocked(id); var canBuy = setup.skillTree.canPurchase(id); /* Hidden skills only appear when purchasable or already unlocked */ if (s.hidden && !unlocked && !canBuy) continue; var node = document.createElement("div"); node.className = "st-node"; if (unlocked) node.className += " st-unlocked"; else if (canBuy) node.className += " st-canbuy"; else node.className += " st-locked"; node.style.left = p.x + "px"; node.style.top = p.y + "px"; node.setAttribute("data-id", id); var costText = unlocked ? "✓ OWNED" : s.cost + " pts"; node.innerHTML = '<div class="st-name">' + s.name + '</div><div class="st-cost">' + costText + '</div>'; (function(skillId, skillData, canPurchase) { node.onclick = function(e) { e.stopPropagation(); if (canPurchase) { setup.skillTree.purchase(skillId); Engine.play("SkillTree"); } }; node.onmouseenter = function(e) { var req = ""; if (skillData.requires && skillData.requires.length > 0) { var names = []; for (var i = 0; i < skillData.requires.length; i++) { var r = setup.skillTree.skills[skillData.requires[i]]; var done = setup.skillTree.isUnlocked(skillData.requires[i]); names.push((done ? "✓ " : "✗ ") + (r ? r.name : skillData.requires[i])); } req = "<div class='st-tip-req'>Requires: " + names.join(", ") + "</div>"; } tooltip.innerHTML = '<div class="st-tip-name">' + skillData.name + '</div>' + '<div class="st-tip-desc">' + (skillData.description || "No description") + '</div>' + '<div class="st-tip-cost">Cost: ' + skillData.cost + ' points</div>' + req; tooltip.style.display = "block"; tooltip.style.left = (e.clientX + 15) + "px"; tooltip.style.top = (e.clientY + 15) + "px"; }; node.onmouseleave = function() { tooltip.style.display = "none"; }; })(id, s, canBuy); nodesDiv.appendChild(node); } } /* Pan */ vp.onmousedown = function(e) { if (e.target.classList.contains("st-node") || e.target.closest(".st-node")) return; dragging = true; dragStartX = e.clientX; dragStartY = e.clientY; panStartX = panX; panStartY = panY; vp.style.cursor = "grabbing"; }; document.onmousemove = function(e) { if (!dragging) return; panX = panStartX + (e.clientX - dragStartX); panY = panStartY + (e.clientY - dragStartY); applyTransform(); }; document.onmouseup = function() { dragging = false; vp.style.cursor = "grab"; }; /* Zoom at mouse position */ vp.onwheel = function(e) { e.preventDefault(); var rect = vp.getBoundingClientRect(); var mouseX = e.clientX - rect.left; var mouseY = e.clientY - rect.top; var oldZoom = zoom; var delta = e.deltaY > 0 ? 0.85 : 1.18; zoom = Math.max(0.1, Math.min(1.5, zoom * delta)); var zoomRatio = zoom / oldZoom; panX = mouseX - (mouseX - panX) * zoomRatio; panY = mouseY - (mouseY - panY) * zoomRatio; applyTransform(); }; /* Touch support for mobile devices */ var touchStartX, touchStartY, touchPanStartX, touchPanStartY; var lastTouchDist = 0; var isTouchDragging = false; vp.ontouchstart = function(e) { if (e.target.classList.contains("st-node") || e.target.closest(".st-node")) return; if (e.touches.length === 1) { /* Single touch - pan */ isTouchDragging = true; touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; touchPanStartX = panX; touchPanStartY = panY; } else if (e.touches.length === 2) { /* Two touches - prepare for pinch zoom */ isTouchDragging = false; var dx = e.touches[0].clientX - e.touches[1].clientX; var dy = e.touches[0].clientY - e.touches[1].clientY; lastTouchDist = Math.sqrt(dx * dx + dy * dy); } e.preventDefault(); }; vp.ontouchmove = function(e) { if (e.touches.length === 1 && isTouchDragging) { /* Single touch - pan */ panX = touchPanStartX + (e.touches[0].clientX - touchStartX); panY = touchPanStartY + (e.touches[0].clientY - touchStartY); applyTransform(); } else if (e.touches.length === 2) { /* Two touches - pinch zoom */ var dx = e.touches[0].clientX - e.touches[1].clientX; var dy = e.touches[0].clientY - e.touches[1].clientY; var dist = Math.sqrt(dx * dx + dy * dy); if (lastTouchDist > 0) { var rect = vp.getBoundingClientRect(); var centerX = (e.touches[0].clientX + e.touches[1].clientX) / 2 - rect.left; var centerY = (e.touches[0].clientY + e.touches[1].clientY) / 2 - rect.top; var oldZoom = zoom; var scale = dist / lastTouchDist; zoom = Math.max(0.1, Math.min(1.5, zoom * scale)); var zoomRatio = zoom / oldZoom; panX = centerX - (centerX - panX) * zoomRatio; panY = centerY - (centerY - panY) * zoomRatio; applyTransform(); } lastTouchDist = dist; } e.preventDefault(); }; vp.ontouchend = function(e) { if (e.touches.length === 0) { isTouchDragging = false; lastTouchDist = 0; } else if (e.touches.length === 1) { /* Went from 2 touches to 1 - restart pan */ isTouchDragging = true; touchStartX = e.touches[0].clientX; touchStartY = e.touches[0].clientY; touchPanStartX = panX; touchPanStartY = panY; lastTouchDist = 0; } }; document.getElementById("st-zin").onclick = function() { var rect = vp.getBoundingClientRect(); var centerX = rect.width / 2; var centerY = rect.height / 2; var oldZoom = zoom; zoom = Math.min(1.5, zoom * 1.3); var zoomRatio = zoom / oldZoom; panX = centerX - (centerX - panX) * zoomRatio; panY = centerY - (centerY - panY) * zoomRatio; applyTransform(); }; document.getElementById("st-zout").onclick = function() { var rect = vp.getBoundingClientRect(); var centerX = rect.width / 2; var centerY = rect.height / 2; var oldZoom = zoom; zoom = Math.max(0.1, zoom * 0.7); var zoomRatio = zoom / oldZoom; panX = centerX - (centerX - panX) * zoomRatio; panY = centerY - (centerY - panY) * zoomRatio; applyTransform(); }; document.getElementById("st-center").onclick = function() { var rect = vp.getBoundingClientRect(); zoom = 0.25; panX = rect.width / 2 - cx * zoom; panY = rect.height / 2 - cy * zoom; applyTransform(); }; drawLines(); drawNodes(); var rect = vp.getBoundingClientRect(); panX = rect.width / 2 - cx * zoom; panY = rect.height / 2 - cy * zoom; applyTransform(); }); <</script>>
Full swap option (every trait traded) use NPC’s image as your character screen. Random swaps, sometimes characters sneak in traits/skills they want to trade. twinning and or identity change/corruption accidental bump and swap switching name+body with someone (probably make this an optional skill in the skill tree) Add sexual orientations for when relationships are updated
<<nobr>> <<set $lastLocation = "RedLightHousing">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b6b; text-align: center;">💋 Red Light District Apartments</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a1a1a 0%, #2d1515 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b6b;"> <p style="color: white; font-size: 18px; margin: 0;"> A run-down apartment building in the heart of the Red Light District. The hallways smell of cheap perfume and cigarette smoke. Flickering neon lights from nearby establishments cast colored shadows through grimy windows. It's not much, but rent is cheap and no one asks questions. </p> </div> <h2 style="color: #ff6b6b;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Return to the red light district.</p> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Back to Red Light District</div>">> <<goto "RedLightDistrict">> <</link>> </div> </div> <<set _npcsHere = setup.getNPCsAtLocation("RedLightHousing")>> <<set _residents = setup.getNPCsLivingAt("RedLightHousing")>> <!-- Knock on Random Door Section --> <h2 style="color: #ff6b6b;">🚪 Knock on a Door</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b;"> <p style="color: #aaa; margin-bottom: 15px;">Try knocking on a random apartment door. There's about a 25% chance someone will answer.</p> <<link "<div style='background: #ff6b6b; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🚪 Knock on Random Door</div>">> <<set _knockResult = setup.knockRandomDoor("RedLightHousing")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "No answer. You hear music playing from inside but no one comes to the door.">> <<goto "RedLightHousing">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ff6b6b;"> <p style="color: #ff6b6b; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">💋 Visit Friend's Place</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66;"> <p style="color: #aaa; margin-bottom: 15px;">You know these residents well enough to visit directly.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>💋 Visit _friend.name</div>">> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #ff6b6b;">💋 Residents in Building</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #ff6b6b; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666;"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The hallways are empty right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "OutskirtsHousing">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #8b7355; text-align: center;">🏚️ Outskirts Housing</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3d3528 0%, #2a2520 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8b7355;"> <p style="color: white; font-size: 18px; margin: 0;"> Rundown houses scattered along the outskirts of town. Peeling paint, overgrown yards, and rusted chain-link fences are common sights here. The neighborhood has seen better days, but the residents make do with what they have. Some call it character, others call it neglect. </p> </div> <h2 style="color: #8b7355;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #8b7355; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #8b7355; margin: 0 0 10px 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Return to the outskirts area.</p> <<link "<div style='background: #8b7355; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Back to Outskirts</div>">> <<goto "Outskirts">> <</link>> </div> </div> <<set _npcsHere = setup.getNPCsAtLocation("OutskirtsHousing")>> <<set _residents = setup.getNPCsLivingAt("OutskirtsHousing")>> <!-- Knock on Random Door Section --> <h2 style="color: #8b7355;">🚪 Knock on a Door</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #8b7355;"> <p style="color: #aaa; margin-bottom: 15px;">Try knocking on a random door. There's about a 25% chance someone will answer.</p> <<link "<div style='background: #8b7355; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🚪 Knock on Random Door</div>">> <<set _knockResult = setup.knockRandomDoor("OutskirtsHousing")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "No one answers. You hear a TV playing inside but no one comes to the door.">> <<goto "OutskirtsHousing">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #8b7355;"> <p style="color: #8b7355; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">🏠 Visit Friend's Place</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66;"> <p style="color: #aaa; margin-bottom: 15px;">You know these residents well enough to visit directly.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🏠 Visit _friend.name</div>">> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #8b7355;">🏚️ Residents Outside</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #8b7355;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #8b7355; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: #8b7355; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #8b7355; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666;"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one is outside in the neighborhood right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ApartmentPenthouse">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">Penthouse Suite</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3d3419 0%, #2a2510 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700;"> <p style="color: white; font-size: 18px; margin: 0;"> A luxurious penthouse sitting atop the city's most prestigious apartment building. Floor-to-ceiling windows offer breathtaking panoramic views of Sunfish City. The interior is all marble floors, designer furniture, and expensive artwork. This is where the city's elite call home. </p> </div> <<if $currentHousingVisit>> <h2 style="color: #ffd700;">Visiting: <<= $currentHousingVisit>>'s Penthouse</h2> <p style="color: #ccc;">You're in the lap of luxury, visiting an NPC's penthouse.</p> <<link "<div style='background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; display: inline-block;'>Leave</div>">> <<set $currentHousingVisit = null>> <<goto "Downtown">> <</link>> <<else>> <p style="color: #888;">The elevator requires a keycard. To visit someone here, you need to have a Best Friend relationship with them.</p> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffd700; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>Back to Downtown</div>">> <<goto "Downtown">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BusinessDistrictHousing">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">🏢 Business District Apartments</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a3040 0%, #102030 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> Upscale apartment complex nestled among the corporate towers of the Business District. Modern architecture, keycard security, and a doorman who remembers everyone's name. The residents are mostly young professionals and executives who value convenience and status. </p> </div> <h2 style="color: #17a2b8;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">🏛️ Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Return to the business district.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <<set _npcsHere = setup.getNPCsAtLocation("BusinessDistrictHousing")>> <<set _residents = setup.getNPCsLivingAt("BusinessDistrictHousing")>> <!-- Knock on Random Door Section --> <h2 style="color: #17a2b8;">🚪 Buzz an Apartment</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8;"> <p style="color: #aaa; margin-bottom: 15px;">Try buzzing a random apartment. There's about a 25% chance someone will answer.</p> <<link "<div style='background: #17a2b8; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🔔 Buzz Random Apartment</div>">> <<set _knockResult = setup.knockRandomDoor("BusinessDistrictHousing")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "No response. The resident is either out or not accepting visitors.">> <<goto "BusinessDistrictHousing">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #17a2b8;"> <p style="color: #17a2b8; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">🏢 Visit Friend's Apartment</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66;"> <p style="color: #aaa; margin-bottom: 15px;">The doorman recognizes you as a friend of these residents.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🏢 Visit _friend.name</div>">> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #17a2b8;">🏢 Residents in Lobby</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666;"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The lobby is quiet right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BeachMansion">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #20c997; text-align: center;">Beach Mansion</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a3d3d 0%, #102828 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #20c997;"> <p style="color: white; font-size: 18px; margin: 0;"> A stunning beachfront mansion with private beach access. The architecture blends modern luxury with coastal charm. Palm trees line the driveway, and the sound of waves provides a constant, soothing backdrop. This is the kind of home most people only dream about. </p> </div> <<if $currentHousingVisit>> <h2 style="color: #20c997;">Visiting: <<= $currentHousingVisit>>'s Mansion</h2> <p style="color: #ccc;">You're visiting an NPC's luxurious beach mansion.</p> <<link "<div style='background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; display: inline-block;'>Leave</div>">> <<set $currentHousingVisit = null>> <<goto "Beach">> <</link>> <<else>> <p style="color: #888;">The gate is locked and secured. To visit someone here, you need to have a Best Friend relationship with them.</p> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #20c997; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>Back to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BrothelPrivateChambers">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">🛏️ Brothel Private Chambers</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3d1a2e 0%, #2a1020 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0;"> The back hallway of the brothel leads to the private living quarters where the workers reside. Each room is surprisingly cozy - a small sanctuary away from work. The thick walls ensure privacy, and the furnishings are tasteful despite the nature of the establishment. </p> </div> <h2 style="color: #e83e8c;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">💋 Brothel</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Return to the main brothel area.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Back to Brothel</div>">> <<goto "Brothel">> <</link>> </div> </div> <<set _npcsHere = setup.getNPCsAtLocation("BrothelPrivateChambers")>> <<set _residents = setup.getNPCsLivingAt("BrothelPrivateChambers")>> <!-- Knock on Random Door Section --> <h2 style="color: #e83e8c;">🚪 Knock on a Room</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e83e8c;"> <p style="color: #aaa; margin-bottom: 15px;">Try knocking on a random worker's door. There's about a 25% chance someone will answer.</p> <<link "<div style='background: #e83e8c; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🚪 Knock on Random Room</div>">> <<set _knockResult = setup.knockRandomDoor("BrothelPrivateChambers")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "No answer. They must be working or resting.">> <<goto "BrothelPrivateChambers">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #e83e8c;"> <p style="color: #e83e8c; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">🛏️ Visit Friend's Room</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66;"> <p style="color: #aaa; margin-bottom: 15px;">You're close enough with these workers to visit their private rooms.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🛏️ Visit _friend.name</div>">> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #e83e8c;">🛏️ Workers in Hallway</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e83e8c;"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666;"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The hallway is quiet. Everyone must be in their rooms or working. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("TheAngler")>> <<run $visitedLocations.push("TheAngler")>> <</if>> <<set $lastLocation = "TheAngler">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #d4a574; text-align: center;">🍺 The Angler</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images\Locations\TheAngler.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #d4a574; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="The Angler Bar"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #3d2d1d 0%, #2a1a0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #d4a574;"> <p style="color: white; font-size: 18px; margin: 0;"> A dimly lit dive bar with wooden walls covered in fishing memorabilia and flickering neon beer signs. The smell of stale beer and cigarette smoke hangs heavy in the air. Workers from the docks and construction sites crowd around the worn bar counter after their shifts, swapping stories and complaints. </p> </div> <h2 style="color: #d4a574;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Alleyway --> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the dark alley.</p> <<link "<div style='background: #666; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave the Bar</div>">> <<goto "Alleyway">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("TheAngler")>> <h2 style="color: #d4a574;">🍺 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #d4a574; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #d4a574; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #d4a574; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #d4a574; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The bar is quiet right now. Just the bartender polishing glasses and the soft hum of the jukebox. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("CommercialDistrict")>> <<run $visitedLocations.push("CommercialDistrict")>> <</if>> <<set $lastLocation = "CommercialDistrict">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #5ca4e8; text-align: center;">🏪 Commercial District</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images\Locations\CommercialDistrict.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #5ca4e8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Commercial District"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a5a 0%, #0a2a4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #5ca4e8;"> <p style="color: white; font-size: 18px; margin: 0;"> A bustling area of commerce and services. Modern office buildings, medical facilities, and various businesses line the clean, well-maintained streets. People in professional attire hurry between appointments while delivery trucks navigate the busy roads. </p> </div> <h2 style="color: #5ca4e8;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Bus Stop --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<run advanceTime(5)>> <<goto "BusStop">> <</link>> </div> <!-- Hospital --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">🏥 Hospital</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Sunfish City General Hospital and medical services.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Hospital</div>">> <<run advanceTime(5)>> <<goto "Hospital">> <</link>> </div> <!-- Mail Service --> <div style="border: 3px solid #d4a574; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d4a574; margin: 0 0 10px 0;">📦 Mail Service</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Package handling and delivery services.</p> <<link "<div style='background: #d4a574; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Mail Service</div>">> <<run advanceTime(5)>> <<goto "MailService">> <</link>> </div> <!-- Modeling Studio --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">📸 Modeling Studio</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Fashion photography and content production.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Studio</div>">> <<run advanceTime(5)>> <<goto "ModelingStudio">> <</link>> </div> <!-- Grocery Store --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">🛒 Grocery Store</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Fresh food and everyday supplies.</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Store</div>">> <<run advanceTime(5)>> <<goto "GroceryStore">> <</link>> </div> <!-- The Golden Seahorse --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">✨ The Golden Seahorse</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Premium furniture and luxury home decor.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Store</div>">> <<run advanceTime(5)>> <<goto "GoldenSeahorseDecor">> <</link>> </div> <!-- Flower Shop --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff69b4; margin: 0 0 10px 0;">🌸 Petal & Stem</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Fresh flowers, bouquets, and tropical plants.</p> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Shop</div>">> <<run advanceTime(5)>> <<goto "FlowerShop">> <</link>> </div> <!-- Bookstore --> <div style="border: 3px solid #8B4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8B4513; margin: 0 0 10px 0;">📚 Ink & Anchor</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Books, novels, and rare editions.</p> <<link "<div style='background: #8B4513; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Shop</div>">> <<run advanceTime(5)>> <<goto "BookStore">> <</link>> </div> </div> <h2 style="color: #5ca4e8;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Industrial District (travel) --> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #aaa; margin: 0 0 10px 0;">🏭 Industrial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Smelters, forge, and quarry. The working edge of town.</p> <<link "<div style='background: #555; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Head to the Industrial District</div>">> <<run advanceTime(15)>> <<goto "IndustrialOutskirts">> <</link>> </div> <!-- Downtown --> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #667eea; margin: 0 0 10px 0;">🏙️ Downtown</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the city center.</p> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Downtown</div>">> <<goto "Downtown">> <</link>> </div> <!-- Business District --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Corporate towers and offices.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> <!-- Residential District --> <div style="border: 3px solid #a3d9a5; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #a3d9a5; margin: 0 0 10px 0;">🏠 Residential District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Quiet neighborhoods and housing.</p> <<link "<div style='background: #a3d9a5; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Residential District</div>">> <<goto "ResidentialDistrict">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("CommercialDistrict")>> <h2 style="color: #5ca4e8;">🏪 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #5ca4e8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #5ca4e8; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #5ca4e8; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #5ca4e8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The streets are busy but no one catches your eye right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Hospital")>> <<run $visitedLocations.push("Hospital")>> <</if>> <<set $lastLocation = "Hospital">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">🏥 Sunfish City General Hospital</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images\Locations\Hospital.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Hospital"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a4a 0%, #0a2a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #17a2b8;"> <p style="color: white; font-size: 18px; margin: 0;"> The main medical facility serving Sunfish City. The sterile white corridors bustle with doctors, nurses, and patients. The smell of antiseptic hangs in the air as medical staff hurry between departments. </p> </div> <h2 style="color: #17a2b8;">Departments</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- General Clinic --> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20c997; margin: 0 0 10px 0;">🩺 General Clinic</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Walk-in care for everyday medical needs.</p> <<link "<div style='background: #20c997; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Clinic</div>">> <<goto "HospitalClinic">> <</link>> </div> <!-- Cosmetic Surgery --> <div style="border: 3px solid #e84393; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e84393; margin: 0 0 10px 0;">💉 Cosmetic Surgery</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Body modification and cosmetic procedures.</p> <<link "<div style='background: #e84393; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Surgery</div>">> <<goto "HospitalCosmeticSurgery">> <</link>> </div> <!-- Research Lab --> <<set _labCurrentMinutes = ($dayNumber - 1) * 1440 + $timeInMinutes>> <<set _labActive = $hospitalLabExpiry && _labCurrentMinutes < $hospitalLabExpiry>> <<set _labHoursLeft = _labActive ? Math.ceil(($hospitalLabExpiry - _labCurrentMinutes) / 60) : 0>> <div style="border: 3px solid #00d4aa; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #00d4aa; margin: 0 0 10px 0;">🧪 Research Lab</h3> <<if _labActive>> <p style="font-size: 14px; color: #aaa; margin: 0 0 5px 0; line-height: 1.4;">Your lab access is active.</p> <p style="font-size: 13px; color: #00d4aa; margin: 0 0 auto 0;">⏱️ <<= _labHoursLeft>> hour<<if _labHoursLeft !== 1>>s<</if>> remaining</p> <<link "<div style='background: #00d4aa; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Lab</div>">> <<set $renovateReturnPassage = "Hospital">> <<goto "RoomLaboratory">> <</link>> <<elseif ($money || 0) >= 10000>> <p style="font-size: 14px; color: #aaa; margin: 0 0 5px 0; line-height: 1.4;">Rent lab equipment for trait research and study.</p> <p style="font-size: 13px; color: #51cf66; margin: 0 0 auto 0;">$10,000 for 12 hours of access</p> <<link "<div style='background: #00d4aa; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Purchase Access ($10,000)</div>">> <<set $money -= 10000>> <<set $hospitalLabExpiry = (($dayNumber - 1) * 1440 + $timeInMinutes) + 720>> <<set $renovateReturnPassage = "Hospital">> <<goto "RoomLaboratory">> <</link>> <<else>> <p style="font-size: 14px; color: #aaa; margin: 0 0 5px 0; line-height: 1.4;">Rent lab equipment for trait research and study.</p> <p style="font-size: 13px; color: #dc3545; margin: 0 0 auto 0;">$10,000 for 12 hours of access</p> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;">Can't Afford ($10,000)</div> <</if>> </div> </div> <h2 style="color: #17a2b8;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Commercial District --> <div style="border: 3px solid #5ca4e8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #5ca4e8; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the commercial area.</p> <<link "<div style='background: #5ca4e8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Hospital</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("Hospital")>> <h2 style="color: #17a2b8;">🏥 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The hospital lobby is quiet. Medical staff hurry past without stopping. </p> </div> <</if>> <!-- Vending Machine --> <div style="border: 3px solid #00b894; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #55efc4; margin: 0 0 10px 0;">🍫 Vending Machine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Grab a quick snack or drink.</p> <<link "<div style='background: #00b894; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Machine</div>">> <<goto "VendingMachineShop">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("HospitalClinic")>> <<run $visitedLocations.push("HospitalClinic")>> <</if>> <<set $lastLocation = "HospitalClinic">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #20c997; text-align: center;">🩺 General Clinic</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images\Locations\HospitalClinic.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #20c997; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Hospital Clinic"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a3a 0%, #0a2a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #20c997;"> <p style="color: white; font-size: 18px; margin: 0;"> The walk-in clinic handles everyday medical needs. Plastic chairs line the waiting area while patients flip through outdated magazines. A reception desk staffed by friendly faces greets incoming patients. </p> </div> <h2 style="color: #20c997;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Hospital --> <div style="border: 3px solid #17a2b8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #17a2b8; margin: 0 0 10px 0;">🏥 Hospital</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the main hospital.</p> <<link "<div style='background: #17a2b8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Back to Hospital</div>">> <<goto "Hospital">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("HospitalClinic")>> <h2 style="color: #20c997;">🩺 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #20c997; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #20c997; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #20c997; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The waiting room is empty. A few chairs sit vacant under fluorescent lights. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("MailService")>> <<run $visitedLocations.push("MailService")>> <</if>> <<set $lastLocation = "MailService">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #d4a574; text-align: center;">📦 Sunfish City Mail Service</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images\Locations\MailService.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #d4a574; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Mail Service"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #3a2a1a 0%, #2a1a0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #d4a574;"> <p style="color: white; font-size: 18px; margin: 0;"> The local mail and package center handles all deliveries coming in and out of Sunfish City. Couriers rush in and out with parcels while clerks sort through mountains of mail. The constant beeping of scanners fills the air. </p> </div> <h2 style="color: #d4a574;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Commercial District --> <div style="border: 3px solid #5ca4e8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #5ca4e8; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the commercial area.</p> <<link "<div style='background: #5ca4e8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Mail Service</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("MailService")>> <h2 style="color: #d4a574;">📦 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #d4a574; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #d4a574; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #d4a574; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #d4a574; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The mail room is busy but no one has time to chat right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ModelingStudio")>> <<run $visitedLocations.push("ModelingStudio")>> <</if>> <<set $lastLocation = "ModelingStudio">> <<run setup.tickOjouRefinement("modelingStudio", 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">📸 Luxe Modeling Studio</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ModelingStudio.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #e83e8c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Modeling Studio"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #5a2d4d 0%, #3d1a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0;"> A sleek, modern building with tinted windows. The reception area is decorated with professional photographs and awards. Two distinct wings branch off from the main lobby - one for fashion modeling and one for adult content production. </p> </div> <!-- Model Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Model")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">📸 Apply: Model</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Model")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">📸 Apply: Model</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">📸 Apply: Model</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $75/hour</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "ModelJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Model Work Shift --> <<if $jobs && $jobs.length > 0 && $jobs[0] === "Model">> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">📸 Modeling Work</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Start a modeling session at Luxe Studio! Choose your session type and work your way up the career tiers. (Max 8 hours/day)</p> <<if setup.modelDisqualified && setup.modelDisqualified()>> <div style="border: 2px solid #dc3545; border-radius: 8px; padding: 12px; background: rgba(220,53,69,0.15); margin-bottom: 10px;"> <p style="color: #dc3545; font-weight: bold; margin: 0 0 6px 0; font-size: 14px;">⚠️ Warning: You No Longer Meet Agency Standards</p> <p style="color: #ff8c00; font-size: 13px; margin: 0;">Your body or appearance has changed since you were hired. You will not be able to work until you meet the requirements again.</p> </div> <</if>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Modeling Session</div>">> <<goto "ModelWork">> <</link>> </div> <</if>> <h2 style="color: #e83e8c;">Departments</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Fashion Department --> <div style="border: 3px solid #9c27b0; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #9c27b0; margin: 0 0 10px 0;">🎨 Fashion Department</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Commercial modeling and brand promotions.</p> <<link "<div style='background: #9c27b0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Fashion Department</div>">> <<goto "ModelingStudioFashion">> <</link>> </div> <!-- Adult Department --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🔞 Adult Department</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">18+ content production.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Adult Department</div>">> <<goto "ModelingStudioAdult">> <</link>> </div> </div> <h2 style="color: #e83e8c;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Commercial District --> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20c997; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Exit the studio.</p> <<link "<div style='background: #20c997; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Studio</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("ModelingStudio")>> <h2 style="color: #e83e8c;">📸 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e83e8c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #c77dac; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The lobby is quiet right now. No models or staff are around. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ModelingStudioFashion")>> <<run $visitedLocations.push("ModelingStudioFashion")>> <</if>> <<set $lastLocation = "ModelingStudioFashion">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9c27b0; text-align: center;">🎨 Fashion Department</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ModelingStudioFashion.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #9c27b0; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Fashion Department"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #4a2d5a 0%, #3a1a4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9c27b0;"> <p style="color: white; font-size: 18px; margin: 0;"> Bright studio lights illuminate professional sets. Racks of designer clothing line the walls while makeup artists and photographers prepare for shoots. The air smells of hairspray and expensive perfume. Models pose for commercial campaigns, magazine spreads, and brand promotions. </p> </div> <h2 style="color: #9c27b0;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Studio Lobby --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">📸 Studio Lobby</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to main area.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Lobby</div>">> <<goto "ModelingStudio">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("ModelingStudioFashion")>> <h2 style="color: #9c27b0;">🎨 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9c27b0; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #9c27b0; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9c27b0; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #b388c9; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #9c27b0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one is working in the fashion department right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ModelingStudioAdult")>> <<run $visitedLocations.push("ModelingStudioAdult")>> <</if>> <<set $lastLocation = "ModelingStudioAdult">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">🔞 Adult Content Department</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ModelingStudioAdult.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #e83e8c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Adult Content Department"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #5a2d4d 0%, #3d1a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0;"> A more private wing of the studio with soundproofed rooms and discrete entrances. Professional equipment and plush sets are arranged for adult content production. Security ensures only authorized personnel enter. Performers work on various projects including solo content, collaborations, and professional productions. </p> </div> <h2 style="color: #e83e8c;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Studio Lobby --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">📸 Studio Lobby</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to main area.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Lobby</div>">> <<goto "ModelingStudio">> <</link>> </div> </div> <!-- Porn Star Apply for Work --> <<set _appStatus = setup.getJobApplicationStatus("Porn Star")>> <<if _appStatus !== "employed">> <<if _appStatus === "notQualified">> <div style="border: 3px solid #666; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🎬 Apply: Porn Star</h3> <p style="font-size: 14px; color: #666; margin: 0 0 5px 0;">You don't meet the requirements for this position.</p> <p style="font-size: 13px; color: #888; margin: 0 0 10px 0;">Requires: <<print setup.getJobRequirementDisplay("Porn Star")>></p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Qualified</div> </div> <<elseif _appStatus === "notHiring">> <div style="border: 3px solid #ff6b6b; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #ff6b6b; margin: 0 0 10px 0;">🎬 Apply: Porn Star</h3> <p style="font-size: 14px; color: #ff6b6b; margin: 0 0 10px 0;">This position is fully staffed right now.</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Not Hiring</div> </div> <<else>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🎬 Apply: Porn Star</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 5px 0;">This position is available!</p> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Pay: $100/hour</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Apply Now</div>">> <<goto "PornStarJobOffer">> <</link>> </div> <</if>> <</if>> <!-- Porn Star Work Shift --> <<if $jobs && $jobs.includes("Porn Star")>> <h2 style="color: #e83e8c;">Work</h2> <<if setup.pornStarDisqualified && setup.pornStarDisqualified()>> <div style="border: 2px solid #dc3545; border-radius: 10px; padding: 15px; background: rgba(220,53,69,0.15); margin-bottom: 15px;"> <p style="color: #dc3545; font-weight: bold; font-size: 16px; margin: 0 0 8px 0; text-align: center;">⚠️ You No Longer Meet Studio Standards</p> <p style="color: #ff8c00; font-size: 13px; margin: 0; text-align: center;">Your current appearance traits prevent you from working as a Porn Star. You can still visit the studio, but filming is unavailable.</p> </div> <</if>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">🎬 Start Work Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;">Clock in as a Porn Star. Choose a scene type and perform for the cameras.</p> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>🎬 Start Work Shift</div>">> <<goto "PornStarWork">> <</link>> </div> <</if>> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("ModelingStudioAdult")>> <h2 style="color: #e83e8c;">🔞 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e83e8c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e83e8c; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #c77dac; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one is working in the adult department right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("GroceryStore")>> <<run $visitedLocations.push("GroceryStore")>> <</if>> <<set $lastLocation = "GroceryStore">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">🛒 Fresh Catch Grocery</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/GroceryStore.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Grocery Store"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1e4a2d 0%, #143d1f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 18px; margin: 0;"> The main grocery store serving Sunfish City. Fluorescent lights illuminate aisles of fresh produce, packaged goods, and everyday essentials. Shopping carts rattle across the polished floors as customers browse the selections. Departments include fresh produce, bakery, deli, frozen foods, and household supplies. </p> </div> <h2 style="color: #28a745;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Commercial District --> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20c997; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Exit the store.</p> <<link "<div style='background: #20c997; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave Store</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsAtLocation("GroceryStore")>> <h2 style="color: #28a745;">🛒 People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #28a745; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #6fbf7f; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one else is shopping right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ResidentialDistrict")>> <<run $visitedLocations.push("ResidentialDistrict")>> <</if>> <<set $lastLocation = "ResidentialDistrict">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #6c757d; text-align: center;">🏘️ Residential District</h1> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ResidentialDistrict.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #6c757d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Residential District"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #3d4a3d 0%, #2a3a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #6c757d;"> <p style="color: white; font-size: 18px; margin: 0;"> Tree-lined streets wind through neighborhoods of varying affluence. From modest starter homes to gated mansions, this district houses many of Sunfish City's residents. Children play in yards while neighbors chat over fences. </p> </div> <h2 style="color: #6c757d;">🏠 Neighborhoods</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">🏠 Normal Homes</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Middle-class neighborhood with modest, well-maintained homes.</p> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Normal Homes</div>">> <<run advanceTime(5)>> <<goto "ResidentialNormalHomes">> <</link>> </div> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🏡 Expensive Homes</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Upper-class area with luxury homes and manicured lawns.</p> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Expensive Homes</div>">> <<run advanceTime(5)>> <<goto "ResidentialExpensiveHomes">> <</link>> </div> <div style="border: 3px solid #fd7e14; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #fd7e14; margin: 0 0 10px 0;">🏰 Mansions</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Gated elite community with sprawling estates.</p> <<link "<div style='background: #fd7e14; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Mansions</div>">> <<run advanceTime(5)>> <<goto "ResidentialMansions">> <</link>> </div> <<if $ownsHouse>> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🏠 Your Home</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Go directly to your home.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Home</div>">> <<goto setup.getCurrentHome()>> <</link>> </div> <</if>> </div> <h2 style="color: #6c757d;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to the Bus Stop</div>">> <<bustravel>> <<goto "BusStop">> <</link>> </div> <div style="border: 3px solid #20c997; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #20c997; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Shopping and services center.</p> <<link "<div style='background: #20c997; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Commercial District</div>">> <<travel>> <<goto "CommercialDistrict">> <</link>> </div> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin: 0 0 10px 0;">🌳 Seabass Park</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Peaceful green space nearby.</p> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Seabass Park</div>">> <<travel>> <<goto "SeabassPark">> <</link>> </div> </div> <<set _npcsHere = setup.getNPCsAtLocation("ResidentialDistrict")>> <h2 style="color: #6c757d;">🏘️ People Here</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #6c757d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The streets are quiet at the moment. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ResidentialNormalHomes")>> <<run $visitedLocations.push("ResidentialNormalHomes")>> <</if>> <<set $lastLocation = "ResidentialNormalHomes">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #6c757d; text-align: center;">🏠 Normal Homes</h1> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ResidentialNormalHomes.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #6c757d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Normal Homes"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #3d4a3d 0%, #2a3a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #6c757d;"> <p style="color: white; font-size: 18px; margin: 0;"> Rows of modest but well-maintained homes line the quiet streets. Families go about their daily lives in this middle-class neighborhood. Mailboxes and small gardens front each property. Working families and young professionals call this area home. </p> </div> <h2 style="color: #6c757d;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">🏘️ Residential District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the main residential area.</p> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Back to Residential District</div>">> <<run advanceTime(5)>> <<goto "ResidentialDistrict">> <</link>> </div> </div> <!-- Homes For Sale Section (only if player doesn't own a house) --> <<if !$ownsHouse>> <h2 style="color: #51cf66;">🏡 Homes For Sale</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #51cf66; margin: 0 0 15px 0; font-size: 20px;">🏡 3 Bed, 2 Bath Suburban Family Home</h3> <p style="color: #ffc107; font-size: 24px; font-weight: bold; margin: 0 0 15px 0;">$250,000</p> <ul style="color: #ccc; margin: 0 0 20px 20px; line-height: 1.8;"> <li>Spacious master bedroom with king-size bed</li> <li>Two additional bedrooms</li> <li>Full kitchen with modern appliances</li> <li>Luxurious master bathroom</li> <li>Two-car garage</li> <li>Tropical backyard with patio</li> </ul> <p style="color: #51cf66; font-weight: bold; margin-bottom: 15px;">No monthly rent - own it forever!</p> <<set _normalDiscount = setup.getHomePriceDiscount("normal")>> <<set _normalPrice = Math.floor(250000 * (1 - _normalDiscount / 100))>> <<if $money >= _normalPrice>> <<set _normalBuyLabel = "<div style='background: #51cf66; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Buy This Home (" + setup.formatMoney(_normalPrice) + ")</div>">> <<link _normalBuyLabel>> <<set $pendingHomePurchase = {price: _normalPrice, location: "ResidentialNormalHomes", destination: "PlayerSuburbanHome", returnTo: "ResidentialNormalHomes"}>> <<goto "ConfirmHomePurchase">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 12px 25px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 16px;'>Insufficient Funds (Need <<print setup.formatMoney(_normalPrice)>>)</div> <p style="color: #888; font-size: 14px; margin-top: 10px; text-align: center;">You have: <<print setup.formatMoney($money)>></p> <</if>> </div> </div> <</if>> <<set _npcsHere = setup.getNPCsAtLocation("ResidentialNormalHomes")>> <<set _residents = setup.getNPCsLivingAt("ResidentialNormalHomes")>> <!-- Knock on Random Door Section --> <h2 style="color: #6c757d;">🚪 Knock on a Door</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #6c757d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">You could try knocking on a random door to see if anyone answers. There's about a 25% chance someone will be home and answer.</p> <<link "<div style='background: #6c757d; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🚪 Knock on Random Door</div>">> <<run advanceTime(5)>> <<set _knockResult = setup.knockRandomDoor("ResidentialNormalHomes")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "No one answers. The house appears empty or the occupant isn't interested in visitors.">> <<goto "ResidentialNormalHomes">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ffc107;"> <p style="color: #ffc107; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">🏠 Visit Friend's Home</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">You know these residents well enough to visit their homes directly.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🏠 Visit _friend.name</div>">> <<run advanceTime(5)>> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #6c757d;">🏠 Residents Outside</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #6c757d; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">These people are currently outside in the neighborhood.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one is outside in the neighborhood right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ResidentialExpensiveHomes")>> <<run $visitedLocations.push("ResidentialExpensiveHomes")>> <</if>> <<set $lastLocation = "ResidentialExpensiveHomes">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffc107; text-align: center;">🏡 Expensive Homes</h1> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ResidentialExpensiveHomes.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Expensive Homes"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #4a5a4a 0%, #3a4a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffc107;"> <p style="color: white; font-size: 18px; margin: 0;"> Larger homes with manicured lawns and luxury vehicles in the driveways. This upscale neighborhood attracts successful professionals and established families. Private security patrols the streets. Upper-middle-class homes with pools, home theaters, and other luxury amenities. </p> </div> <h2 style="color: #ffc107;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">🏘️ Residential District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the main residential area.</p> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Back to Residential District</div>">> <<run advanceTime(5)>> <<goto "ResidentialDistrict">> <</link>> </div> </div> <!-- Homes For Sale Section (only if player doesn't own a house here) --> <<if !$ownsHouse || $houseLocation !== "ResidentialExpensiveHomes">> <h2 style="color: #ffc107;">🏡 Homes For Sale</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #ffc107; margin: 0 0 15px 0; font-size: 20px;">🏡 5 Bed, 4 Bath Luxury Home</h3> <p style="color: #ffc107; font-size: 24px; font-weight: bold; margin: 0 0 15px 0;">$2,250,000</p> <ul style="color: #ccc; margin: 0 0 20px 20px; line-height: 1.8;"> <li>Stunning master suite with California king bed</li> <li>Gourmet kitchen with professional appliances</li> <li>Private home theater</li> <li>Heated infinity pool & spa</li> <li>Fully equipped home gym</li> <li>Temperature-controlled wine cellar</li> <li>Two luxurious guest suites</li> <li>3-car garage with workshop</li> <li>Tropical backyard with outdoor kitchen</li> </ul> <p style="color: #ffc107; font-weight: bold; margin-bottom: 15px;">No monthly rent - own it forever!</p> <<set _expDiscount = setup.getHomePriceDiscount("expensive")>> <<set _expPrice = Math.floor(2250000 * (1 - _expDiscount / 100))>> <<if $money >= _expPrice>> <<set _expBuyLabel = "<div style='background: #ffc107; color: #1a1a1a; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Buy This Home (" + setup.formatMoney(_expPrice) + ")</div>">> <<link _expBuyLabel>> <<set $pendingHomePurchase = {price: _expPrice, location: "ResidentialExpensiveHomes", destination: "PlayerExpensiveHome", returnTo: "ResidentialExpensiveHomes"}>> <<goto "ConfirmHomePurchase">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 12px 25px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 16px;'>Insufficient Funds (Need <<print setup.formatMoney(_expPrice)>>)</div> <p style="color: #888; font-size: 14px; margin-top: 10px; text-align: center;">You have: <<print setup.formatMoney($money)>></p> <</if>> </div> </div> <</if>> <<set _npcsHere = setup.getNPCsAtLocation("ResidentialExpensiveHomes")>> <<set _residents = setup.getNPCsLivingAt("ResidentialExpensiveHomes")>> <!-- Knock on Random Door Section --> <h2 style="color: #ffc107;">🚪 Knock on a Door</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">You could try knocking on a door to see if anyone answers. There's about a 25% chance someone will be home and answer.</p> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🚪 Knock on Random Door</div>">> <<run advanceTime(5)>> <<set _knockResult = setup.knockRandomDoor("ResidentialExpensiveHomes")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "No one answers. The house appears empty or the occupant isn't interested in visitors.">> <<goto "ResidentialExpensiveHomes">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ffc107;"> <p style="color: #ffc107; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">🏡 Visit Friend's Home</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">You know these residents well enough to visit their homes directly.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🏡 Visit _friend.name</div>">> <<run advanceTime(5)>> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #ffc107;">🏡 Residents Outside</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffc107; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">These people are currently outside in the neighborhood.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #ffe066; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #ffc107; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> No one is outside in the upscale neighborhood right now. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("ResidentialMansions")>> <<run $visitedLocations.push("ResidentialMansions")>> <</if>> <<set $lastLocation = "ResidentialMansions">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #fd7e14; text-align: center;">🏰 Mansion Row</h1> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ResidentialMansions.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #fd7e14; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Mansion Row"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #5a6a5a 0%, #4a5a4a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #fd7e14;"> <p style="color: white; font-size: 18px; margin: 0;"> Behind wrought-iron gates and high hedges sit the grandest homes in Sunfish City. This exclusive community is home to the city's wealthiest residents. Armed security guards patrol the perimeter while groundskeepers maintain the immaculate estates. Sprawling estates with private pools, tennis courts, and staff quarters. </p> </div> <h2 style="color: #fd7e14;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #6c757d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #6c757d; margin: 0 0 10px 0;">🏘️ Residential District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Return to the main residential area.</p> <<link "<div style='background: #6c757d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Back to Residential District</div>">> <<run advanceTime(5)>> <<goto "ResidentialDistrict">> <</link>> </div> </div> <!-- Mansion For Sale Section (only if player doesn't own this mansion) --> <<if !$ownsHouse || $houseLocation !== "ResidentialMansions">> <h2 style="color: #fd7e14;">🏰 Mansions For Sale</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #fd7e14; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #fd7e14; margin: 0 0 10px 0;">🏰 Modern Mansion Estate</h3> <<set _mansionDiscount = setup.getHomePriceDiscount("mansion")>> <<set _mansionPrice = Math.floor(23943041.93 * (1 - _mansionDiscount / 100))>> <p style="font-size: 22px; color: #27ae60; font-weight: bold; margin: 0 0 10px 0;"><<print setup.formatMoney(_mansionPrice)>></p> <p style="font-size: 14px; color: #ccc; margin: 0 0 10px 0; line-height: 1.4;"> <strong>8 Bed, 6 Bath | 15,000+ sq ft</strong><br> Master suite with panoramic views, great room with 30-foot ceilings, chef's kitchen, executive office, formal dining, two-story library. </p> <p style="font-size: 13px; color: #aaa; margin: 0 0 15px 0; line-height: 1.4;"> <em>Features: Private theater, indoor pool, gym with sauna, wine cellar, game room, 4 guest suites, staff quarters, 6-car garage, 3-acre grounds with helipad</em> </p> <<if $money >= _mansionPrice>> <<set _mansionBuyLabel = "<div style='background: #fd7e14; color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Buy This Mansion (" + setup.formatMoney(_mansionPrice) + ")</div>">> <<link _mansionBuyLabel>> <<set $pendingHomePurchase = {price: _mansionPrice, location: "ResidentialMansions", destination: "PlayerModernMansion", returnTo: "ResidentialMansions"}>> <<goto "ConfirmHomePurchase">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 12px 25px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 16px;'>Insufficient Funds (Need <<print setup.formatMoney(_mansionPrice)>>)</div> <p style="color: #888; font-size: 14px; margin-top: 10px; text-align: center;">You have: <<print setup.formatMoney($money)>></p> <</if>> </div> </div> <</if>> <<set _npcsHere = setup.getNPCsAtLocation("ResidentialMansions")>> <<set _residents = setup.getNPCsLivingAt("ResidentialMansions")>> <!-- Knock on Random Gate Section --> <h2 style="color: #fd7e14;">🚪 Ring a Gate Bell</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #fd7e14; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">You could try ringing a gate bell to see if anyone will let you in. There's about a 25% chance someone will answer.</p> <<link "<div style='background: #fd7e14; color: white; padding: 12px 20px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; display: inline-block;'>🔔 Ring Random Gate Bell</div>">> <<run advanceTime(5)>> <<set _knockResult = setup.knockRandomDoor("ResidentialMansions")>> <<if _knockResult.success>> <<set $tradingWithNPC = _knockResult.npc>> <<set $knockedOnDoor = true>> <<goto "NPCInteraction">> <<else>> <<set $doorKnockMessage = "A voice crackles through the intercom: 'No solicitors.' The connection cuts off.">> <<goto "ResidentialMansions">> <</if>> <</link>> </div> <<if $doorKnockMessage>> <div style="background: #3a3a3a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #fd7e14;"> <p style="color: #fd7e14; margin: 0;">$doorKnockMessage</p> </div> <<set $doorKnockMessage = null>> <</if>> <!-- Visit Specific NPC Home (Relationship Level 3+) --> <<set _friendsHere = []>> <<for _res range _residents>> <<if setup.canVisitNPCHome(_res.name)>> <<run _friendsHere.push(_res)>> <</if>> <</for>> <<if _friendsHere.length > 0>> <h2 style="color: #51cf66;">🏰 Visit Friend's Estate</h2> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">You're on the guest list for these estates.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px;"> <<for _friend range _friendsHere>> <<capture _friend>> <<link "<div style='background: #51cf66; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🏰 Visit _friend.name</div>">> <<run advanceTime(5)>> <<set $tradingWithNPC = _friend>> <<set $visitingHome = true>> <<goto "NPCInteraction">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <h2 style="color: #fd7e14;">🏰 Elite Residents Outside</h2> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #fd7e14; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #aaa; margin-bottom: 15px;">These residents are currently visible on the estate grounds.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #fd7e14; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #fd7e14; margin: 0 0 10px 0;">_npc.name</h3> <p style="font-size: 14px; color: #ffb366; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<if setup.getRelationshipLevel && setup.getRelationshipLevel(_npc.name) !== "Stranger">> <p style="color: #aaa; font-size: 14px; margin: 5px 0;"><strong style="color: #51cf66;">Relationship:</strong> <<print setup.getRelationshipLevel(_npc.name)>></p> <</if>> <<link "<div style='background: #fd7e14; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #666; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="text-align: center; color: #aaa; margin: 0; font-style: italic;"> The elite residents are not visible from the street. </p> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set _npc = $lifeSwapNPC>> <<set _lifeSwapProtectedNPCs = ["Xanithar Galdenentri", "Revna McKraken", "Roisin Sullivan", "Luna Snow", "Fen Ris", "Quesha Epo", "Flona Vulri", "Mochi", "Ren", "Clover", "Bun Bun", "Clair"]>> <<set _npcNameForCheck = _npc ? (_npc.originalName || _npc.name) : "">> <<if !_npc>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <p style="color: #ff6b6b;">Error: No NPC selected for life swap.</p> [[Go Back|$lastLocation]] </div> <<elseif $possessionActive === true && $lifeSwapPortraitSource === "Roisin Sullivan">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 3px solid #ff6b6b; text-align: center;"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0;">Life Swap Unavailable</h2> <p style="color: #ccc; font-size: 16px;">You cannot life swap while possessing Roisin through the Sunfish Cuff.</p> <p style="color: #888; font-size: 14px;">Return to your own body first.</p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px;'>← Go Back</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> </div> <<elseif _lifeSwapProtectedNPCs.includes(_npcNameForCheck) && !$debugLifeSwapBypass>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: #2a2a2a; padding: 25px; border-radius: 12px; border: 3px solid #ff6b6b; text-align: center;"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0;">Life Swap Unavailable</h2> <p style="color: #ccc; font-size: 16px;">Life swap is not available for <<print _npc.name>>.</p> <p style="color: #888; font-size: 14px;">This NPC is protected from life swapping.</p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px;'>← Go Back</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="background: linear-gradient(135deg, #ff0080 0%, #7928ca 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #ff0080;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Life Swap</h1> <p style="color: white; margin: 0; font-size: 16px; text-align: center;"> Swap your entire existence with <<print _npc.name>> </p> </div> <!-- Warning/Info --> <<if $lifeSwapIsOriginalBody>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #51cf66; margin: 0 0 15px 0; font-size: 24px; text-align: center;">RETURN TO ORIGINAL BODY</h2> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> This is your original body. You can swap back without any cost. </p> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin: 0 0 15px 0; font-size: 24px; text-align: center;">WARNING</h2> <p style="color: #ccc; font-size: 16px; text-align: center; margin: 0;"> This will completely swap your life with <<print _npc.name>>. You will become them and they will become you. </p> <p style="color: #ffa500; font-size: 14px; text-align: center; margin-top: 10px;"> Your Sunfish trait will be consumed to perform this swap. </p> </div> <</if>> <!-- What Will Be Swapped --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0; font-size: 22px; border-bottom: 2px solid #9b59b6; padding-bottom: 10px;">What Will Be Swapped:</h3> <ul style="color: #ccc; font-size: 16px; line-height: 2;"> <li><strong style="color: #51cf66;">Name:</strong> Your name and their name</li> <li><strong style="color: #51cf66;">Stats:</strong> Strength, Intelligence, Charisma, Dexterity</li> <li><strong style="color: #51cf66;">Appearance:</strong> Hair, Skin, Age, Physique</li> <li><strong style="color: #51cf66;">Body Parts:</strong> Gender, Chest, Butt, Genitals</li> <li><strong style="color: #51cf66;">Physical Traits:</strong> ALL physical traits</li> <li><strong style="color: #51cf66;">Mental Traits:</strong> ALL mental traits</li> <li><strong style="color: #51cf66;">Skills:</strong> ALL skills</li> <li><strong style="color: #51cf66;">Jobs:</strong> Your job and their job</li> <li><strong style="color: #51cf66;">Relationships:</strong> ALL relationship levels with ALL NPCs</li> <li><strong style="color: #51cf66;">Portrait:</strong> NPC image path swap</li> </ul> </div> <!-- Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 25px;"> <<link "<div style='background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Confirm Life Swap</div>">> <<set $lifeSwapOldPlayerName = $firstName + " " + $lastName>> <<set $lifeSwapOldPlayerTraits = { physical: $physicalTraits ? $physicalTraits.slice() : [], mental: $mentalTraits ? $mentalTraits.slice() : [], skills: $skills ? $skills.slice() : [], appearance: JSON.parse(JSON.stringify($appearance)), bodyParts: JSON.parse(JSON.stringify($bodyParts)), stats: JSON.parse(JSON.stringify($stats)) }>> <<set $lifeSwapNPCOldName = _npc.name>> <<set $lifeSwapNPCOldTraits = { physical: _npc.physicalTraits ? _npc.physicalTraits.slice() : [], mental: _npc.mentalTraits ? _npc.mentalTraits.slice() : [], skills: _npc.skills ? _npc.skills.slice() : [], appearance: JSON.parse(JSON.stringify(_npc.appearance)), bodyParts: JSON.parse(JSON.stringify(_npc.bodyParts)), stats: JSON.parse(JSON.stringify(_npc.stats)) }>> <!-- Track original body for free swap back (only set on first swap) --> <<if !$lifeSwapOriginalBodyNPC>> <<set $lifeSwapOriginalBodyNPC = _npc.originalName || _npc.name>> <!-- Suspend cafe ownership: old life retains the cafe while player is away --> <<if $cafeOwnership && $cafeOwnership.owned>> <<set $cafeOwnership.owned = false>> <<set $cafeOwnership.suspendedByLifeSwap = true>> <</if>> <<elseif $lifeSwapIsOriginalBody>> <!-- Swapping back to original - clear the tracking --> <<set $lifeSwapOriginalBodyNPC = null>> <!-- Restore cafe ownership if it was suspended by life swap --> <<if $cafeOwnership && $cafeOwnership.suspendedByLifeSwap>> <<set $cafeOwnership.owned = true>> <<set $cafeOwnership.suspendedByLifeSwap = false>> <</if>> <</if>> <!-- Remove Sunfish trait if not swapping back to original body (unless bypass is enabled) --> <<if !$lifeSwapIsOriginalBody && !$debugLifeSwapBypass>> <<if $skills && $skills.includes("Sunfish")>> <<set $skills = $skills.filter(function(s) { return s !== "Sunfish"; })>> <</if>> <<if $physicalTraits && $physicalTraits.includes("Sunfish")>> <<set $physicalTraits = $physicalTraits.filter(function(t) { return t !== "Sunfish"; })>> <</if>> <<if $mentalTraits && $mentalTraits.includes("Sunfish")>> <<set $mentalTraits = $mentalTraits.filter(function(t) { return t !== "Sunfish"; })>> <</if>> <</if>> <<run setup.performLifeSwap(_npc)>> <!-- Ensure Soul trait stays with player after swap --> <<if !$skills>><<set $skills = []>><</if>> <<if !$skills.includes("Soul")>> <<run $skills.push("Soul")>> <</if>> <!-- Remove Soul from NPC (it transfers with player) --> <<if _npc.skills && _npc.skills.includes("Soul")>> <<set _npc.skills = _npc.skills.filter(function(s) { return s !== "Soul"; })>> <</if>> <<goto "LifeSwapTransformation">> <</link>> <<link "<div style='background: #666; color: white; padding: 18px; border-radius: 12px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Cancel</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set _oldPlayerName = $lifeSwapOldPlayerName>> <<set _oldPlayerTraits = $lifeSwapOldPlayerTraits>> <<set _oldNPCName = $lifeSwapNPCOldName>> <<set _oldNPCTraits = $lifeSwapNPCOldTraits>> <<set _newPlayerName = $firstName + " " + $lastName>> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="background: linear-gradient(135deg, #ff0080 0%, #7928ca 50%, #0080ff 100%); padding: 30px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 0 30px rgba(255,0,128,0.5); border: 2px solid #ff0080; text-align: center;"> <h1 style="color: white; margin: 0; font-size: 36px; text-shadow: 0 0 20px rgba(255,255,255,0.5);">Life Swap Complete</h1> <p style="color: rgba(255,255,255,0.9); margin: 10px 0 0 0; font-size: 18px;">Your existence has been exchanged with <<print _oldNPCName>></p> </div> <!-- Your Transformation Section --> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #ff0080; box-shadow: 0 0 20px rgba(255,0,128,0.3);"> <h2 style="color: #ff0080; margin: 0 0 20px 0; font-size: 28px; border-bottom: 2px solid #ff0080; padding-bottom: 10px;">Your Transformation</h2> <!-- Mental/Memory Changes --> <div style="background: rgba(0,0,0,0.4); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #9b59b6;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">Mental Shift</h3> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> A wave of dizziness washes over you as reality begins to blur. Your memories start to feel... distant, like watching someone else's life through frosted glass. The name "<<print _oldPlayerName>>" echoes in your mind, but it feels foreign now, like a half-forgotten dream. </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> New memories flood in, vivid and intimate. You remember <<print _oldNPCName>>'s life as if you'd lived it yourself... </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0; font-style: italic;"> <<if $mentalTraits && $mentalTraits.includes("Bimbo") && $mentalTraits.includes("Flirty")>> You remember being the life of every party, batting your eyelashes at anyone cute while your friends giggled beside you. Boys, girls - it didn't matter. You'd twirl your hair, lean in close, and watch them melt. School was just a place to show off new outfits and collect phone numbers. Why bother with books when you could get anyone to do your homework with a pout and a promise? <<elseif $mentalTraits && $mentalTraits.includes("Bimbo") && $mentalTraits.includes("Submissive")>> You remember the blissful simplicity of letting others think for you. Why worry about complicated stuff when someone smarter could just tell you what to do? You'd nod along happily, eager to please, finding joy in being useful even if you didn't quite understand why. Being pretty and obedient was so much easier than being smart. <<elseif $mentalTraits && $mentalTraits.includes("Bimbo")>> You remember hours in front of mirrors, perfecting your makeup, practicing your pout. Complex thoughts would drift away like clouds, replaced by simple pleasures - shopping, gossip, looking hot. Friends would talk about careers and futures while you wondered what color to paint your nails next. Life was just... easier when you didn't think too hard. <<elseif $mentalTraits && $mentalTraits.includes("Dominant") && $mentalTraits.includes("Cruel")>> You remember the intoxicating rush of power, of watching others squirm beneath your gaze. You didn't just want control - you wanted them to suffer for the privilege of serving you. Tears, begging, broken spirits... these were your trophies. The weak existed to be dominated, and you were born to rule over them with an iron fist. <<elseif $mentalTraits && $mentalTraits.includes("Dominant") && $mentalTraits.includes("Confident")>> You remember walking into rooms and feeling everyone's attention snap to you like magnets. People naturally deferred to you, sought your approval, waited for your commands. Leadership wasn't something you learned - it was simply who you were. Others followed because they recognized greatness when they saw it. <<elseif $mentalTraits && $mentalTraits.includes("Dominant")>> You remember the satisfaction of being in charge, of having others look to you for direction. Your word was law in your social circles. People didn't argue with you - they obeyed. And those who didn't? They learned quickly. Power wasn't given to you; you took it, and you held it with an iron grip. <<elseif $mentalTraits && $mentalTraits.includes("Submissive") && $mentalTraits.includes("Perverted")>> You remember the sweet surrender of giving yourself completely to another's desires. The thrill of being used, of existing solely for someone else's pleasure. Boundaries were suggestions, and "no" was a word that rarely crossed your lips. Being wanted, being taken, being owned - these were your deepest cravings. <<elseif $mentalTraits && $mentalTraits.includes("Submissive") && $mentalTraits.includes("Shy")>> You remember always fading into the background, grateful when someone else made decisions for you. Speaking up felt impossible - what if people judged you? It was safer to follow, to agree, to let stronger personalities take the lead. Being invisible was comfortable. Being commanded was a relief. <<elseif $mentalTraits && $mentalTraits.includes("Submissive")>> You remember the peace that came with surrender. Following orders felt natural, safe. When someone took charge, you could finally relax, finally stop pretending to be something you weren't. Being useful to others gave your life meaning. Obedience wasn't weakness - it was freedom. <<elseif $mentalTraits && $mentalTraits.includes("Delinquent") && $mentalTraits.includes("Brave")>> You remember being the one who'd take any dare, start any fight, tell any authority figure exactly where they could shove their rules. Fear was for other people. You'd stare down cops, teachers, gang members - anyone who thought they could intimidate you. Scars were just souvenirs from a life lived without limits. <<elseif $mentalTraits && $mentalTraits.includes("Delinquent") && $mentalTraits.includes("Perverted")>> You remember dark alleys and darker appetites. Rules were for suckers, and that applied to bedroom rules too. You took what you wanted, when you wanted, from whoever was willing - or foolish enough to catch your eye. Detention was just another place to scout for new conquests. <<elseif $mentalTraits && $mentalTraits.includes("Delinquent")>> You remember the rush of breaking every rule they tried to put on you. Skipping class to smoke behind the bleachers, tagging walls, petty theft for the thrill of it. Authority figures were just obstacles to mock. You'd been expelled twice, arrested once, and you wore each incident like a badge of honor. <<elseif $mentalTraits && $mentalTraits.includes("Nerd") && $mentalTraits.includes("Shy")>> You remember hiding in the library during lunch, burying yourself in books to avoid the terrifying social jungle of the cafeteria. Perfect grades were your only pride, your only proof of worth. You'd stammer and blush if anyone actually talked to you, then replay the conversation a thousand times, cringing at every awkward word. <<elseif $mentalTraits && $mentalTraits.includes("Nerd") && $mentalTraits.includes("Arrogant")>> You remember the exhausting burden of being smarter than everyone around you. Teachers were idiots who couldn't keep up. Classmates were mouth-breathing simpletons. You'd correct people constantly, roll your eyes at wrong answers, and wonder why no one wanted to be your friend. Their loss - they couldn't handle your brilliance anyway. <<elseif $mentalTraits && $mentalTraits.includes("Nerd")>> You remember late nights studying, the glow of computer screens, the satisfaction of understanding things others couldn't grasp. Social events were awkward ordeals, but academic achievements? Those were your domain. Top of every class, winner of every science fair, the one teachers actually respected. <<elseif $mentalTraits && $mentalTraits.includes("Jock") && $mentalTraits.includes("Confident")>> You remember being the star everyone wanted to be or be with. Championships, cheering crowds, your name chanted by hundreds. Your body was a finely tuned machine, and you showed it off at every opportunity. College scouts, sponsorship offers, the world at your feet. You were destined for greatness, and everyone knew it. <<elseif $mentalTraits && $mentalTraits.includes("Jock") && $mentalTraits.includes("Arrogant")>> You remember looking down at the losers who couldn't throw, couldn't run, couldn't compete. What was the point of people who couldn't win? You'd shove nerds into lockers, mock the unathletic, and bask in the worship of those who recognized athletic superiority. Second place was just first loser. <<elseif $mentalTraits && $mentalTraits.includes("Jock")>> You remember the burn of pushing your body to its limits, the roar of crowds when you scored, the camaraderie of teammates who'd bleed for each other. Early morning practices, protein shakes, the sweet exhaustion of giving everything you had. Sports weren't just games - they were life. <<elseif $mentalTraits && $mentalTraits.includes("Goth") && $mentalTraits.includes("Creative")>> You remember filling journals with dark poetry and morbid sketches, finding beauty in decay and meaning in melancholy. While others chased popularity, you explored the shadows - art that disturbed, music that ached, fashion that screamed "I'm not like you." Being misunderstood was the point. <<elseif $mentalTraits && $mentalTraits.includes("Goth") && $mentalTraits.includes("Perverted")>> You remember nights in underground clubs, leather and lace, pleasures that "normal" people would never understand. Pain and pleasure blurred together beautifully. Your lovers were as dark as your wardrobe, drawn to your dangerous aesthetic, eager to explore forbidden territories with you. <<elseif $mentalTraits && $mentalTraits.includes("Goth")>> You remember embracing the darkness while others chased the light. Black clothes, heavy eyeliner, music that matched your melancholy soul. Cemetery walks at midnight, candles in your room, feeling like the only one who understood that beauty lived in shadows. Mainstream society could keep their shallow happiness. <<elseif $mentalTraits && $mentalTraits.includes("Prep") && $mentalTraits.includes("Ambitious")>> You remember networking at country clubs since you were twelve, learning early that it's not what you know but who you know. Perfect grades, perfect clothes, perfect connections. Everything was a stepping stone to success. You'd smile at people you despised because they might be useful someday. <<elseif $mentalTraits && $mentalTraits.includes("Prep") && $mentalTraits.includes("Flirty")>> You remember being the popular one everyone wanted to date. Designer clothes, perfect hair, effortless charm. You'd flirt with everyone worth knowing, collecting admirers like accessories. Social climbing was a game, and romance was just another tool in your arsenal. <<elseif $mentalTraits && $mentalTraits.includes("Prep")>> You remember country club tennis lessons, charity galas, summer homes. Everything had to be perfect - grades, clothes, reputation. You learned to smile even when you wanted to scream, to play the game of social status like your life depended on it. Because in your world, it did. <<elseif $mentalTraits && $mentalTraits.includes("Diva") && $mentalTraits.includes("Dominant")>> You remember demanding absolute perfection from everyone around you - and getting it. Minions scrambled to meet your exacting standards while you critiqued their failures mercilessly. You weren't bossy; you were a leader. You didn't have tantrums; you had high standards. And anyone who couldn't handle that could get out of your spotlight. <<elseif $mentalTraits && $mentalTraits.includes("Diva")>> You remember always being the center of attention - exactly where you belonged. Meltdowns when things weren't perfect, dramatic exits, speeches about how no one understood your genius. The world revolved around you, and anyone who forgot that would be reminded. Loudly. <<elseif $mentalTraits && $mentalTraits.includes("Tomboy") && $mentalTraits.includes("Brave")>> You remember being tougher than any of the boys, taking hits and giving them back twice as hard. Dresses were prisons; dirt was freedom. You'd climb the highest trees, fight the biggest bullies, and refuse to cry no matter what. "Ladylike" was an insult you wore as a badge of honor. <<elseif $mentalTraits && $mentalTraits.includes("Tomboy")>> You remember scraped knees and grass stains, preferring sports to dolls, hanging with the boys because girls were too dramatic. You'd arm wrestle, belch contests, video game marathons. People tried to put you in pink; you responded with mud and defiance. <<elseif $mentalTraits && $mentalTraits.includes("Femboy") && $mentalTraits.includes("Confident")>> You remember owning your unique style with pride, strutting in skirts while others could only stare. Let them look. Let them judge. You were beautiful and you knew it. The bravest thing wasn't fighting - it was being yourself when the world wanted you to conform. <<elseif $mentalTraits && $mentalTraits.includes("Femboy") && $mentalTraits.includes("Shy")>> You remember the secret thrill of trying on clothes society said weren't for you, the terror and excitement of finally going out in them. Every stare felt like a judgment, but you couldn't stop. This was who you were, even if the world wasn't ready to see it. <<elseif $mentalTraits && $mentalTraits.includes("Femboy")>> You remember discovering that gender was a spectrum, not a prison. Skirts felt right. Makeup was art. The confusion on people's faces when they couldn't categorize you was its own reward. You weren't trying to be something you weren't - you were finally being exactly what you were. <<elseif $mentalTraits && $mentalTraits.includes("Geek") && $mentalTraits.includes("Perverted")>> You remember the overlap between fandom and fantasy, convention hookups with fellow enthusiasts, fanfiction that got increasingly explicit. Your interests went deep - really deep. The vanilla world would never understand the particular pleasures of a truly devoted geek. <<elseif $mentalTraits && $mentalTraits.includes("Geek")>> You remember marathon sessions of your favorite games, heated debates about canon vs fanon, the joy of finding someone who loved the same obscure things you did. Collections displayed proudly, conventions circled on calendars, a rich inner world more vivid than mundane reality. <<elseif $mentalTraits && $mentalTraits.includes("Perverted") && $mentalTraits.includes("Confident")>> You remember owning your desires without shame. While others hid their fantasies, you pursued them openly. Lovers knew exactly what they were getting into - and lined up anyway. Your reputation preceded you, and you made sure it was well-earned. <<elseif $mentalTraits && $mentalTraits.includes("Perverted")>> You remember the constant thrum of desire coloring every interaction. Innocent conversations became charged with subtext. Your browser history would make a sailor blush. Finding others who shared your particular appetites, exploring depths that vanilla people couldn't imagine. <<elseif $mentalTraits && $mentalTraits.includes("Confident") && $mentalTraits.includes("Flirty")>> You remember commanding every room you walked into, using charm like a weapon. Flirting wasn't desperate - it was sport. You'd leave a trail of flustered admirers wondering what just happened, already moving on to your next conquest with a knowing smile. <<elseif $mentalTraits && $mentalTraits.includes("Confident")>> You remember the ease of knowing your own worth. Job interviews, first dates, high-pressure moments - you thrived on them all. Self-doubt was for other people. You walked through life like you owned it, because in many ways, you did. <<elseif $mentalTraits && $mentalTraits.includes("Shy") && $mentalTraits.includes("Kind")>> You remember watching from the sidelines, too nervous to join in but always noticing who needed help. Quiet acts of kindness, anonymous generosity, being there for people even when you couldn't find words to say. Your gentle heart ached for others, even as social anxiety kept you distant. <<elseif $mentalTraits && $mentalTraits.includes("Shy")>> You remember the safety of corners at parties, the relief when plans got cancelled, the exhaustion of pretending to be okay around people. Your inner world was rich and deep, but sharing it felt impossible. Being alone wasn't lonely - it was sanctuary. <<elseif $mentalTraits && $mentalTraits.includes("Flirty")>> You remember the thrill of the chase, the art of the tease. Every interaction was an opportunity to make someone's heart race. You'd leave breadcrumbs of interest, watch them follow, then decide if they were worth catching. The game never got old. <<elseif $mentalTraits && $mentalTraits.includes("Intelligent") && $mentalTraits.includes("Ambitious")>> You remember always being ten steps ahead, seeing angles others missed. School was too easy; you were already planning your empire. Knowledge was power, and you hoarded both. Scholarships, opportunities, connections - you collected them like weapons for future battles. <<elseif $mentalTraits && $mentalTraits.includes("Intelligent")>> You remember the isolation of being smarter than your peers, teachers who couldn't challenge you, conversations that bored you. Your mind craved stimulation that rarely came. Books were better company than most people. At least they didn't ask you to explain things twice. <<elseif $mentalTraits && $mentalTraits.includes("Creative")>> You remember seeing possibilities everywhere others saw nothing. Ideas came faster than you could capture them - notebooks filled with half-finished brilliance. The mundane world was just raw material for your imagination. Creating wasn't a hobby; it was as necessary as breathing. <<elseif $mentalTraits && $mentalTraits.includes("Ambitious")>> You remember the hunger that never faded, the drive that pushed you past everyone else. Second place was failure. Good enough never was. You'd sacrifice sleep, relationships, peace of mind - whatever it took to climb higher. The top was the only acceptable destination. <<elseif $mentalTraits && $mentalTraits.includes("Lucky")>> You remember a lifetime of improbable wins and narrow escapes. Finding money on the ground, meeting the right person at the right time, disasters that somehow missed you. People called it luck; you just called it Tuesday. The universe seemed to bend in your favor. <<elseif $mentalTraits && $mentalTraits.includes("Brave")>> You remember standing up when everyone else sat down, speaking out when others stayed silent. Fear existed, but it never stopped you. Bullies backed down from your stare. Challenges were just opportunities to prove yourself. Courage wasn't the absence of fear - it was telling fear to shut up. <<elseif $mentalTraits && $mentalTraits.includes("Kind")>> You remember the faces of everyone you helped, the warmth of genuine gratitude. Stray animals, lonely kids, overwhelmed strangers - you couldn't pass by someone in need. Your heart was too big for a world this harsh, but you kept it open anyway. <<elseif $mentalTraits && $mentalTraits.includes("Lazy")>> You remember the art of doing absolutely nothing, elevated to a lifestyle. Why work hard when you could work barely? Deadlines were suggestions, ambition was exhausting, and naps were sacred. You'd perfected the minimum effort required to coast through life. <<elseif $mentalTraits && $mentalTraits.includes("Arrogant")>> You remember being right about everything - or at least knowing you were. Other people's opinions were just noise. You'd correct, condescend, and dismiss without a second thought. If they couldn't handle your superiority, that was their problem. <<elseif $mentalTraits && $mentalTraits.includes("Cruel")>> You remember the satisfaction of making others hurt. Words chosen for maximum damage, actions designed to wound. Empathy was weakness. Kindness was manipulation. The world was full of victims, and you were happy to help them remember their place. <<else>> You remember ordinary days that somehow felt like someone else's life. Morning routines, familiar places, faces of people you must have known. The memories are there, settling into place, becoming yours whether you want them or not. <</if>> </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> These memories settle into your mind like they've always been there, pushing aside your old self. You feel your personality shifting, molding itself to fit this new identity. </p> <!-- Trait-based personality changes --> <<if $mentalTraits && $mentalTraits.length > 0>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $mentalTraits.includes("Confident")>> A surge of confidence fills you. Where you once hesitated, you now feel bold and self-assured. You know you're desirable, and you're not afraid to show it. <</if>> <<if $mentalTraits.includes("Submissive")>> A warm, yielding sensation spreads through your mind. You find yourself wanting to please others, to follow rather than lead. The thought of being commanded sends a pleasant shiver down your spine. <</if>> <<if $mentalTraits.includes("Dominant")>> Power courses through your thoughts. You feel an overwhelming urge to take control, to command attention, to bend others to your will. Leadership feels natural now. <</if>> <<if $mentalTraits.includes("Bimbo")>> Your thoughts become simpler, lighter. Complex worries fade away, replaced by a bubbly, carefree attitude. You find yourself giggling at things you wouldn't have before. Looking hot and having fun is all that matters now. <</if>> <<if $mentalTraits.includes("Perverted")>> Your mind fills with lewd thoughts. Every interaction now has a sensual undertone, and you find yourself imagining erotic scenarios constantly. Your libido has gone into overdrive. <</if>> <<if $mentalTraits.includes("Shy")>> You feel yourself becoming more reserved, more hesitant. The thought of being the center of attention makes you want to hide. You'll need to work up courage for things that once came easily. <</if>> <<if $mentalTraits.includes("Flirty")>> A playful energy fills you. You want to tease, to flirt, to make others blush. Every conversation feels like an opportunity for seduction. <</if>> </p> <</if>> </div> <!-- Physical Changes --> <div style="background: rgba(0,0,0,0.4); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ff6b6b;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">Physical Transformation</h3> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Your body begins to tingle all over as the transformation takes hold. You gasp as you feel your form shifting, reshaping itself into something new. </p> <!-- Gender change --> <<if _oldPlayerTraits.bodyParts.gender !== $bodyParts.gender>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if $bodyParts.gender === "female">> The most intense sensation hits between your legs. You moan as you feel your manhood receding, reshaping, your body becoming smooth and feminine. New nerve endings awaken as your sex transforms completely. You feel yourself becoming wet with arousal at the strange new sensations. Your hips widen with a satisfying crack, your waist narrows, and you feel unmistakably, wonderfully female. <<else>> An intense pressure builds between your legs. You groan as new flesh forms, growing and hardening. Your feminine curves begin to flatten and reshape themselves. Your shoulders broaden, your jaw becomes more defined. The transformation leaves you breathing heavily, unmistakably male. <</if>> </p> <</if>> <!-- Chest changes --> <<if _oldPlayerTraits.bodyParts.chest !== $bodyParts.chest>> <<set _chestSize = $bodyParts.chest.toLowerCase().replace(/ /g, "")>> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _chestImageHTML = '<div style="text-align: center; margin: 20px 0;"><img src="Images/PostSwap/Chest_' + _chestSize + '.webp" style="max-width: 60%; border-radius: 10px; border: 2px solid #FF69B4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Chest Transformation"></div>'>> <<print _chestImageHTML>> <</if>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if _chestSize === "huge" || _chestSize === "giant" || _chestSize === "gigantic">> Your chest begins to swell dramatically. You watch in amazement as flesh fills out, growing heavier and heavier. Your new breasts push outward, straining against any clothing, each movement sending waves of pleasure through your sensitive new tissue. They're massive, impossible to ignore, and achingly sensitive to every touch. <<elseif _chestSize === "large">> Your chest swells pleasantly, filling out into generous, heavy breasts. They bounce with each breath, sensitive nipples hardening at the cool air. You cup them experimentally, gasping at how good it feels. <<elseif _chestSize === "medium">> Your chest reshapes into a pleasant handful, proportioned and perky. The new weight feels natural, enticing. Your nipples are incredibly sensitive now. <<elseif _chestSize === "small">> Your chest becomes petite but perfectly formed, small mounds with sensitive peaks that react to every sensation. <<elseif _chestSize === "flat" || _chestSize === "flatmasculine">> Your chest flattens, any curves receding until you're left with a smooth, toned surface. The sensitivity fades to a more masculine baseline. <</if>> </p> <</if>> <!-- Butt changes --> <<if _oldPlayerTraits.bodyParts.butt !== $bodyParts.butt>> <<set _buttSize = $bodyParts.butt.toLowerCase().replace(/ /g, "")>> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _buttImageHTML = '<div style="text-align: center; margin: 20px 0;"><img src="Images/PostSwap/Butt_' + _buttSize + '.webp" style="max-width: 60%; border-radius: 10px; border: 2px solid #FF69B4; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Butt Transformation"></div>'>> <<print _buttImageHTML>> <</if>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if _buttSize === "huge" || _buttSize === "giant" || _buttSize === "gigantic">> Your rear begins to expand dramatically, flesh filling out into a massive, attention-commanding ass. Each cheek grows heavy and round, jiggling with every movement. You can feel the weight of it, the way it demands attention. <<elseif _buttSize === "large" || _buttSize === "big">> Your backside swells into a generous, curvy rear that fills out any clothing perfectly. It's the kind of ass that turns heads and invites stares. <<elseif _buttSize === "medium">> Your rear reshapes into a nicely proportioned bottom, curved and attractive without being excessive. <<elseif _buttSize === "small" || _buttSize === "flat" || _buttSize === "flatmasculine">> Your backside becomes smaller and tighter, compact and athletic. <</if>> </p> <</if>> <!-- Genital changes --> <<if _oldPlayerTraits.bodyParts.genitals !== $bodyParts.genitals>> <<set _newGenitals = $bodyParts.genitals.toLowerCase()>> <<set _oldGenitals = _oldPlayerTraits.bodyParts.genitals.toLowerCase()>> <<set _genitalDescriptor = "Average">> <<if _newGenitals.includes("big")>><<set _genitalDescriptor = "Big">> <<elseif _newGenitals.includes("small")>><<set _genitalDescriptor = "Small">> <<elseif _newGenitals.includes("tight")>><<set _genitalDescriptor = "Tight">> <<elseif _newGenitals.includes("loose")>><<set _genitalDescriptor = "Loose">> <</if>> <<set _genitalType = _newGenitals.includes("penis") ? "penis" : "vagina">> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.eroticImagesEnabled>> <<set _genitalImageHTML = '<div style="text-align: center; margin: 20px 0;"><img src="Images/PostSwap/' + _genitalDescriptor + '_' + _genitalType + '.webp" style="max-width: 60%; border-radius: 10px; border: 2px solid #9370DB; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Genital Transformation"></div>'>> <<print _genitalImageHTML>> <</if>> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<if _oldGenitals.includes("penis") && !_newGenitals.includes("penis")>> An overwhelming wave of sensation crashes over you as the profound transformation begins. Your cock tingles intensely before it starts shrinking, pulling inward, inverting. You feel your testicles ascending, transforming. Flesh splits and reforms - soft, sensitive folds emerge where your manhood once was. When it's done, you have a complete, wet pussy. You tentatively explore the soft folds, slipping a finger inside and gasping at the new sensations. Your new vagina throbs with sensitivity. <<elseif !_oldGenitals.includes("penis") && _newGenitals.includes("penis")>> An overwhelming surge of sensation crashes through your core. Your vaginal walls begin closing, sealing as flesh pushes outward. Your clitoris extends, growing rapidly, thickening and lengthening into a full shaft. A cock grows from where your pussy was, extending outward, getting harder. Your ovaries descend and transform into testicles. When it's done, you stare down at your new cock jutting proudly. You wrap your hand around the shaft, feeling the heat, the hardness. Your new penis throbs insistently, already leaking. <<elseif _newGenitals.includes("penis")>> Your cock tingles and shifts, the shaft adjusting itself to its new size. <<if _genitalDescriptor === "Big">>You gasp as your penis swells, thickening and lengthening dramatically. Veins become prominently visible as your cock grows heavier, more substantial.<<elseif _genitalDescriptor === "Small">>You feel your penis contracting, shrinking to more modest proportions. The shaft slims down, becoming more petite.<<else>>Your penis settles into comfortable, average proportions.<</if>> <<else>> Your pussy tingles as it transforms to its new state. <<if _genitalDescriptor === "Tight">>You gasp as your internal muscles contract powerfully, the walls of your vagina squeezing inward, becoming incredibly tight and gripping.<<elseif _genitalDescriptor === "Loose">>Your vaginal walls relax and open, becoming more spacious and accommodating inside.<<else>>Your vagina settles into average tightness - moderate and responsive.<</if>> <</if>> </p> <</if>> <!-- Hair and appearance --> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0;"> Your hair shifts and changes, becoming <<print $appearance.hairLength>> and <<print $appearance.hairColor.toLowerCase()>>. Your skin takes on a <<print $appearance.skinTone>> tone, smooth and flawless. When the tingling finally fades, you're left breathing heavily, inhabiting a body that is entirely new yet somehow feels perfectly natural. </p> </div> <!-- Skills --> <<if $skills && $skills.length > 0>> <div style="background: rgba(0,0,0,0.4); padding: 20px; border-radius: 10px; border-left: 4px solid #51cf66;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">New Abilities</h3> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0;"> Knowledge you never had floods into your mind. You suddenly know how to do things that would have seemed impossible before. Your new skills feel natural, like muscle memory you've always had: <span style="color: #51cf66; font-weight: bold;"><<print $skills.join(", ")>></span>. </p> </div> <</if>> </div> <!-- Their Transformation Section --> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 3px solid #0080ff; box-shadow: 0 0 20px rgba(0,128,255,0.3);"> <h2 style="color: #0080ff; margin: 0 0 20px 0; font-size: 28px; border-bottom: 2px solid #0080ff; padding-bottom: 10px;"><<print _oldNPCName>>'s Transformation</h2> <div style="background: rgba(0,0,0,0.4); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #4dabf7;"> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You watch in fascination as <<print _oldNPCName>> begins to change before your eyes. Their expression goes slack for a moment, eyes unfocusing as their memories shift and rearrange themselves. When they blink back to awareness, there's something different in their gaze - they're looking at you with your old eyes, your old personality peering out from behind their changing features. </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> Their body begins to shift and reshape. <<if _oldNPCTraits.bodyParts.gender !== _oldPlayerTraits.bodyParts.gender>> <<if _oldPlayerTraits.bodyParts.gender === "female">> You watch their masculine features soften, hips widening, chest swelling as they become unmistakably female. They gasp and moan at the sensations, hands exploring their new curves. <<else>> Their feminine curves begin to flatten and harden, shoulders broadening as masculinity takes hold. They grunt as new anatomy forms between their legs. <</if>> <</if>> </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> <<set _theirNewChest = _oldPlayerTraits.bodyParts.chest.toLowerCase()>> <<if _theirNewChest === "huge" || _theirNewChest === "giant" || _theirNewChest === "gigantic">> Their chest swells dramatically, massive breasts forming that strain against their clothing. They cup the heavy flesh in disbelief, gasping at the sensitivity. <<elseif _theirNewChest === "large">> Their chest fills out into generous, bouncing breasts that they can't help but stare down at in amazement. <<elseif _theirNewChest === "flat" || _theirNewChest === "flat masculine">> Their chest flattens, any curves disappearing into a smooth, masculine plane. <</if>> </p> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0;"> Their hair shifts to <<print _oldPlayerTraits.appearance.hairLength>> <<print _oldPlayerTraits.appearance.hairColor.toLowerCase()>>, skin becoming <<print _oldPlayerTraits.appearance.skinTone>>. When the transformation completes, they look exactly like you used to - they ARE you now, or at least, they have your old body and your old life. They blink at you with confused recognition, adjusting to their new existence as <<print _oldPlayerName>>. </p> </div> <!-- Their mental changes --> <<if _oldPlayerTraits.mental && _oldPlayerTraits.mental.length > 0>> <div style="background: rgba(0,0,0,0.4); padding: 20px; border-radius: 10px; border-left: 4px solid #9b59b6;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">Their New Personality</h3> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.8; margin: 0;"> You can see the personality shift happening behind their eyes. They're inheriting your old traits: <span style="color: #9b59b6; font-weight: bold;"><<print _oldPlayerTraits.mental.join(", ")>></span>. <<if _oldPlayerTraits.mental.includes("Confident")>> They stand a little straighter, a new self-assurance in their posture. <</if>> <<if _oldPlayerTraits.mental.includes("Submissive")>> Their eyes become softer, more deferential, waiting for direction. <</if>> <<if _oldPlayerTraits.mental.includes("Bimbo")>> A vapid smile spreads across their face as complex thoughts drain away, replaced by simple, bubbly happiness. <</if>> They're becoming the person you used to be. </p> </div> <</if>> </div> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff0080 0%, #7928ca 100%); color: white; padding: 18px 50px; border-radius: 12px; font-weight: bold; font-size: 20px; box-shadow: 0 0 20px rgba(255,0,128,0.5); cursor: pointer;'>Begin Your New Life</div>">> <!-- Check for Mayor job achievement after life swap --> <<if $jobs && $jobs.includes("City Mayor")>> <<run setup.achievements.unlock("become_mayor")>> <</if>> <<set _exitTo = $preNPCLocation || $lastLocation || "Downtown">> <<goto _exitTo>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _pole = setup.fishing.getCurrentPole()>> <<set _poleTier = $fishingPole || 0>> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invFull = setup.fishing.isInventoryFull()>> <<set _themeColor = "#f4a460">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Sunfish Cuff: Lunar Crescent rare drop on crescent-moon ocean fishing --> <<run setup.sunfishCuff.ensureState(); setup.moon.ensureState();>> <<set _cuffMoonOk = ($moonPhase === "Waxing Crescent") || ($moonPhase === "Waning Crescent")>> <<if $cuffPieces && $cuffPieces.band && !$cuffPieces.crescent && _cuffMoonOk>> <div style="background: linear-gradient(135deg, #0a1a30 0%, #1a0a30 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; margin: 0 auto 25px auto; max-width: 720px; box-shadow: 0 0 24px rgba(201,169,255,0.25);"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">Pale crescent light scrapes the wave-tops. Something fine and curved washes against your boot. You crouch and pick it up before it can slide back into the foam.</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">A crescent of polished bone, weighted at one end. The Lunar Crescent of the Sunfish Cuff. You suspect it would only have surfaced under a moon like this one.</p> <p style="color: #c9a9ff; font-weight: bold; text-align: center; margin: 0;">You found the Lunar Crescent.</p> </div> <<run setup.sunfishCuff.grantPiece("crescent")>> <</if>> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "Beach">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _themeColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _themeColor>>44; margin-bottom: 20px;"> <h2 style="color: <<print _themeColor>>; margin: 0 0 10px 0; text-align: center;">🏖️ Beach Fishing</h2> <p style="color: #aaa; margin: 0; font-size: 14px; text-align: center;">The gentle waves lap at the shore. Perfect for catching coastal fish.</p> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 15px;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;">Lv <<print _level>></div> <div style="color: #888; font-size: 11px;">Skill</div> <div style="background: #333; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #3498db, #2ecc71); height: 100%; width: <<print _xpProgress.percent>>%;"></div> </div> </div> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> <div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #888; font-size: 11px;">Collection</div> </div> </div> </div> </div> <!-- Equipment Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: <<if _poleTier === 4>>#e040fb<<elseif _poleTier === 3>>#ffd700<<elseif _poleTier === 2>>#3498db<<elseif _poleTier === 1>>#aaa<<else>>#e74c3c<</if>>; font-size: 16px; font-weight: bold;">🎣 <<if _hasRod>><<print _pole.name>><<else>>No Rod<</if>></div> <<if _hasRod>> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 11px;">Max: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity.toUpperCase()>></span></div> <<if _poleTier === 4>><div style="color: #51cf66; font-size: 10px; margin-top: 3px;">No Trash • Treasure Bonus</div><</if>> <<else>> <div style="color: #e74c3c; font-size: 11px;">Buy at dealership</div> <</if>> </div> </div> <!-- Cast Line Button --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px #2ecc7144; margin-bottom: 20px; text-align: center;"> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #ff6b6b;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #ff6b6b; font-size: 20px; font-weight: bold;">Too Exhausted to Fish</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">You need to sleep before you can fish</div> </div> <<elseif !_hasRod>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">No Fishing Rod!</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Buy one at the dealership</div> </div> <<elseif _invFull>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🐟</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">Inventory Full</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Sell fish at the dealership</div> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; cursor: pointer; border: 3px solid #27ae60; box-shadow: 0 4px 15px rgba(39, 174, 96, 0.5);'><div style='font-size: 40px; margin-bottom: 8px;'>🎣</div><div style='color: white; font-size: 20px; font-weight: bold;'>Cast Line</div></div>">> <<set $fishingLocation = "beach">> <<goto "FishingQTE">> <</link>> <</if>> </div> <!-- Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>📖 Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "Beach">><</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _pole = setup.fishing.getCurrentPole()>> <<set _poleTier = $fishingPole || 0>> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invFull = setup.fishing.isInventoryFull()>> <<set _themeColor = "#1a5276">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Sunfish Cuff: Lunar Crescent rare drop on crescent-moon ocean fishing --> <<run setup.sunfishCuff.ensureState(); setup.moon.ensureState();>> <<set _cuffMoonOk = ($moonPhase === "Waxing Crescent") || ($moonPhase === "Waning Crescent")>> <<if $cuffPieces && $cuffPieces.band && !$cuffPieces.crescent && _cuffMoonOk>> <div style="background: linear-gradient(135deg, #0a1a30 0%, #1a0a30 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; margin: 0 auto 25px auto; max-width: 720px; box-shadow: 0 0 24px rgba(201,169,255,0.25);"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">Pale crescent light scrapes the wave-tops. Something fine and curved washes against your boot. You crouch and pick it up before it can slide back into the foam.</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">A crescent of polished bone, weighted at one end. The Lunar Crescent of the Sunfish Cuff. You suspect it would only have surfaced under a moon like this one.</p> <p style="color: #c9a9ff; font-weight: bold; text-align: center; margin: 0;">You found the Lunar Crescent.</p> </div> <<run setup.sunfishCuff.grantPiece("crescent")>> <</if>> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #1a5276; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #1a527644; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "Docks">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _themeColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _themeColor>>44; margin-bottom: 20px;"> <h2 style="color: <<print _themeColor>>; margin: 0 0 10px 0; text-align: center;">🚢 Dock Fishing</h2> <p style="color: #aaa; margin: 0; font-size: 14px; text-align: center;">Deep water fishing. Home to bigger, more valuable catches.</p> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 15px;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;">Lv <<print _level>></div> <div style="color: #888; font-size: 11px;">Skill</div> <div style="background: #333; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #3498db, #2ecc71); height: 100%; width: <<print _xpProgress.percent>>%;"></div> </div> </div> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> <div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #888; font-size: 11px;">Collection</div> </div> </div> </div> </div> <!-- Equipment Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: <<if _poleTier === 4>>#e040fb<<elseif _poleTier === 3>>#ffd700<<elseif _poleTier === 2>>#3498db<<elseif _poleTier === 1>>#aaa<<else>>#e74c3c<</if>>; font-size: 16px; font-weight: bold;">🎣 <<if _hasRod>><<print _pole.name>><<else>>No Rod<</if>></div> <<if _hasRod>> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 11px;">Max: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity.toUpperCase()>></span></div> <<if _poleTier === 4>><div style="color: #51cf66; font-size: 10px; margin-top: 3px;">No Trash • Treasure Bonus</div><</if>> <<else>> <div style="color: #e74c3c; font-size: 11px;">Buy at dealership</div> <</if>> </div> </div> <!-- Cast Line Button --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px #2ecc7144; margin-bottom: 20px; text-align: center;"> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #ff6b6b;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #ff6b6b; font-size: 20px; font-weight: bold;">Too Exhausted to Fish</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">You need to sleep before you can fish</div> </div> <<elseif !_hasRod>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">No Fishing Rod!</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Buy one at the dealership</div> </div> <<elseif _invFull>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🐟</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">Inventory Full</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Sell fish at the dealership</div> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; cursor: pointer; border: 3px solid #27ae60; box-shadow: 0 4px 15px rgba(39, 174, 96, 0.5);'><div style='font-size: 40px; margin-bottom: 8px;'>🎣</div><div style='color: white; font-size: 20px; font-weight: bold;'>Cast Line</div></div>">> <<set $fishingLocation = "docks">> <<goto "FishingQTE">> <</link>> <</if>> </div> <!-- Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>📖 Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #1a5276; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #1a527644; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "Docks">><</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _pole = setup.fishing.getCurrentPole()>> <<set _poleTier = $fishingPole || 0>> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invFull = setup.fishing.isInventoryFull()>> <<set _themeColor = "#2ecc71">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Location Image (Day/Night Cycle) --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <<set _timeOfDay = getTimeOfDay()>> <<if _timeOfDay === "morning">> <<set _locationImg = "Images/Locations/Pond.webp">> <<elseif _timeOfDay === "afternoon">> <<set _locationImg = "Images/Locations/PondDay.webp">> <<else>> <<set _locationImg = "Images/Locations/PondNight.webp">> <</if>> <div style="text-align: center; margin: 20px 0;"> <img @src="_locationImg" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Hidden Pond"> </div> <</if>> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #2ecc71; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #2ecc7144; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "SeabassPark">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _themeColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _themeColor>>44; margin-bottom: 20px;"> <h2 style="color: <<print _themeColor>>; margin: 0 0 10px 0; text-align: center;">🌿 Hidden Pond</h2> <p style="color: #aaa; margin: 0; font-size: 14px; text-align: center;">A secret fishing spot. Legends say rare fish dwell here.</p> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 15px;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;">Lv <<print _level>></div> <div style="color: #888; font-size: 11px;">Skill</div> <div style="background: #333; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #3498db, #2ecc71); height: 100%; width: <<print _xpProgress.percent>>%;"></div> </div> </div> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> <div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #888; font-size: 11px;">Collection</div> </div> </div> </div> </div> <!-- Equipment Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: <<if _poleTier === 4>>#e040fb<<elseif _poleTier === 3>>#ffd700<<elseif _poleTier === 2>>#3498db<<elseif _poleTier === 1>>#aaa<<else>>#e74c3c<</if>>; font-size: 16px; font-weight: bold;">🎣 <<if _hasRod>><<print _pole.name>><<else>>No Rod<</if>></div> <<if _hasRod>> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 11px;">Max: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity.toUpperCase()>></span></div> <<if _poleTier === 4>><div style="color: #51cf66; font-size: 10px; margin-top: 3px;">No Trash • Treasure Bonus</div><</if>> <<else>> <div style="color: #e74c3c; font-size: 11px;">Buy at dealership</div> <</if>> </div> </div> <!-- Cast Line Button --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px #2ecc7144; margin-bottom: 20px; text-align: center;"> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #ff6b6b;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #ff6b6b; font-size: 20px; font-weight: bold;">Too Exhausted to Fish</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">You need to sleep before you can fish</div> </div> <<elseif !_hasRod>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">No Fishing Rod!</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Buy one at the dealership</div> </div> <<elseif _invFull>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🐟</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">Inventory Full</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Sell fish at the dealership</div> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; cursor: pointer; border: 3px solid #27ae60; box-shadow: 0 4px 15px rgba(39, 174, 96, 0.5);'><div style='font-size: 40px; margin-bottom: 8px;'>🎣</div><div style='color: white; font-size: 20px; font-weight: bold;'>Cast Line</div></div>">> <<set $fishingLocation = "pond">> <<goto "FishingQTE">> <</link>> <</if>> </div> <!-- Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>📖 Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #2ecc71; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #2ecc7144; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "SeabassPark">><</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _pole = setup.fishing.getCurrentPole()>> <<set _poleTier = $fishingPole || 0>> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invFull = setup.fishing.isInventoryFull()>> <<set _themeColor = "#00bcd4">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #00bcd4; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #00bcd444; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "CoralReef">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _themeColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _themeColor>>44; margin-bottom: 20px;"> <h2 style="color: <<print _themeColor>>; margin: 0 0 10px 0; text-align: center;">🐠 Coral Reef Fishing</h2> <p style="color: #aaa; margin: 0; font-size: 14px; text-align: center;">Crystal clear waters teeming with colorful tropical fish. A diver's paradise.</p> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 15px;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;">Lv <<print _level>></div> <div style="color: #888; font-size: 11px;">Skill</div> <div style="background: #333; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #3498db, #2ecc71); height: 100%; width: <<print _xpProgress.percent>>%;"></div> </div> </div> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> <div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #888; font-size: 11px;">Collection</div> </div> </div> </div> </div> <!-- Equipment Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: <<if _poleTier === 4>>#e040fb<<elseif _poleTier === 3>>#ffd700<<elseif _poleTier === 2>>#3498db<<elseif _poleTier === 1>>#aaa<<else>>#e74c3c<</if>>; font-size: 16px; font-weight: bold;">🎣 <<if _hasRod>><<print _pole.name>><<else>>No Rod<</if>></div> <<if _hasRod>> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 11px;">Max: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity.toUpperCase()>></span></div> <<if _poleTier === 4>><div style="color: #51cf66; font-size: 10px; margin-top: 3px;">No Trash • Treasure Bonus</div><</if>> <<else>> <div style="color: #e74c3c; font-size: 11px;">Buy at dealership</div> <</if>> </div> </div> <!-- Cast Line Button --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px #2ecc7144; margin-bottom: 20px; text-align: center;"> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #ff6b6b;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #ff6b6b; font-size: 20px; font-weight: bold;">Too Exhausted to Fish</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">You need to sleep before you can fish</div> </div> <<elseif !_hasRod>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">No Fishing Rod!</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Buy one at the dealership</div> </div> <<elseif _invFull>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🐟</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">Inventory Full</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Sell fish at the dealership</div> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; cursor: pointer; border: 3px solid #27ae60; box-shadow: 0 4px 15px rgba(39, 174, 96, 0.5);'><div style='font-size: 40px; margin-bottom: 8px;'>🎣</div><div style='color: white; font-size: 20px; font-weight: bold;'>Cast Line</div></div>">> <<set $fishingLocation = "coralReef">> <<goto "FishingQTE">> <</link>> <</if>> </div> <!-- Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>📖 Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #00bcd4; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #00bcd444; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "CoralReef">><</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _pole = setup.fishing.getCurrentPole()>> <<set _poleTier = $fishingPole || 0>> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invFull = setup.fishing.isInventoryFull()>> <<set _themeColor = "#7c4dff">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #7c4dff; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #7c4dff44; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "UnderWaterCave">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _themeColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _themeColor>>44; margin-bottom: 20px;"> <h2 style="color: <<print _themeColor>>; margin: 0 0 10px 0; text-align: center;">🌊 Underwater Cave Fishing</h2> <p style="color: #aaa; margin: 0; font-size: 14px; text-align: center;">Bioluminescent waters hide mysterious deep-sea creatures. Rare fish lurk in the shadows.</p> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 15px;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;">Lv <<print _level>></div> <div style="color: #888; font-size: 11px;">Skill</div> <div style="background: #333; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #3498db, #2ecc71); height: 100%; width: <<print _xpProgress.percent>>%;"></div> </div> </div> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> <div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #888; font-size: 11px;">Collection</div> </div> </div> </div> </div> <!-- Equipment Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: <<if _poleTier === 4>>#e040fb<<elseif _poleTier === 3>>#ffd700<<elseif _poleTier === 2>>#3498db<<elseif _poleTier === 1>>#aaa<<else>>#e74c3c<</if>>; font-size: 16px; font-weight: bold;">🎣 <<if _hasRod>><<print _pole.name>><<else>>No Rod<</if>></div> <<if _hasRod>> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 11px;">Max: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity.toUpperCase()>></span></div> <<if _poleTier === 4>><div style="color: #51cf66; font-size: 10px; margin-top: 3px;">No Trash • Treasure Bonus</div><</if>> <<else>> <div style="color: #e74c3c; font-size: 11px;">Buy at dealership</div> <</if>> </div> </div> <!-- Cast Line Button --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px #2ecc7144; margin-bottom: 20px; text-align: center;"> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #ff6b6b;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #ff6b6b; font-size: 20px; font-weight: bold;">Too Exhausted to Fish</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">You need to sleep before you can fish</div> </div> <<elseif !_hasRod>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">No Fishing Rod!</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Buy one at the dealership</div> </div> <<elseif _invFull>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🐟</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">Inventory Full</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Sell fish at the dealership</div> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; cursor: pointer; border: 3px solid #27ae60; box-shadow: 0 4px 15px rgba(39, 174, 96, 0.5);'><div style='font-size: 40px; margin-bottom: 8px;'>🎣</div><div style='color: white; font-size: 20px; font-weight: bold;'>Cast Line</div></div>">> <<set $fishingLocation = "underwaterCave">> <<goto "FishingQTE">> <</link>> <</if>> </div> <!-- Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>📖 Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #7c4dff; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #7c4dff44; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "UnderWaterCave">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set _result = setup.fishing.attemptCatch($fishingLocation)>> <<if _result.fishId === "quill">> <!-- Special Quill catch screen --> <<if !$physicalTraits.includes("Quill")>> <<set $physicalTraits.push("Quill")>> <<set $quillCaught = true>> <</if>> <<run setup.fishing.addXp(250)>> <div style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #000; display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 9999;"> <img src="Images/Other/Fish/spr_fish_172_xxx.webp" style="width: 100vw; height: 100vh; object-fit: contain; position: absolute; top: 0; left: 0; image-rendering: pixelated; opacity: 0.8;"> <div style="position: relative; z-index: 10000; text-align: center;"> <h1 style="color: #ff6b9d; font-size: 72px; text-shadow: 0 0 30px #ff6b9d, 0 0 60px #ff6b9d80, 0 0 90px #ff6b9d40; margin: 0; font-family: serif;">Quill</h1> </div> <div style="position: relative; z-index: 10000; margin-top: 40px;"> <<link "<div style='background: rgba(255,107,157,0.3); border: 2px solid #ff6b9d; padding: 15px 40px; border-radius: 10px; color: #ff6b9d; font-weight: bold; font-size: 18px;'>Continue</div>">> <<if $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> </div> </div> <<else>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #3498db;"> <<set _fish = _result.fish>> <<set _color = setup.fishing.rarityColors[_fish.rarity]>> <<set _catchMessage = setup.fishing.getCatchMessage(_fish.rarity)>> <<set _catchQuality = setup.fishing.getCatchQuality(_fish, _result.price, setup.fishing.getLevel())>> <<set _leveledUp = setup.fishing.recordCatch(_result.fishId, _result.price, _result.xp, _result.basePrice)>> <!-- Automaton: Extra fish catches (2x normal, 3x overcharged) --> <<if _result.catchMultiplier && _result.catchMultiplier > 1>> <<for _extraCatch = 1; _extraCatch < _result.catchMultiplier; _extraCatch++>> <<run setup.fishing.recordCatch(_result.fishId, _result.price, _result.xp, _result.basePrice)>> <</for>> <</if>> <!-- Catch Message --> <div style="color: <<print _color>>; font-size: 18px; font-weight: bold; margin-bottom: 15px; text-shadow: 0 0 10px <<print _color>>40;"><<print _catchMessage>></div> <div style="margin-bottom: 20px;"> <<if _fish.icon>> <img @src="_fish.icon" style="width: 96px; height: 96px; image-rendering: pixelated;"> <<else>> <div style="font-size: 80px;">🐟</div> <</if>> </div> <<if _result.isNew>> <div style="background: linear-gradient(135deg, #f39c12 0%, #e74c3c 100%); padding: 10px 20px; border-radius: 20px; display: inline-block; margin-bottom: 15px;"> <span style="color: white; font-weight: bold;">✨ NEW CATCH! ✨</span> </div> <</if>> <h2 style="color: <<print _color>>; margin: 0 0 10px 0; font-size: 28px;"><<print _fish.name>></h2> <div style="color: <<print _color>>; font-size: 14px; text-transform: uppercase; margin-bottom: 15px;"><<print _fish.rarity>></div> <p style="color: #aaa; font-style: italic; margin: 0 0 20px 0;"><<print _catchQuality.text>></p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: #2ecc71; font-size: 24px; font-weight: bold;">+$<<print _result.price>></div> <div style="color: #888; font-size: 12px;">Sold</div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: #3498db; font-size: 24px; font-weight: bold;">+<<print _result.xp>> XP</div> <div style="color: #888; font-size: 12px;">Experience</div> </div> </div> <<if _leveledUp>> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 15px; border-radius: 10px; margin-bottom: 20px;"> <div style="color: white; font-size: 18px; font-weight: bold;">🎉 LEVEL UP! 🎉</div> <div style="color: rgba(255,255,255,0.8);">You are now Fishing Level <<print _leveledUp>>!</div> </div> <</if>> <div style="margin-top: 20px; display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%); padding: 15px 30px; border-radius: 10px; color: white; font-weight: bold;'>🎣 Cast Again</div>">> <<goto "FishingCast">> <</link>> <<link "<div style='background: #555; padding: 15px 30px; border-radius: 10px; color: white; font-weight: bold;'>← Back</div>">> <<if $fishingLocation === "beach">> <<goto "FishingBeach">> <<elseif $fishingLocation === "docks">> <<goto "FishingDocks">> <<elseif $fishingLocation === "pond">> <<goto "FishingPond">> <<elseif $fishingLocation === "coralReef">> <<goto "FishingCoralReef">> <<elseif $fishingLocation === "underwaterCave">> <<goto "FishingUnderwaterCave">> <<elseif $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> </div> </div> </div> <</if>> <</nobr>>
<<nobr>> <<if setup.slime && setup.slime.isActivityBlocked("fish")>><<goto "SlimeBlocked">><</if>> <!-- Check if player can fish --> <<set _canFishCheck = setup.fishing.canFish()>> <<if !_canFishCheck.can>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #e74c3c;"> <<if _canFishCheck.reason === "inventory_full">> <div style="font-size: 60px; margin-bottom: 20px;">🐟📦</div> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">Inventory Full!</h2> <p style="color: #aaa;">You can't carry any more fish. Sell your catch at the dealership first!</p> <<else>> <div style="font-size: 60px; margin-bottom: 20px;">🎣❌</div> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">No Fishing Rod!</h2> <p style="color: #aaa;">You need a fishing rod to fish. Buy one at the dealership!</p> <</if>> <div style="margin-top: 20px;"> <<link "<div style='background: #555; padding: 15px 30px; border-radius: 10px; color: white;'>Back</div>">> <<if $fishingLocation === "beach">> <<goto "FishingBeach">> <<elseif $fishingLocation === "docks">> <<goto "FishingDocks">> <<elseif $fishingLocation === "pond">> <<goto "FishingPond">> <<elseif $fishingLocation === "coralReef">> <<goto "FishingCoralReef">> <<elseif $fishingLocation === "underwaterCave">> <<goto "FishingUnderwaterCave">> <<elseif $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> </div> </div> </div> <<else>> <!-- Fishing takes 30 minutes --> <<set $timeInMinutes += 30>> <<if $debugForceRarity>> <<set _preResult = setup.fishing.getRandomFishOfRarity($debugForceRarity)>> <<set $debugForceRarity = false>> <<else>> <<set _preResult = setup.fishing.attemptCatch($fishingLocation)>> <</if>> <<set $qtePendingFish = _preResult>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 600px; text-align: center; border: 3px solid #3498db;"> <div style="margin-bottom: 15px;"> <div style="font-size: 64px;">❓</div> </div> <h2 style="color: #3498db; margin: 0 0 5px 0;">Something's biting!</h2> <div style="color: #888; font-size: 12px; text-transform: uppercase; margin-bottom: 20px;">Reel it in!</div> <p style="color: #aaa; margin-bottom: 20px;">Click when the marker is in the green zone!</p> <div id="qte-container" style="position: relative; width: 100%; height: 60px; background: #1a1a1a; border-radius: 10px; margin-bottom: 30px; overflow: hidden; border: 2px solid #555;"> <div id="qte-zone" style="position: absolute; height: 100%; background: linear-gradient(90deg, #f1c40f 0%, #2ecc71 50%, #f1c40f 100%); opacity: 0.9;"> <!-- Center line indicator for 100% accuracy --> <div style="position: absolute; left: 50%; transform: translateX(-50%); width: 3px; height: 100%; background: white; box-shadow: 0 0 8px #fff, 0 0 15px #f1c40f;"></div> </div> <div id="qte-marker" style="position: absolute; width: 8px; height: 100%; background: white; box-shadow: 0 0 10px white;"></div> </div> <p style="color: #888; font-size: 12px; margin-top: -20px; margin-bottom: 20px;">Aim for the center line for 100% accuracy!</p> <div id="qte-instructions"> <<link "<div id='catch-btn' style='background: linear-gradient(135deg, #e67e22 0%, #f39c12 100%); padding: 20px 60px; border-radius: 15px; color: white; font-weight: bold; font-size: 24px; cursor: pointer;'>🎣 CATCH!</div>">> <<run window.handleQTECatch()>> <</link>> </div> <div style="margin-top: 20px;"> <<link "<div style='background: #555; padding: 12px 25px; border-radius: 10px; color: white;'>Cancel</div>">> <<script>>window.qteRunning = false;<</script>> <<if $fishingLocation === "beach">> <<goto "FishingBeach">> <<elseif $fishingLocation === "docks">> <<goto "FishingDocks">> <<elseif $fishingLocation === "pond">> <<goto "FishingPond">> <<elseif $fishingLocation === "coralReef">> <<goto "FishingCoralReef">> <<elseif $fishingLocation === "underwaterCave">> <<goto "FishingUnderwaterCave">> <<elseif $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> </div> </div> </div> <<run setup.fishingQTE.startQTE()>> <</if>> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #3498db;"> <<set _hookRescue = $qteHookRescue>><<set $qteHookRescue = false>> <<if $qteSuccess && $qtePendingFish && $qtePendingFish.isTrash>> <<set _result = $qtePendingFish>> <<set _trash = _result.trash>> <<set _finalPrice = _result.price>> <<set _finalXp = _result.xp>> <<set $money = ($money || 0) + _finalPrice>> <<set _leveledUp = setup.fishing.addXp(_finalXp)>> <<if !$fishingStats>><<set $fishingStats = { totalCatches: 0, moneyEarned: 0 }>><</if>> <<set $fishingStats.totalCatches++>> <<set $fishingStats.moneyEarned += _finalPrice>> <div style="margin-bottom: 15px;"> <div style="font-size: 80px;">🗑️</div> </div> <h2 style="color: #888; margin: 0 0 10px 0; font-size: 28px;"><<print _trash.name>></h2> <div style="color: #666; font-size: 14px; text-transform: uppercase; margin-bottom: 15px;">TRASH</div> <p style="color: #aaa; font-style: italic; margin: 0 0 20px 0;"><<print _trash.description>></p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: #666; font-size: 24px; font-weight: bold;">Worthless</div> <div style="color: #666; font-size: 12px;">No Value</div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: #666; font-size: 24px; font-weight: bold;">+1 XP</div> <div style="color: #666; font-size: 12px;">Experience</div> </div> </div> <p style="color: #e67e22; font-size: 12px;">Upgrade your fishing rod to catch less trash!</p> <<elseif $qteSuccess && $qtePendingFish && $qtePendingFish.isTreasure>> <<set _result = $qtePendingFish>> <<set _treasure = _result.treasure>> <<set _treasureRarity = _result.treasureRarity>> <<set _treasureColor = setup.fishing.treasureRarityColors[_treasureRarity] || "#aaaaaa">> <<set _finalXp = _result.xp>> <<set _treasureMoney = _result.price || 0>> <<set _leveledUp = setup.fishing.addXp(_finalXp)>> <<set $money = ($money || 0) + _treasureMoney>> <<if !$fishingStats>><<set $fishingStats = { totalCatches: 0, moneyEarned: 0 }>><</if>> <<set $fishingStats.moneyEarned += _treasureMoney>> <div style="margin-bottom: 15px;"> <<if _treasure.icon>> <img @src="_treasure.icon" style="width: 96px; height: 96px; image-rendering: pixelated;"> <<else>> <div style="font-size: 80px;">📦</div> <</if>> </div> <div style="background: linear-gradient(135deg, <<print _treasureColor>> 0%, <<print _treasureColor>>88 100%); padding: 10px 20px; border-radius: 20px; display: inline-block; margin-bottom: 15px;"> <span style="color: white; font-weight: bold;">🎁 TREASURE! 🎁</span> </div> <h2 style="color: <<print _treasureColor>>; margin: 0 0 10px 0; font-size: 28px;"><<print _treasure.name>></h2> <div style="color: <<print _treasureColor>>; font-size: 14px; text-transform: uppercase; margin-bottom: 15px;"><<print _treasureRarity>> TREASURE</div> <p style="color: #aaa; font-style: italic; margin: 0 0 20px 0;"><<print _treasure.description>></p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: #2ecc71; font-size: 24px; font-weight: bold;">$<<print _treasureMoney.toLocaleString()>></div> <div style="color: #888; font-size: 12px;">Value</div> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: <<print _treasureColor>>; font-size: 24px; font-weight: bold;">+<<print _finalXp>> XP</div> <div style="color: #888; font-size: 12px;">Experience</div> </div> </div> <<if _leveledUp>> <div style="background: linear-gradient(135deg, #f1c40f 0%, #e67e22 100%); padding: 15px; border-radius: 10px; margin-bottom: 15px;"> <div style="color: white; font-size: 18px; font-weight: bold;">🎉 LEVEL UP!</div> <div style="color: white;">You are now Fishing Level <<print _leveledUp>>!</div> </div> <</if>> <p style="color: #f59e0b; font-size: 12px;">Lucky find! Better rods have higher treasure chances.</p> <<elseif $qteSuccess && $qtePendingFish && $qtePendingFish.isScaledTrait>> <!-- Scaled trait catch --> <<if !$physicalTraits.includes("Scaled")>> <<set $physicalTraits.push("Scaled")>> <</if>> <<run setup.fishing.addXp(50)>> <div style="text-align: center; padding: 20px;"> <div style="font-size: 100px; margin-bottom: 20px;">🐟</div> <h1 style="color: #1abc9c; font-size: 48px; text-shadow: 0 0 30px #1abc9c, 0 0 60px #1abc9c80; margin: 0 0 20px 0;">Scaled</h1> <p style="color: #ccc; font-size: 18px; line-height: 1.6; margin: 0 0 15px 0;"> Instead of a fish, you pull up a handful of shimmering scales. They seem alive in your hands, warm and pulsing with an inner light. Before you can react, they crawl up your arm and embed themselves into your skin. </p> <div style="background: rgba(26,188,156,0.15); border: 2px solid #1abc9c; padding: 15px; border-radius: 10px; margin-bottom: 30px;"> <div style="color: #1abc9c; font-weight: bold; font-size: 18px;">You've gained the Scaled trait!</div> </div> <div style="margin-top: 20px;"> <<link "<div style='background: rgba(26,188,156,0.3); border: 2px solid #1abc9c; padding: 15px 40px; border-radius: 10px; color: #1abc9c; font-weight: bold; font-size: 18px; display: inline-block;'>Continue</div>">> <<goto "FishingOasis">> <</link>> </div> </div> <<elseif $qteSuccess && $qtePendingFish && $qtePendingFish.fish && $qtePendingFish.fishId === "quill">> <!-- Special Quill catch screen --> <<if !$physicalTraits.includes("Quill")>> <<set $physicalTraits.push("Quill")>> <<set $quillCaught = true>> <</if>> <<run setup.fishing.addXp(250)>> </div> </div> <div style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: #000; display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 9999;"> <img src="Images/Other/Fish/spr_fish_172_xxx.webp" style="width: 100vw; height: 100vh; object-fit: contain; position: absolute; top: 0; left: 0; image-rendering: pixelated; opacity: 0.8;"> <div style="position: relative; z-index: 10000; text-align: center;"> <h1 style="color: #ff6b9d; font-size: 72px; text-shadow: 0 0 30px #ff6b9d, 0 0 60px #ff6b9d80, 0 0 90px #ff6b9d40; margin: 0; font-family: serif;">Quill</h1> </div> <div style="position: relative; z-index: 10000; margin-top: 40px;"> <<link "<div style='background: rgba(255,107,157,0.3); border: 2px solid #ff6b9d; padding: 15px 40px; border-radius: 10px; color: #ff6b9d; font-weight: bold; font-size: 18px;'>Continue</div>">> <<if $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> </div> </div> <<elseif $qteSuccess && $qtePendingFish && $qtePendingFish.fish>> <<set _result = $qtePendingFish>> <<set _fish = _result.fish>> <<set _color = setup.fishing.rarityColors[_fish.rarity] || "#aaaaaa">> <<set _catchMessage = setup.fishing.getCatchMessage(_fish.rarity)>> <<set _bonusMultiplier = $qteAccuracyPercent >= 90 ? 1.05 : 1.0>> <<set _finalPrice = Math.floor(_result.price * _bonusMultiplier)>> <<set _finalXp = Math.floor(_result.xp * _bonusMultiplier)>> <<set _catchQuality = setup.fishing.getCatchQuality(_fish, _finalPrice, setup.fishing.getLevel())>> <<if $qteAccuracyPercent !== 100>> <<set _catchQuality.text = _catchQuality.quality === "perfect" ? "An excellent catch!" : _catchQuality.text>> <<set _catchQuality.quality = _catchQuality.quality === "perfect" ? "excellent" : _catchQuality.quality>> <</if>> <<set _finalBasePrice = Math.floor(_result.basePrice * _bonusMultiplier)>> <<set _catchResult = setup.fishing.recordCatch(_result.fishId, _finalPrice, _finalXp, _finalBasePrice)>> <!-- Automaton: Extra fish catches (2x normal, 3x overcharged) --> <<if _result.catchMultiplier && _result.catchMultiplier > 1>> <<for _extraCatch = 1; _extraCatch < _result.catchMultiplier; _extraCatch++>> <<run setup.fishing.recordCatch(_result.fishId, _finalPrice, _finalXp, _finalBasePrice)>> <</for>> <</if>> <<if _hookRescue>> <div style="background: linear-gradient(135deg, #1565c0 0%, #0d3b66 100%); padding: 12px; border-radius: 10px; margin-bottom: 15px; border: 2px solid #4dd0e1; box-shadow: 0 0 15px rgba(77,208,225,0.4);"> <span style="color: #e0f7fa; font-weight: bold;">🪝 The Sunfish Hook saved your catch! 🪝</span> </div> <</if>> <!-- Accuracy Display --> <<set _accuracyColor = $qteAccuracyPercent >= 90 ? "#f1c40f" : $qteAccuracyPercent >= 70 ? "#2ecc71" : $qteAccuracyPercent >= 50 ? "#3498db" : "#e67e22">> <<if $qtePerfect>> <div style="background: linear-gradient(135deg, #f1c40f 0%, #e67e22 100%); padding: 10px 20px; border-radius: 20px; display: inline-block; margin-bottom: 10px;"> <span style="color: white; font-weight: bold;">⭐ PERFECT CATCH! ⭐</span> </div> <</if>> <div style="margin-bottom: 15px;"> <div style="color: <<print _accuracyColor>>; font-size: 32px; font-weight: bold;"><<print $qteAccuracyPercent || 0>>%</div> <div style="color: #888; font-size: 12px;">Accuracy</div> <div style="background: #1a1a1a; border-radius: 10px; height: 8px; width: 200px; margin: 8px auto; overflow: hidden;"> <div style="background: linear-gradient(90deg, #e74c3c 0%, #f39c12 50%, #2ecc71 80%, #f1c40f 100%); height: 100%; width: <<print $qteAccuracyPercent || 0>>%;"></div> </div> </div> <!-- Catch Message --> <div style="color: <<print _color>>; font-size: 18px; font-weight: bold; margin-bottom: 15px; text-shadow: 0 0 10px <<print _color>>40;"><<print _catchMessage>></div> <div style="margin-bottom: 15px;"> <<if _fish.icon>><img @src="_fish.icon" style="width: 96px; height: 96px; image-rendering: pixelated;"><<else>><div style="font-size: 60px;">🐟</div><</if>> </div> <<if _result.isNew>> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 8px 15px; border-radius: 15px; display: inline-block; margin-bottom: 10px;"> <span style="color: white; font-weight: bold; font-size: 14px;">✨ NEW! ✨</span> </div> <</if>> <h2 style="color: <<print _color>>; margin: 0 0 10px 0; font-size: 28px;"><<print _fish.name>></h2> <div style="color: <<print _color>>; font-size: 14px; text-transform: uppercase; margin-bottom: 15px;"><<print _fish.rarity>></div> <p style="color: #aaa; font-style: italic; margin: 0 0 20px 0;"><<print _catchQuality.text>></p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <<if _catchResult.addedToInventory>> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">📦 Stored</div> <div style="color: #888; font-size: 12px;">Added to Inventory</div> <div style="color: #f39c12; font-size: 11px;">Worth ~$<<print _finalPrice>></div> <<else>> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">❌ Full</div> <div style="color: #888; font-size: 12px;">Inventory Full!</div> <div style="color: #e74c3c; font-size: 11px;">Fish was released</div> <</if>> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px;"> <div style="color: #3498db; font-size: 24px; font-weight: bold;">+<<print _finalXp>> XP</div> <div style="color: #888; font-size: 12px;">Experience</div> </div> </div> <!-- Inventory Status --> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invPercent = Math.floor((_invCount / _maxInv) * 100)>> <div style="background: #1a1a1a; padding: 10px; border-radius: 8px; margin-bottom: 15px;"> <div style="color: <<if _invPercent >= 100>>#e74c3c<<elseif _invPercent >= 75>>#e67e22<<elseif _invPercent >= 50>>#f1c40f<<else>>#2ecc71<</if>>; font-size: 12px; font-weight: bold;">Fish Inventory: <<print _invCount>>/<<print _maxInv>></div> <<set _invGradient = _invPercent >= 100 ? 'linear-gradient(90deg, #e67e22 0%, #e74c3c 100%)' : _invPercent >= 75 ? 'linear-gradient(90deg, #f1c40f 0%, #e67e22 100%)' : _invPercent >= 50 ? 'linear-gradient(90deg, #2ecc71 0%, #f1c40f 100%)' : 'linear-gradient(90deg, #27ae60 0%, #2ecc71 100%)'>> <div style="background: #000; border-radius: 4px; height: 8px; margin-top: 5px; overflow: hidden;"> <div @style="'background: ' + _invGradient + '; height: 100%; width: ' + _invPercent + '%;'"></div> </div> </div> <<if _catchResult.leveledUp>> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 15px; border-radius: 10px; margin-bottom: 20px;"> <div style="color: white; font-size: 18px; font-weight: bold;">🎉 LEVEL UP! 🎉</div> <div style="color: rgba(255,255,255,0.8);">You are now Fishing Level <<print _catchResult.leveledUp>>!</div> </div> <</if>> <<elseif !$qteSuccess && $qtePendingFish && $qtePendingFish.fish && ($currentArtifact === "The Sunfish Hook" || ($physicalTraits && $physicalTraits.includes("Naiad"))) && (["epic","legendary","mythical"].indexOf($qtePendingFish.fish.rarity) !== -1) && random(1,100) <= 5>> <<set $qteSuccess = true>><<set $qteHookRescue = true>> <<goto "FishingQTEResult">> <<else>> <div style="font-size: 60px; margin-bottom: 20px;">❌</div> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">Missed!</h2> <p style="color: #aaa;">You clicked outside the green zone. Try again!</p> <</if>> <div style="margin-top: 20px; display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='background: linear-gradient(135deg, #e67e22 0%, #f39c12 100%); padding: 15px 30px; border-radius: 10px; color: white; font-weight: bold;'>⚡ Try Again</div>">> <<goto "FishingQTE">> <</link>> <<link "<div style='background: #555; padding: 15px 30px; border-radius: 10px; color: white; font-weight: bold;'>← Back</div>">> <<if $fishingLocation === "beach">> <<goto "FishingBeach">> <<elseif $fishingLocation === "docks">> <<goto "FishingDocks">> <<elseif $fishingLocation === "pond">> <<goto "FishingPond">> <<elseif $fishingLocation === "coralReef">> <<goto "FishingCoralReef">> <<elseif $fishingLocation === "underwaterCave">> <<goto "FishingUnderwaterCave">> <<elseif $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _fishingStats = $fishingStats || {totalCatches: 0, moneyEarned: 0}>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 100%); min-height: 100vh; padding: 20px;"> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<if $fishingLocation>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #9b59b6; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #9b59b644; display: inline-block;'>← Back to Fishing</div>">> <<if $fishingLocation === "beach">> <<goto "FishingBeach">> <<elseif $fishingLocation === "docks">> <<goto "FishingDocks">> <<elseif $fishingLocation === "pond">> <<goto "FishingPond">> <<elseif $fishingLocation === "coralReef">> <<goto "FishingCoralReef">> <<elseif $fishingLocation === "underwaterCave">> <<goto "FishingUnderwaterCave">> <<elseif $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #9b59b6; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #9b59b644; display: inline-block;'>← Back</div>">> <<goto $lastLocation>> <</link>> <</if>> </div> <div style="background: linear-gradient(135deg, #7d3c98 0%, #9b59b6 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #9b59b6;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">📖 Fish Encyclopedia</h1> <p style="color: #d7bde2; margin: 0; font-size: 16px; text-align: center;">Your collection of caught fish</p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 15px; text-align: center;"> <div> <div style="color: #f39c12; font-size: 28px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #aaa; font-size: 12px;">Species Found</div> <div style="background: #1a1a1a; border-radius: 5px; height: 8px; margin-top: 5px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #f39c12, #e74c3c); height: 100%; width: <<print _stats.percent>>%;"></div> </div> </div> <div> <div style="color: #3498db; font-size: 28px; font-weight: bold;"><<print _fishingStats.totalCatches>></div> <div style="color: #aaa; font-size: 12px;">Total Catches</div> </div> <div> <div style="color: #2ecc71; font-size: 28px; font-weight: bold;">$<<print _fishingStats.moneyEarned>></div> <div style="color: #aaa; font-size: 12px;">Money Earned</div> </div> <div> <div style="color: #9b59b6; font-size: 28px; font-weight: bold;">Lv.<<print setup.fishing.getLevel()>></div> <div style="color: #aaa; font-size: 12px;">Fishing Level</div> </div> </div> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #555;"> <h3 style="color: #ccc; margin: 0 0 15px 0;">Collection by Rarity</h3> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; gap: 15px;"> <div style="text-align: center;"> <div style="color: #aaaaaa; font-size: 18px; font-weight: bold;"><<print _stats.byRarity.common>>/<<print _stats.totalByRarity.common>></div> <div style="color: #aaaaaa; font-size: 12px;">Common</div> </div> <div style="text-align: center;"> <div style="color: #51cf66; font-size: 18px; font-weight: bold;"><<print _stats.byRarity.uncommon>>/<<print _stats.totalByRarity.uncommon>></div> <div style="color: #51cf66; font-size: 12px;">Uncommon</div> </div> <div style="text-align: center;"> <div style="color: #339af0; font-size: 18px; font-weight: bold;"><<print _stats.byRarity.rare>>/<<print _stats.totalByRarity.rare>></div> <div style="color: #339af0; font-size: 12px;">Rare</div> </div> <div style="text-align: center;"> <div style="color: #a855f7; font-size: 18px; font-weight: bold;"><<print _stats.byRarity.epic || 0>>/<<print _stats.totalByRarity.epic || 0>></div> <div style="color: #a855f7; font-size: 12px;">Epic</div> </div> <div style="text-align: center;"> <div style="color: #ffd700; font-size: 18px; font-weight: bold;"><<print _stats.byRarity.legendary>>/<<print _stats.totalByRarity.legendary>></div> <div style="color: #ffd700; font-size: 12px;">Legendary</div> </div> <div style="text-align: center;"> <div style="color: #ff6b9d; font-size: 18px; font-weight: bold;"><<print _stats.byRarity.mythical>>/<<print _stats.totalByRarity.mythical>></div> <div style="color: #ff6b9d; font-size: 12px;">Mythical</div> </div> </div> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #555;"> <h3 style="color: #ccc; margin: 0 0 15px 0;">All Fish</h3> <!-- Sort fish by rarity order, then alphabetically --> <<set _rarityOrder = {common: 0, uncommon: 1, rare: 2, epic: 3, legendary: 4, mythical: 5}>> <<set _sortedFish = []>> <<for _fishId, _fish range setup.fishing.fish>> <<if !_fish.hidden>> <<run _sortedFish.push({id: _fishId, data: _fish})>> <</if>> <</for>> <<run _sortedFish.sort(function(a, b) { var rarityA = _rarityOrder[a.data.rarity] || 0; var rarityB = _rarityOrder[b.data.rarity] || 0; if (rarityA !== rarityB) return rarityA - rarityB; return a.data.name.localeCompare(b.data.name); })>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px;"> <<for _fishEntry range _sortedFish>> <<set _fishId = _fishEntry.id>> <<set _fish = _fishEntry.data>> <<set _caught = $fishCollection && $fishCollection.includes(_fishId)>> <<set _color = setup.fishing.rarityColors[_fish.rarity]>> <<if _caught>> <<set _locNames = setup.fishing.locationDisplayNames>> <<set _locList = []>> <<for _loc range _fish.locations>> <<run _locList.push(_locNames[_loc] || _loc)>> <</for>> <<set _locDisplay = _locList.join(", ")>> <<set _cardHtml = "<div style='background: #1a1a1a; padding: 15px; border-radius: 10px; border: 2px solid " + _color + "; text-align: center; cursor: pointer;'><div style='margin-bottom: 10px;'><img src='" + _fish.icon + "' style='width: 64px; height: 64px; image-rendering: pixelated;'></div><div style='color: " + _color + "; font-weight: bold; font-size: 14px; margin-bottom: 4px;'>" + _fish.name + "</div><div style='color: " + _color + "; font-size: 10px; text-transform: uppercase; margin-bottom: 8px;'>" + _fish.rarity + "</div></div>">> <<capture _fish, _color, _fishId, _locDisplay, _cardHtml>> <<link _cardHtml>> <<popover 'noclick'>> <div style="padding: 25px; text-align: center; background: #1a1a1a; border-radius: 10px; max-width: 400px;"> <div style="margin-bottom: 12px;"> <img @src="_fish.icon" style="width: 96px; height: 96px; image-rendering: pixelated;"> </div> <div style="color: <<print _color>>; font-weight: bold; font-size: 22px; margin-bottom: 4px;"><<print _fish.name>></div> <div style="color: <<print _color>>; font-size: 12px; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 6px;"><<print _fish.rarity>></div> <div style="color: #2ecc71; font-size: 14px; margin-bottom: 18px;"> <<if _fish.basePriceMin !== undefined && _fish.basePriceMax !== undefined>> $<<print _fish.basePriceMin.toLocaleString()>> - $<<print _fish.basePriceMax.toLocaleString()>> <<else>> <<set _minPrice = Math.max(1, Math.floor(_fish.basePrice * 0.7))>> <<set _maxPrice = Math.ceil(_fish.basePrice * 1.3)>> $<<print _minPrice.toLocaleString()>> - $<<print _maxPrice.toLocaleString()>> <</if>> </div> <div style="border-top: 1px solid #333; padding-top: 15px; text-align: left;"> <div style="margin-bottom: 12px;"> <div style="color: #888; font-size: 13px;">Location</div> <div style="color: #3498db; font-size: 16px; font-weight: bold;"><<print _locDisplay>></div> </div> <<if _fish.time>> <div style="margin-bottom: 12px;"> <div style="color: #888; font-size: 13px;">Time</div> <div style="color: #f1c40f; font-size: 16px; font-weight: bold;"><<print _fish.time>></div> </div> <</if>> <<if _fish.weather>> <div style="margin-bottom: 12px;"> <div style="color: #888; font-size: 13px;">Weather</div> <div style="color: #e67e22; font-size: 16px; font-weight: bold;"><<print _fish.weather>></div> </div> <</if>> <<if !_fish.time && !_fish.weather>> <div style="color: #666; font-size: 13px; font-style: italic;">No time or weather requirements</div> <</if>> </div> <div style="margin-top: 15px;"> <<link "<div style='display: inline-block; background: #9b59b6; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Close</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> <</capture>> <<else>> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; border: 2px solid <<print _color>>; opacity: 0.4; text-align: center;"> <div style="margin-bottom: 10px;"> <div style="width: 64px; height: 64px; background: #333; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center; color: #555; font-size: 32px;">?</div> </div> <div style="color: <<print _color>>; font-weight: bold; font-size: 14px; margin-bottom: 4px;">???</div> <div style="color: <<print _color>>; font-size: 10px; text-transform: uppercase; margin-bottom: 8px;"><<print _fish.rarity>></div> <div style="color: #555; font-size: 11px; font-style: italic;">Not discovered</div> </div> <</if>> <</for>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<if $fishingLocation>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #9b59b6; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #9b59b644; display: inline-block;'>← Back to Fishing</div>">> <<if $fishingLocation === "beach">> <<goto "FishingBeach">> <<elseif $fishingLocation === "docks">> <<goto "FishingDocks">> <<elseif $fishingLocation === "pond">> <<goto "FishingPond">> <<elseif $fishingLocation === "coralReef">> <<goto "FishingCoralReef">> <<elseif $fishingLocation === "underwaterCave">> <<goto "FishingUnderwaterCave">> <<elseif $fishingLocation === "oasis">> <<goto "FishingOasis">> <<elseif $fishingLocation === "shallowOcean" || $fishingLocation === "deepOcean" || $fishingLocation === "abyssal">> <<goto "OceanFishing">> <<else>> <<goto "FishingDocks">> <</if>> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #9b59b6; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #9b59b644; display: inline-block;'>← Back</div>">> <<goto $lastLocation>> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<run setup.syncDiscoveredTraits()>> <<if !$discoveredTraits>><<set $discoveredTraits = {physical: [], mental: [], skills: [], voice: []}>><</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<goto $lastLocation>> <</link>> </div> <!-- Header --> <div style="background: linear-gradient(135deg, #9b59b6 0%, #6c3483 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #9b59b6;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Trait Encyclopedia</h1> <p style="color: #d7bde2; margin: 0; font-size: 16px; text-align: center;">Traits you have discovered</p> </div> <!-- Summary Stats --> <<set _bodyCount = ($discoveredTraits.body ? $discoveredTraits.body.length : 0)>> <<set _totalDiscovered = $discoveredTraits.physical.length + $discoveredTraits.mental.length + $discoveredTraits.skills.length + ($discoveredTraits.jobs ? $discoveredTraits.jobs.length : 0) + _bodyCount>> <<set _currentTotal = ($physicalTraits ? $physicalTraits.length : 0) + ($mentalTraits ? $mentalTraits.length : 0) + ($skills ? $skills.length : 0) + ($jobs ? $jobs.length : 0)>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(80px, 1fr)); gap: 15px; text-align: center;"> <div> <div style="color: #f39c12; font-size: 28px; font-weight: bold;"><<print _totalDiscovered>></div> <div style="color: #aaa; font-size: 12px;">Total Discovered</div> </div> <div> <div style="color: #e74c3c; font-size: 28px; font-weight: bold;"><<print $discoveredTraits.physical.length>></div> <div style="color: #aaa; font-size: 12px;">Physical</div> </div> <div> <div style="color: #3498db; font-size: 28px; font-weight: bold;"><<print $discoveredTraits.mental.length>></div> <div style="color: #aaa; font-size: 12px;">Mental</div> </div> <div> <div style="color: #2ecc71; font-size: 28px; font-weight: bold;"><<print $discoveredTraits.skills.length>></div> <div style="color: #aaa; font-size: 12px;">Skills</div> </div> <div> <div style="color: #f1c40f; font-size: 28px; font-weight: bold;"><<print $discoveredTraits.jobs ? $discoveredTraits.jobs.length : 0>></div> <div style="color: #aaa; font-size: 12px;">Jobs</div> </div> <div> <div style="color: #ff69b4; font-size: 28px; font-weight: bold;"><<print _bodyCount>></div> <div style="color: #aaa; font-size: 12px;">Body</div> </div> </div> </div> <!-- PHYSICAL TRAITS SECTION --> <<if $discoveredTraits.physical.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #e74c3c;"> <h3 style="color: #e74c3c; margin: 0 0 15px 0; font-size: 20px;">Physical Traits</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px;"> <<for _trait range $discoveredTraits.physical>> <<if _trait !== "Quill">> <<set _isActive = ($physicalTraits && $physicalTraits.includes(_trait))>> <<set _desc = setup.getTraitDescription(_trait)>> <<set _bonuses = setup.traitBonuses[_trait]>> <<set _val = setup.getTraitValue("physical", _trait)>> <<set _bonusText = "">> <<if _bonuses>> <<set _bonusParts = []>> <<if _bonuses.strength>><<run _bonusParts.push((_bonuses.strength > 0 ? "+" : "") + _bonuses.strength + " STR")>><</if>> <<if _bonuses.charisma>><<run _bonusParts.push((_bonuses.charisma > 0 ? "+" : "") + _bonuses.charisma + " CHA")>><</if>> <<if _bonuses.dexterity>><<run _bonusParts.push((_bonuses.dexterity > 0 ? "+" : "") + _bonuses.dexterity + " DEX")>><</if>> <<if _bonuses.intelligence>><<run _bonusParts.push((_bonuses.intelligence > 0 ? "+" : "") + _bonuses.intelligence + " INT")>><</if>> <<set _bonusText = _bonusParts.join(", ")>> <</if>> <<set _jobEffects = setup.getTraitJobEffects(_trait)>> <<set _hasSunfish = setup.skillTree.hasEffect("eyeOfTheSunfish")>> <<set _popupHtml = "<div style='background: #1e1e1e; padding: 24px; border-radius: 12px; text-align: center; border: 2px solid #e74c3c; min-width: 240px;'>" + "<div style='color: #e74c3c; font-weight: bold; font-size: 20px; margin-bottom: 4px;'>" + _trait + "</div>" + "<div style='color: #666; font-size: 11px; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 14px;'>Physical Trait</div>" + "<div style='border-top: 1px solid #333; margin: 0 -24px 14px; padding: 0;'></div>">> <<if _hasSunfish && _desc && _desc.length > 0>><<set _popupHtml = _popupHtml + "<div style='color: #bbb; font-size: 14px; margin-bottom: 12px; line-height: 1.4;'>" + _desc + "</div>">><</if>> <<if _bonusText.length > 0>><<set _popupHtml = _popupHtml + "<div style='color: #f39c12; font-size: 13px; margin-bottom: 12px; font-weight: bold;'>" + _bonusText + "</div>">><</if>> <<if _hasSunfish && _jobEffects.length > 0>> <<set _popupHtml = _popupHtml + "<div style='border-top: 1px solid #333; margin: 0 -24px 12px; padding: 0;'></div>">> <<set _popupHtml = _popupHtml + "<div style='color: #888; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px; text-align: center;'>Effects</div>">> <<set _popupHtml = _popupHtml + "<div style='text-align: left; margin-bottom: 12px;'>">> <<for _eff range _jobEffects>> <<set _popupHtml = _popupHtml + "<div style='color: #8be; font-size: 12px; margin-bottom: 4px;'>" + _eff + "</div>">> <</for>> <<set _popupHtml = _popupHtml + "</div>">> <</if>> <<set _popupHtml = _popupHtml + "<div style='color: #666; font-size: 12px;'>Value: " + _val + " pts</div>">> <<if _isActive>><<set _popupHtml = _popupHtml + "<div style='color: #2ecc71; font-size: 12px; margin-top: 8px; font-weight: bold;'>Currently Active</div>">><</if>> <<set _popupHtml = _popupHtml + "</div>">> <<set _cardStyle = "background: " + (_isActive ? "linear-gradient(135deg, #2d1a1a 0%, #1a1a1a 100%)" : "#1a1a1a") + "; padding: 15px; border-radius: 10px; text-align: center; border: 2px solid " + (_isActive ? "#e74c3c" : "#444") + "; cursor: pointer;">> <<set _cardHtml = "<div style='" + _cardStyle + "'><span style='color: " + (_isActive ? "#e74c3c" : "#888") + "; font-size: 13px; font-weight: bold;'>" + _trait + "</span></div>">> <<capture _trait, _popupHtml, _cardHtml>> <<link _cardHtml>> <<popover "noclick">> <<print _popupHtml>> <div style="text-align: center; margin-top: 16px;"> <<link "<div style='display: inline-block; background: #e74c3c; color: white; padding: 10px 30px; border-radius: 8px; font-weight: bold; font-size: 14px; cursor: pointer;'>Close</div>">> <<run Dialog.close()>> <</link>> </div> <</popover>> <</link>> <</capture>> <</if>> <</for>> </div> </div> <</if>> <!-- MENTAL TRAITS SECTION --> <<if $discoveredTraits.mental.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #3498db;"> <h3 style="color: #3498db; margin: 0 0 15px 0; font-size: 20px;">Mental Traits</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px;"> <<for _trait range $discoveredTraits.mental>> <<set _isActive = ($mentalTraits && $mentalTraits.includes(_trait))>> <<set _desc = setup.getTraitDescription(_trait)>> <<set _bonuses = setup.traitBonuses[_trait]>> <<set _val = setup.getTraitValue("mental", _trait)>> <<set _bonusText = "">> <<if _bonuses>> <<set _bonusParts = []>> <<if _bonuses.strength>><<run _bonusParts.push((_bonuses.strength > 0 ? "+" : "") + _bonuses.strength + " STR")>><</if>> <<if _bonuses.charisma>><<run _bonusParts.push((_bonuses.charisma > 0 ? "+" : "") + _bonuses.charisma + " CHA")>><</if>> <<if _bonuses.dexterity>><<run _bonusParts.push((_bonuses.dexterity > 0 ? "+" : "") + _bonuses.dexterity + " DEX")>><</if>> <<if _bonuses.intelligence>><<run _bonusParts.push((_bonuses.intelligence > 0 ? "+" : "") + _bonuses.intelligence + " INT")>><</if>> <<set _bonusText = _bonusParts.join(", ")>> <</if>> <<set _hasSunfish = setup.skillTree.hasEffect("eyeOfTheSunfish")>> <<set _popupHtml = "<div style='background: #1e1e1e; padding: 24px; border-radius: 12px; text-align: center; border: 2px solid #3498db; min-width: 240px;'>" + "<div style='color: #3498db; font-weight: bold; font-size: 20px; margin-bottom: 4px;'>" + _trait + "</div>" + "<div style='color: #666; font-size: 11px; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 14px;'>Mental Trait</div>" + "<div style='border-top: 1px solid #333; margin: 0 -24px 14px; padding: 0;'></div>">> <<if _hasSunfish && _desc && _desc.length > 0>><<set _popupHtml = _popupHtml + "<div style='color: #bbb; font-size: 14px; margin-bottom: 12px; line-height: 1.4;'>" + _desc + "</div>">><</if>> <<if _bonusText.length > 0>><<set _popupHtml = _popupHtml + "<div style='color: #f39c12; font-size: 13px; margin-bottom: 12px; font-weight: bold;'>" + _bonusText + "</div>">><</if>> <<set _jobEffects = setup.getTraitJobEffects(_trait)>> <<if _hasSunfish && _jobEffects.length > 0>> <<set _popupHtml = _popupHtml + "<div style='border-top: 1px solid #333; margin: 0 -24px 12px; padding: 0;'></div>">> <<set _popupHtml = _popupHtml + "<div style='color: #888; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px; text-align: center;'>Effects</div>">> <<set _popupHtml = _popupHtml + "<div style='text-align: left; margin-bottom: 12px;'>">> <<for _eff range _jobEffects>> <<set _popupHtml = _popupHtml + "<div style='color: #8be; font-size: 12px; margin-bottom: 4px;'>" + _eff + "</div>">> <</for>> <<set _popupHtml = _popupHtml + "</div>">> <</if>> <<set _popupHtml = _popupHtml + "<div style='color: #666; font-size: 12px;'>Value: " + _val + " pts</div>">> <<if _isActive>><<set _popupHtml = _popupHtml + "<div style='color: #2ecc71; font-size: 12px; margin-top: 8px; font-weight: bold;'>Currently Active</div>">><</if>> <<set _popupHtml = _popupHtml + "</div>">> <<set _cardStyle = "background: " + (_isActive ? "linear-gradient(135deg, #1a1a2d 0%, #1a1a1a 100%)" : "#1a1a1a") + "; padding: 15px; border-radius: 10px; text-align: center; border: 2px solid " + (_isActive ? "#3498db" : "#444") + "; cursor: pointer;">> <<set _cardHtml = "<div style='" + _cardStyle + "'><span style='color: " + (_isActive ? "#3498db" : "#888") + "; font-size: 13px; font-weight: bold;'>" + _trait + "</span></div>">> <<capture _trait, _popupHtml, _cardHtml>> <<link _cardHtml>> <<popover "noclick">> <<print _popupHtml>> <div style="text-align: center; margin-top: 16px;"> <<link "<div style='display: inline-block; background: #3498db; color: white; padding: 10px 30px; border-radius: 8px; font-weight: bold; font-size: 14px; cursor: pointer;'>Close</div>">> <<run Dialog.close()>> <</link>> </div> <</popover>> <</link>> <</capture>> <</for>> </div> </div> <</if>> <!-- SKILLS SECTION --> <<if $discoveredTraits.skills.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #2ecc71;"> <h3 style="color: #2ecc71; margin: 0 0 15px 0; font-size: 20px;">Skills</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px;"> <<for _trait range $discoveredTraits.skills>> <<set _isActive = ($skills && $skills.includes(_trait))>> <<set _desc = setup.getTraitDescription(_trait)>> <<set _bonuses = setup.skillBonuses[_trait]>> <<set _val = setup.getTraitValue("skill", _trait)>> <<set _bonusText = "">> <<if _bonuses>> <<set _bonusParts = []>> <<if _bonuses.strength>><<run _bonusParts.push((_bonuses.strength > 0 ? "+" : "") + _bonuses.strength + " STR")>><</if>> <<if _bonuses.charisma>><<run _bonusParts.push((_bonuses.charisma > 0 ? "+" : "") + _bonuses.charisma + " CHA")>><</if>> <<if _bonuses.dexterity>><<run _bonusParts.push((_bonuses.dexterity > 0 ? "+" : "") + _bonuses.dexterity + " DEX")>><</if>> <<if _bonuses.intelligence>><<run _bonusParts.push((_bonuses.intelligence > 0 ? "+" : "") + _bonuses.intelligence + " INT")>><</if>> <<set _bonusText = _bonusParts.join(", ")>> <</if>> <<set _hasSunfish = setup.skillTree.hasEffect("eyeOfTheSunfish")>> <<set _popupHtml = "<div style='background: #1e1e1e; padding: 24px; border-radius: 12px; text-align: center; border: 2px solid #2ecc71; min-width: 240px;'>" + "<div style='color: #2ecc71; font-weight: bold; font-size: 20px; margin-bottom: 4px;'>" + _trait + "</div>" + "<div style='color: #666; font-size: 11px; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 14px;'>Skill</div>" + "<div style='border-top: 1px solid #333; margin: 0 -24px 14px; padding: 0;'></div>">> <<if _hasSunfish && _desc && _desc.length > 0>><<set _popupHtml = _popupHtml + "<div style='color: #bbb; font-size: 14px; margin-bottom: 12px; line-height: 1.4;'>" + _desc + "</div>">><</if>> <<if _bonusText.length > 0>><<set _popupHtml = _popupHtml + "<div style='color: #f39c12; font-size: 13px; margin-bottom: 12px; font-weight: bold;'>" + _bonusText + "</div>">><</if>> <<set _jobEffects = setup.getTraitJobEffects(_trait)>> <<if _hasSunfish && _jobEffects.length > 0>> <<set _popupHtml = _popupHtml + "<div style='border-top: 1px solid #333; margin: 0 -24px 12px; padding: 0;'></div>">> <<set _popupHtml = _popupHtml + "<div style='color: #888; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px; text-align: center;'>Effects</div>">> <<set _popupHtml = _popupHtml + "<div style='text-align: left; margin-bottom: 12px;'>">> <<for _eff range _jobEffects>> <<set _popupHtml = _popupHtml + "<div style='color: #8be; font-size: 12px; margin-bottom: 4px;'>" + _eff + "</div>">> <</for>> <<set _popupHtml = _popupHtml + "</div>">> <</if>> <<set _popupHtml = _popupHtml + "<div style='color: #666; font-size: 12px;'>Value: " + _val + " pts</div>">> <<if _isActive>><<set _popupHtml = _popupHtml + "<div style='color: #2ecc71; font-size: 12px; margin-top: 8px; font-weight: bold;'>Currently Active</div>">><</if>> <<set _popupHtml = _popupHtml + "</div>">> <<set _cardStyle = "background: " + (_isActive ? "linear-gradient(135deg, #1a2d1a 0%, #1a1a1a 100%)" : "#1a1a1a") + "; padding: 15px; border-radius: 10px; text-align: center; border: 2px solid " + (_isActive ? "#2ecc71" : "#444") + "; cursor: pointer;">> <<set _cardHtml = "<div style='" + _cardStyle + "'><span style='color: " + (_isActive ? "#2ecc71" : "#888") + "; font-size: 13px; font-weight: bold;'>" + _trait + "</span></div>">> <<capture _trait, _popupHtml, _cardHtml>> <<link _cardHtml>> <<popover "noclick">> <<print _popupHtml>> <div style="text-align: center; margin-top: 16px;"> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 10px 30px; border-radius: 8px; font-weight: bold; font-size: 14px; cursor: pointer;'>Close</div>">> <<run Dialog.close()>> <</link>> </div> <</popover>> <</link>> <</capture>> <</for>> </div> </div> <</if>> <!-- BODY PARTS SECTION --> <<if $discoveredTraits.body && $discoveredTraits.body.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #ff69b4;"> <h3 style="color: #ff69b4; margin: 0 0 15px 0; font-size: 20px;">Body</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px;"> <<for _bp range $discoveredTraits.body>> <<set _bpIsActive = false>> <<if $bodyParts>> <<if _bp.label === "Gender" && $bodyParts.gender === _bp.value>><<set _bpIsActive = true>><</if>> <<if _bp.label === "Chest" && $bodyParts.chest === _bp.value>><<set _bpIsActive = true>><</if>> <<if _bp.label === "Butt" && $bodyParts.butt === _bp.value>><<set _bpIsActive = true>><</if>> <<if _bp.label === "Genitals" && $bodyParts.genitals === _bp.value>><<set _bpIsActive = true>><</if>> <</if>> <<set _bpEffects = []>> <<if _bp.label === "Chest">> <<if _bp.value.includes("large") || _bp.value.includes("huge") || _bp.value.includes("gigantic") || _bp.value.includes("giant")>> <<run _bpEffects.push("Stripping: +20-30% tip bonus")>> <<run _bpEffects.push("PrawnHub: Bonus to full strip/freestyle")>> <</if>> <</if>> <<if _bp.label === "Gender" && _bp.value === "female">> <<run _bpEffects.push("Brothel: Required (female only)")>> <</if>> <<if _bp.label === "Genitals" && _bp.value.includes("vagina")>> <<run _bpEffects.push("Stripping Full Strip: +20% tips")>> <</if>> <<set _bpVal = setup.getTraitValue("bodyPart", _bp.label.toLowerCase(), _bp.value)>> <<set _hasSunfish = setup.skillTree.hasEffect("eyeOfTheSunfish")>> <<set _bpPopup = "<div style='background: #1e1e1e; padding: 24px; border-radius: 12px; text-align: center; border: 2px solid #ff69b4; min-width: 240px;'>" + "<div style='color: #ff69b4; font-weight: bold; font-size: 20px; margin-bottom: 4px;'>" + _bp.label + "</div>" + "<div style='color: #666; font-size: 11px; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 14px;'>Body Part</div>" + "<div style='border-top: 1px solid #333; margin: 0 -24px 14px; padding: 0;'></div>" + "<div style='color: #bbb; font-size: 16px; margin-bottom: 12px; font-weight: bold;'>" + _bp.value.charAt(0).toUpperCase() + _bp.value.slice(1) + "</div>">> <<if _hasSunfish && _bpEffects.length > 0>> <<set _bpPopup = _bpPopup + "<div style='border-top: 1px solid #333; margin: 0 -24px 12px; padding: 0;'></div>">> <<set _bpPopup = _bpPopup + "<div style='color: #888; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px; text-align: center;'>Effects</div>">> <<set _bpPopup = _bpPopup + "<div style='text-align: left; margin-bottom: 12px;'>">> <<for _eff range _bpEffects>> <<set _bpPopup = _bpPopup + "<div style='color: #8be; font-size: 12px; margin-bottom: 4px;'>" + _eff + "</div>">> <</for>> <<set _bpPopup = _bpPopup + "</div>">> <</if>> <<set _bpPopup = _bpPopup + "<div style='color: #666; font-size: 12px;'>Value: " + _bpVal + " pts</div>">> <<if _bpIsActive>><<set _bpPopup = _bpPopup + "<div style='color: #2ecc71; font-size: 12px; margin-top: 8px; font-weight: bold;'>Currently Active</div>">><</if>> <<set _bpPopup = _bpPopup + "</div>">> <<set _bpCardStyle = "background: " + (_bpIsActive ? "linear-gradient(135deg, #2d1a2a 0%, #1a1a1a 100%)" : "#1a1a1a") + "; padding: 15px; border-radius: 10px; text-align: center; border: 2px solid " + (_bpIsActive ? "#ff69b4" : "#444") + "; cursor: pointer;">> <<set _bpCard = "<div style='" + _bpCardStyle + "'><span style='color: " + (_bpIsActive ? "#ff69b4" : "#888") + "; font-size: 13px; font-weight: bold;'>" + _bp.label + ": " + _bp.value.charAt(0).toUpperCase() + _bp.value.slice(1) + "</span></div>">> <<capture _bp, _bpPopup, _bpCard>> <<link _bpCard>> <<popover "noclick">> <<print _bpPopup>> <div style="text-align: center; margin-top: 16px;"> <<link "<div style='display: inline-block; background: #ff69b4; color: white; padding: 10px 30px; border-radius: 8px; font-weight: bold; font-size: 14px; cursor: pointer;'>Close</div>">> <<run Dialog.close()>> <</link>> </div> <</popover>> <</link>> <</capture>> <</for>> </div> </div> <</if>> <!-- JOBS SECTION --> <<if $discoveredTraits.jobs && $discoveredTraits.jobs.length > 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #f1c40f;"> <h3 style="color: #f1c40f; margin: 0 0 15px 0; font-size: 20px;">Jobs</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 15px;"> <<for _job range $discoveredTraits.jobs>> <<set _isActive = ($jobs && $jobs.includes(_job))>> <<set _val = setup.getTraitValue("job", _job)>> <<set _jobReqs = setup.jobRequirements[_job]>> <<set _reqParts = []>> <<if _jobReqs>> <<if _jobReqs.strength>><<run _reqParts.push("STR " + _jobReqs.strength)>><</if>> <<if _jobReqs.dexterity>><<run _reqParts.push("DEX " + _jobReqs.dexterity)>><</if>> <<if _jobReqs.charisma>><<run _reqParts.push("CHA " + _jobReqs.charisma)>><</if>> <<if _jobReqs.intelligence>><<run _reqParts.push("INT " + _jobReqs.intelligence)>><</if>> <</if>> <<set _reqText = _reqParts.length > 0 ? _reqParts.join(", ") : "None">> <<set _hasSunfish = setup.skillTree.hasEffect("eyeOfTheSunfish")>> <<set _popupHtml = "<div style='background: #1e1e1e; padding: 24px; border-radius: 12px; text-align: center; border: 2px solid #f1c40f; min-width: 240px;'>" + "<div style='color: #f1c40f; font-weight: bold; font-size: 20px; margin-bottom: 4px;'>" + _job + "</div>" + "<div style='color: #666; font-size: 11px; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 14px;'>Job</div>" + "<div style='border-top: 1px solid #333; margin: 0 -24px 14px; padding: 0;'></div>">> <<if _hasSunfish>><<set _popupHtml = _popupHtml + "<div style='color: #888; font-size: 11px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 8px;'>Requirements</div>" + "<div style='color: #bbb; font-size: 14px; margin-bottom: 12px;'>" + _reqText + "</div>">><</if>> <<set _popupHtml = _popupHtml + "<div style='color: #666; font-size: 12px;'>Value: " + _val + " pts</div>">> <<if _isActive>><<set _popupHtml = _popupHtml + "<div style='color: #2ecc71; font-size: 12px; margin-top: 8px; font-weight: bold;'>Currently Active</div>">><</if>> <<set _popupHtml = _popupHtml + "</div>">> <<set _cardStyle = "background: " + (_isActive ? "linear-gradient(135deg, #2d2a0a 0%, #1a1a1a 100%)" : "#1a1a1a") + "; padding: 15px; border-radius: 10px; text-align: center; border: 2px solid " + (_isActive ? "#f1c40f" : "#444") + "; cursor: pointer;">> <<set _cardHtml = "<div style='" + _cardStyle + "'><span style='color: " + (_isActive ? "#f1c40f" : "#888") + "; font-size: 13px; font-weight: bold;'>" + _job + "</span></div>">> <<capture _job, _popupHtml, _cardHtml>> <<link _cardHtml>> <<popover "noclick">> <<print _popupHtml>> <div style="text-align: center; margin-top: 16px;"> <<link "<div style='display: inline-block; background: #f1c40f; color: #000; padding: 10px 30px; border-radius: 8px; font-weight: bold; font-size: 14px; cursor: pointer;'>Close</div>">> <<run Dialog.close()>> <</link>> </div> <</popover>> <</link>> <</capture>> <</for>> </div> </div> <</if>> <!-- Empty State --> <<if _totalDiscovered === 0>> <div style="background: #2a2a2a; padding: 30px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #555;"> <p style="color: #888; text-align: center; font-style: italic; font-size: 16px;">You haven't discovered any traits yet. Traits will appear here as you acquire them.</p> </div> <</if>> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if $dealershipTab === undefined || $dealershipTab === "boats">><<set $dealershipTab = "upgrades">><</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Leave Dealership</div>">><<goto "Docks">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #3498db; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #3498db; margin: 0 0 15px 0;">⚓ Fishing & Gear Dealership</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;"><<if $boat>><<print setup.fishing.boats[$boat].name>><<else>>None<</if>></div> <div style="color: #888; font-size: 11px;">Boat</div> </div> <div> <div style="color: #e67e22; font-size: 20px; font-weight: bold;"><<print setup.fishing.getCurrentPole().name>></div> <div style="color: #888; font-size: 11px;">Pole</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print setup.fishing.getInventoryCount()>>/<<print setup.fishing.getMaxInventory()>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> </div> </div> </div> <!-- Tab Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #51cf66; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;"> <<link "<div style='background: <<if $dealershipTab === \"upgrades\">>#9b59b6<<else>>linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)<</if>>; border: 2px solid #9b59b6; color: <<if $dealershipTab === \"upgrades\">>#fff<<else>>#888<</if>>; padding: 10px 15px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px; <<if $dealershipTab === \"upgrades\">>box-shadow: 0 0 15px #9b59b688;<</if>>'>🛠️ Items & Upgrades</div>">><<set $dealershipTab = "upgrades">><<goto "FishingDealership">><</link>> <<link "<div style='background: <<if $dealershipTab === \"sell\">>#2ecc71<<else>>linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%)<</if>>; border: 2px solid #2ecc71; color: <<if $dealershipTab === \"sell\">>#fff<<else>>#888<</if>>; padding: 10px 15px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px; <<if $dealershipTab === \"sell\">>box-shadow: 0 0 15px #2ecc7188;<</if>>'>💰 Sell Fish</div>">><<set $dealershipTab = "sell">><<goto "FishingDealership">><</link>> </div> </div> <!-- Tab Content --> <<if $dealershipTab === "upgrades">><<set _tabColor = "#9b59b6">><<elseif $dealershipTab === "sell">><<set _tabColor = "#2ecc71">><<else>><<set _tabColor = "#9b59b6">><</if>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _tabColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _tabColor>>44;"> <!-- ITEMS & UPGRADES TAB --> <<if $dealershipTab === "upgrades">> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">🛠️ Items & Upgrades</h2> <!-- Boats Section --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-bottom: 20px;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🚤 Boats</h3> <div style="display: grid; gap: 15px;"> <<for _tier, _boat range setup.fishing.boats>> <<set _owned = $boat && $boat >= _tier>> <<set _canBuy = !_owned && ($money || 0) >= setup.drifterDiscount(_boat.price)>> <<set _isUpgrade = $boat && $boat < _tier>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid <<if _owned>>#2ecc71<<elseif _tier >= 2>>#555<<elseif _canBuy>>#9b59b6<<else>>#555<</if>>; border-radius: 8px; padding: 15px;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;"> <div style="flex: 1; min-width: 180px;"> <h3 style="color: <<if _owned>>#2ecc71<<elseif _tier >= 2>>#555<<else>>#9b59b6<</if>>; margin: 0 0 5px 0; font-size: 16px;">Tier <<print _tier>>: <<print _boat.name>></h3> <p style="color: #aaa; margin: 0 0 8px 0; font-size: 13px;"><<print _boat.description>></p> <div style="color: #888; font-size: 11px;">Ocean: <<print _boat.oceanAccess.join(", ")>> | Tank: Tier <<print _boat.maxTankTier>></div> </div> <div style="text-align: right;"> <<if _tier >= 2>> <div style="color: #555; font-size: 14px; margin-bottom: 8px;">Coming Soon</div> <div style="background: #333; color: #555; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">🚧 Coming Soon</div> <<elseif _owned>> <div style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 8px;">$<<print setup.drifterDiscount(_boat.price)>></div> <div style="background: #2ecc71; color: white; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Owned</div> <<elseif _canBuy>> <div style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 8px;">$<<print setup.drifterDiscount(_boat.price)>></div> <<capture _tier, _boat>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer; font-size: 13px;'><<if _isUpgrade>>Upgrade<<else>>Purchase<</if>></div>">> <<set $money -= setup.drifterDiscount(_boat.price)>> <<set $boat = _tier>> <<goto "FishingDealership">> <</link>> <</capture>> <<else>> <div style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 8px;">$<<print setup.drifterDiscount(_boat.price)>></div> <div style="background: #333; color: #666; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Need $<<print setup.drifterDiscount(_boat.price)>></div> <</if>> </div> </div> </div> <</for>> </div> </div> <!-- Fish Storage Tanks Section --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-bottom: 20px;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🪣 Fish Storage Tanks</h3> <div style="background-color: #2a2a2a; padding: 10px; border-radius: 8px; border: 1px solid #555; margin-bottom: 15px;"> <p style="color: #aaa; margin: 0; text-align: center; font-size: 13px;">Current Storage: <<if $fishTank>>Tier <<print $fishTank>> Tank (<<print setup.fishing.getMaxInventory()>> fish)<<else>>No Tank (5 fish)<</if>></p> </div> <div style="display: grid; gap: 15px;"> <<for _tier, _tank range setup.fishing.fishTanks>> <<set _owned = $fishTank && $fishTank >= _tier>> <<set _canBuy = !_owned && ($money || 0) >= setup.drifterDiscount(_tank.price)>> <<set _hasBoatReq = _tank.requiredBoat === null || ($boat && $boat >= _tank.requiredBoat)>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid <<if _owned>>#2ecc71<<elseif _canBuy && _hasBoatReq>>#9b59b6<<else>>#555<</if>>; border-radius: 8px; padding: 15px;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;"> <div style="flex: 1; min-width: 180px;"> <h3 style="color: <<if _owned>>#2ecc71<<else>>#9b59b6<</if>>; margin: 0 0 5px 0; font-size: 16px;">Tier <<print _tier>> Storage Tank</h3> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 13px;">Stores up to <<print _tank.capacity>> fish</p> <<if _tank.requiredBoat>> <div style="color: <<if _hasBoatReq>>#888<<else>>#e74c3c<</if>>; font-size: 12px;">Requires Tier <<print _tank.requiredBoat>>+ Boat</div> <</if>> </div> <div style="text-align: right;"> <div style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 8px;">$<<print setup.drifterDiscount(_tank.price)>></div> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Owned</div> <<elseif !_hasBoatReq>> <div style="background: #e74c3c; color: white; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Need Boat</div> <<elseif _canBuy>> <<capture _tier, _tank>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer; font-size: 13px;'>Purchase</div>">> <<set $money -= setup.drifterDiscount(_tank.price)>> <<set $fishTank = _tier>> <<goto "FishingDealership">> <</link>> <</capture>> <<else>> <div style="background: #333; color: #666; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Need $<<print setup.drifterDiscount(_tank.price)>></div> <</if>> </div> </div> </div> <</for>> </div> </div> <!-- Fishing Rods Section --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 20px;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🎣 Fishing Rods</h3> <div style="background-color: #2a2a2a; padding: 10px; border-radius: 8px; border: 1px solid #555; margin-bottom: 15px;"> <p style="color: #aaa; margin: 0; text-align: center; font-size: 13px;">Current Rod: <<if $fishingPole && $fishingPole > 0>><<print setup.fishing.getCurrentPole().name>><<else>><span style="color: #e74c3c;">None</span><</if>></p> </div> <div style="display: grid; gap: 15px;"> <<for _tier, _rod range setup.fishing.fishingPoles>> <<if _rod.isSunfishRod>><<continue>><</if>> <<set $maxRodTier = Math.max($maxRodTier || 0, Math.min($fishingPole || 0, 3))>> <<set _currentPole = $maxRodTier>> <<set _owned = _currentPole >= _tier>> <<set _canBuy = !_owned && ($money || 0) >= setup.drifterDiscount(_rod.price)>> <<set _isNext = !_owned && (_tier === 1 || _currentPole >= (_tier - 1))>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid <<if _owned>>#2ecc71<<elseif _canBuy && _isNext>>#9b59b6<<else>>#555<</if>>; border-radius: 8px; padding: 15px;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;"> <div style="flex: 1; min-width: 180px;"> <h3 style="color: <<if _owned>>#2ecc71<<else>>#9b59b6<</if>>; margin: 0 0 5px 0; font-size: 16px;"><<print _rod.name>></h3> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 13px;"><<print _rod.description>></p> <div style="color: #888; font-size: 12px;">Tier <<print _tier>> Rod</div> </div> <div style="text-align: right;"> <div style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 8px;">$<<print setup.drifterDiscount(_rod.price).toLocaleString()>></div> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Owned</div> <<elseif !_isNext>> <div style="background: #333; color: #666; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Locked</div> <<elseif _canBuy>> <<capture _tier, _rod>> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer; font-size: 13px;'>Purchase</div>">> <<set $money -= setup.drifterDiscount(_rod.price)>> <<set $maxRodTier = Math.max($maxRodTier || 0, _tier)>> <<set $fishingPole = _tier>> <<goto "FishingDealership">> <</link>> <</capture>> <<else>> <div style="background: #333; color: #666; padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 13px;">Need $<<print setup.drifterDiscount(_rod.price).toLocaleString()>></div> <</if>> </div> </div> </div> <</for>> </div> </div> <<elseif $dealershipTab === "sell">> <!-- SELL TAB --> <h2 style="color: #2ecc71; margin: 0 0 15px 0;">💰 Sell Your Fish</h2> <!-- Show last sale result if available --> <<if $lastFishSale>> <<if $lastFishSale.count > 0>> <div style="background: linear-gradient(135deg, #1a472a 0%, #0d2818 100%); padding: 20px; border-radius: 10px; border: 2px solid #2ecc71; margin-bottom: 20px; text-align: center;"> <div style="font-size: 36px; margin-bottom: 10px;">💰</div> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">Sold <<print $lastFishSale.count>> Fish!</h3> <div style="color: #2ecc71; font-size: 28px; font-weight: bold;">+$<<print $lastFishSale.money>></div> <!-- Show trait bonuses --> <div style="margin-top: 15px; display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<if $lastFishSale.hasPearl>> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 10px 15px; border-radius: 8px;"> <span style="color: white;">🐚 Pearl of Abundance: +$<<print $lastFishSale.pearlBonus>></span> </div> <</if>> <<if $lastFishSale.hasFishingTrait>> <div style="background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); padding: 10px 15px; border-radius: 8px;"> <span style="color: white;">🎣 Fishing Trait: +$<<print $lastFishSale.fishingTraitBonus>> (+20%)</span> </div> <</if>> <<if $lastFishSale.hasWerefox>> <div style="background: linear-gradient(135deg, #e67e22 0%, #d35400 100%); padding: 10px 15px; border-radius: 8px;"> <span style="color: white;">Werefox: +$<<print $lastFishSale.werefoxBonus>> (+10%)</span> </div> <</if>> <<if $lastFishSale.hasSiren>> <div style="background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); padding: 10px 15px; border-radius: 8px;"> <span style="color: white;">Siren: +$<<print $lastFishSale.sirenBonus>> (2x)</span> </div> <</if>> </div> </div> <</if>> <<unset $lastFishSale>> <</if>> <<if $fishInventory && $fishInventory.length > 0>> <<set _level = setup.fishing.getLevel()>> <<set _priceBonus = 1 + (_level * 0.05)>> <<set _totalValue = 0>> <<for _fish range $fishInventory>> <<set _totalValue += Math.floor(_fish.basePrice * _priceBonus)>> <</for>> <<set _hasPearl = ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <<set _pearlBonus = _hasPearl ? Math.floor(_totalValue * 0.5) : 0>> <!-- Check for trait bonuses --> <<set _hasFishingTrait = $mentalTraits && ($mentalTraits.includes("Fishing") || $mentalTraits.includes("Advanced Angler") || $mentalTraits.includes("Master Angler") || $mentalTraits.includes("Fishimon Master"))>> <<set _hasWerefox = $physicalTraits && $physicalTraits.includes("Werefox")>> <<set _hasSiren = $physicalTraits && $physicalTraits.includes("Siren")>> <<set _fishingTraitBonus = _hasFishingTrait ? Math.floor(_totalValue * 0.2) : 0>> <<set _werefoxBonus = _hasWerefox ? Math.floor(_totalValue * 0.1) : 0>> <<set _sirenBonus = _hasSiren ? _totalValue : 0>> <<set _finalTotal = _totalValue + _pearlBonus + _fishingTraitBonus + _werefoxBonus + _sirenBonus>> <!-- Active Bonuses Display --> <<if _hasPearl || _hasFishingTrait || _hasWerefox || _hasSiren>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #9b59b6; margin-bottom: 15px;"> <h4 style="color: #9b59b6; margin: 0 0 10px 0; text-align: center;">✨ Active Sale Bonuses</h4> <div style="display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;"> <<if _hasPearl>> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 8px 12px; border-radius: 6px;"> <span style="color: white; font-size: 13px;">🐚 Pearl: +50% (+$<<print _pearlBonus>>)</span> </div> <</if>> <<if _hasFishingTrait>> <div style="background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); padding: 8px 12px; border-radius: 6px;"> <span style="color: white; font-size: 13px;">🎣 Fishing: +20% (+$<<print _fishingTraitBonus>>)</span> </div> <</if>> <<if _hasWerefox>> <div style="background: linear-gradient(135deg, #e67e22 0%, #d35400 100%); padding: 8px 12px; border-radius: 6px;"> <span style="color: white; font-size: 13px;">Werefox: +10% (+$<<print _werefoxBonus>>)</span> </div> <</if>> <<if _hasSiren>> <div style="background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); padding: 8px 12px; border-radius: 6px;"> <span style="color: white; font-size: 13px;">Siren: 2x Value (+$<<print _sirenBonus>>)</span> </div> <</if>> </div> </div> <</if>> <!-- Sell All Button --> <div style="background-color: #1a1a1a; padding: 20px; border-radius: 8px; border: 1px solid #2ecc71; margin-bottom: 20px; text-align: center;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">Sell All Fish</h3> <p style="color: #aaa; margin: 0 0 5px 0;">Total Value: <span style="color: #2ecc71; font-weight: bold; font-size: 24px;">$<<print _finalTotal>></span></p> <<if _hasPearl || _hasFishingTrait || _hasWerefox || _hasSiren>> <p style="color: #888; margin: 0 0 15px 0; font-size: 12px;">(Base: $<<print _totalValue>> + bonuses)</p> <</if>> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 18px; cursor: pointer;'>Sell All (<<print $fishInventory.length>> fish)</div>">> <<set $lastFishSale = setup.fishing.sellAllFish()>> <<goto "FishingDealership">> <</link>> </div> <!-- Individual Fish --> <h3 style="color: #2ecc71; margin: 0 0 15px 0;">Your Fish</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 15px;"> <<for _i, _fish range $fishInventory>> <<set _fishBasePrice = Math.floor(_fish.basePrice * _priceBonus)>> <<set _fishPearlBonus = _hasPearl ? Math.floor(_fishBasePrice * 0.5) : 0>> <<set _fishPrice = _fishBasePrice + _fishPearlBonus>> <<set _color = setup.fishing.rarityColors[_fish.rarity] || "#aaaaaa">> <<capture _i, _fish, _fishPrice, _color>> <div style="border: 2px solid <<print _color>>; border-radius: 10px; padding: 15px; background: #1a1a1a; text-align: center;"> <div style="margin-bottom: 10px;"> <<if _fish.icon>> <img @src="_fish.icon" style="width: 48px; height: 48px; image-rendering: pixelated;"> <<else>> <div style="font-size: 36px;">🐟</div> <</if>> </div> <div style="color: <<print _color>>; font-weight: bold; font-size: 14px; margin-bottom: 4px;"><<print _fish.name>></div> <div style="color: <<print _color>>; font-size: 10px; text-transform: uppercase; margin-bottom: 8px;"><<print _fish.rarity>></div> <div style="color: #2ecc71; font-weight: bold; margin-bottom: 10px;">$<<print _fishPrice>></div> <<link "<div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; font-size: 12px; font-weight: bold;'>Sell</div>">> <<set $lastFishSale = setup.fishing.sellFish(_i)>> <<goto "FishingDealership">> <</link>> </div> <</capture>> <</for>> </div> <<else>> <div style="background-color: #1a1a1a; padding: 40px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="font-size: 48px; margin-bottom: 15px;">🎣</div> <h3 style="color: #888; margin: 0 0 10px 0;">No Fish to Sell</h3> <p style="color: #666; margin: 0;">Go catch some fish first!</p> </div> <</if>> <</if>> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #3498db; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #3498db44; display: inline-block;'>← Leave Dealership</div>">><<goto "Docks">><</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #3498db 0%, #2874a6 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Boat Sales</h1> <p style="color: #aed6f1; margin: 0; font-size: 16px; text-align: center;">Your Money: $<<print $money || 0>> | Current Boat: <<if $boat>><<print setup.fishing.boats[$boat].name>><<else>>None<</if>></p> </div> <div style="display: grid; gap: 20px; margin-bottom: 25px;"> <<for _tier, _boat range setup.fishing.boats>> <<set _owned = $boat && $boat >= _tier>> <<set _canBuy = !_owned && ($money || 0) >= _boat.price>> <<set _isUpgrade = $boat && $boat < _tier>> <div style="border: 3px solid <<if _owned>>#2ecc71<<elseif _canBuy>>#3498db<<else>>#555<</if>>; border-radius: 12px; padding: 20px; background: #2a2a2a;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div style="flex: 1; min-width: 200px;"> <h3 style="color: <<if _owned>>#2ecc71<<else>>#3498db<</if>>; margin: 0 0 8px 0;">Tier <<print _tier>>: <<print _boat.name>></h3> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;"><<print _boat.description>></p> <div style="color: #888; font-size: 12px;"> Ocean Access: <<print _boat.oceanAccess.join(", ")>><br> Max Tank Tier: <<print _boat.maxTankTier>> </div> </div> <div style="text-align: right;"> <div style="color: #2ecc71; font-size: 24px; font-weight: bold; margin-bottom: 10px;">$<<print _boat.price>></div> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Owned</div> <<elseif _canBuy>> <<capture _tier, _boat>> <<link "<div style='background: #3498db; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold; cursor: pointer;'><<if _isUpgrade>>Upgrade<<else>>Purchase<</if>></div>">> <<set $money -= _boat.price>> <<set $boat = _tier>> <<goto "DealershipBoats">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #666; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Not Enough Money</div> <</if>> </div> </div> </div> <</for>> </div> <div style="text-align: center;"> <<link "<div style='background: #555; padding: 15px 40px; border-radius: 10px; display: inline-block; color: white; font-weight: bold;'>← Back to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Boat Upgrades</h1> <p style="color: #d7bde2; margin: 0; font-size: 16px; text-align: center;">Your Money: $<<print $money || 0>> | Boat: <<print setup.fishing.boats[$boat].name>></p> </div> <!-- Installed Upgrades --> <<if $boatUpgrades && $boatUpgrades.length > 0>> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #2ecc71;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">Installed Upgrades</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _upgradeId range $boatUpgrades>> <<set _upgrade = setup.fishing.boatUpgrades[_upgradeId]>> <<if _upgrade>> <div style="background: #1a1a1a; padding: 8px 15px; border-radius: 6px; border: 1px solid #2ecc71;"> <span style="color: #2ecc71;"><<print _upgrade.name>></span> </div> <</if>> <</for>> </div> </div> <</if>> <!-- Available Upgrades --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _upgradeId, _upgrade range setup.fishing.boatUpgrades>> <<set _owned = $boatUpgrades && $boatUpgrades.includes(_upgradeId)>> <<set _canBuy = !_owned && ($money || 0) >= _upgrade.price>> <div style="border: 3px solid <<if _owned>>#2ecc71<<elseif _canBuy>>#9b59b6<<else>>#555<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h4 style="color: <<if _owned>>#2ecc71<<else>>#9b59b6<</if>>; margin: 0 0 8px 0;"><<print _upgrade.name>></h4> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;"><<print _upgrade.description>></p> <div style="display: flex; justify-content: space-between; align-items: center;"> <div style="color: #2ecc71; font-weight: bold;">$<<print _upgrade.price>></div> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 8px 15px; border-radius: 6px; font-size: 12px; font-weight: bold;">Installed</div> <<elseif _canBuy>> <<capture _upgradeId, _upgrade>> <<link "<div style='background: #9b59b6; color: white; padding: 8px 15px; border-radius: 6px; font-size: 12px; font-weight: bold; cursor: pointer;'>Install</div>">> <<set $money -= _upgrade.price>> <<if !$boatUpgrades>><<set $boatUpgrades = []>><</if>> <<run $boatUpgrades.push(_upgradeId)>> <<goto "DealershipUpgrades">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #666; padding: 8px 15px; border-radius: 6px; font-size: 12px; font-weight: bold;">Need $<<print _upgrade.price>></div> <</if>> </div> </div> <</for>> </div> <div style="text-align: center;"> <<link "<div style='background: #555; padding: 15px 40px; border-radius: 10px; display: inline-block; color: white; font-weight: bold;'>← Back to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Fishing Tackle</h1> <p style="color: #a9dfbf; margin: 0; font-size: 16px; text-align: center;">Your Money: $<<print $money || 0>></p> </div> <!-- Current Tackle Status --> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #2ecc71;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">Your Current Tackle</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; text-align: center;"> <div style="background: #1a1a1a; padding: 10px; border-radius: 8px;"> <div style="color: #888; font-size: 11px;">Hook</div> <div style="color: #3498db; font-weight: bold;"><<if $tackle && $tackle.hook>><<print setup.fishing.hookTypes[$tackle.hook].name>><<else>>None<</if>></div> </div> <div style="background: #1a1a1a; padding: 10px; border-radius: 8px;"> <div style="color: #888; font-size: 11px;">Line</div> <div style="color: #9b59b6; font-weight: bold;"><<if $tackle && $tackle.line>><<print setup.fishing.lineTypes[$tackle.line].name>><<else>>None<</if>></div> </div> </div> </div> <!-- Hooks Section --> <h3 style="color: #3498db;">Hooks</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _hookId, _hook range setup.fishing.hookTypes>> <<set _owned = $tackle && $tackle.hook === _hookId>> <<set _canBuy = !_owned && ($money || 0) >= _hook.price>> <div style="border: 2px solid <<if _owned>>#2ecc71<<elseif _canBuy>>#3498db<<else>>#555<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h4 style="color: #3498db; margin: 0 0 10px 0;"><<print _hook.name>></h4> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #2ecc71; font-weight: bold;">$<<print _hook.price>></span> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: bold;">Equipped</div> <<elseif _canBuy>> <<capture _hookId, _hook>> <<link "<div style='background: #3498db; color: white; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: bold;'>Buy</div>">> <<set $money -= _hook.price>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set $tackle.hook = _hookId>> <<goto "DealershipTackle">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #666; padding: 6px 12px; border-radius: 6px; font-size: 12px;">Need $<<print _hook.price>></div> <</if>> </div> </div> <</for>> </div> <!-- Lines Section --> <h3 style="color: #9b59b6;">Fishing Line</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _lineId, _line range setup.fishing.lineTypes>> <<set _owned = $tackle && $tackle.line === _lineId>> <<set _canBuy = !_owned && ($money || 0) >= _line.price>> <div style="border: 2px solid <<if _owned>>#2ecc71<<elseif _canBuy>>#9b59b6<<else>>#555<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h4 style="color: #9b59b6; margin: 0 0 10px 0;"><<print _line.name>></h4> <div style="display: flex; justify-content: space-between; align-items: center;"> <span style="color: #2ecc71; font-weight: bold;">$<<print _line.price>></span> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: bold;">Equipped</div> <<elseif _canBuy>> <<capture _lineId, _line>> <<link "<div style='background: #9b59b6; color: white; padding: 6px 12px; border-radius: 6px; font-size: 12px; font-weight: bold;'>Buy</div>">> <<set $money -= _line.price>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set $tackle.line = _lineId>> <<goto "DealershipTackle">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #666; padding: 6px 12px; border-radius: 6px; font-size: 12px;">Need $<<print _line.price>></div> <</if>> </div> </div> <</for>> </div> <div style="text-align: center;"> <<link "<div style='background: #555; padding: 15px 40px; border-radius: 10px; display: inline-block; color: white; font-weight: bold;'>← Back to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #f39c12;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Fish Storage Tanks</h1> <p style="color: #fdebd0; margin: 0; font-size: 16px; text-align: center;">Your Money: $<<print $money || 0>> | Current Capacity: <<print setup.fishing.getMaxInventory()>> fish</p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #f39c12;"> <p style="color: #aaa; margin: 0; text-align: center;">Without a tank, you can only hold 5 fish. Upgrade to store more!</p> </div> <div style="display: grid; gap: 20px; margin-bottom: 25px;"> <<for _tier, _tank range setup.fishing.fishTanks>> <<set _owned = $fishTank && $fishTank >= _tier>> <<set _canBuy = !_owned && ($money || 0) >= _tank.price>> <<set _hasBoatReq = _tank.requiredBoat === null || ($boat && $boat >= _tank.requiredBoat)>> <div style="border: 3px solid <<if _owned>>#2ecc71<<elseif _canBuy && _hasBoatReq>>#f39c12<<else>>#555<</if>>; border-radius: 12px; padding: 20px; background: #2a2a2a;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div style="flex: 1; min-width: 200px;"> <h3 style="color: <<if _owned>>#2ecc71<<else>>#f39c12<</if>>; margin: 0 0 8px 0;">Tier <<print _tier>> Storage Tank</h3> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;">Stores up to <<print _tank.capacity>> fish</p> <<if _tank.requiredBoat>> <p style="color: <<if _hasBoatReq>>#888<<else>>#e74c3c<</if>>; margin: 0; font-size: 12px;">Requires Tier <<print _tank.requiredBoat>>+ Boat</p> <</if>> </div> <div style="text-align: right;"> <div style="color: #2ecc71; font-size: 24px; font-weight: bold; margin-bottom: 10px;">$<<print _tank.price>></div> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Owned</div> <<elseif !_hasBoatReq>> <div style="background: #e74c3c; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Need Boat</div> <<elseif _canBuy>> <<capture _tier, _tank>> <<link "<div style='background: #f39c12; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold; cursor: pointer;'>Purchase</div>">> <<set $money -= _tank.price>> <<set $fishTank = _tier>> <<goto "DealershipTanks">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #666; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Not Enough Money</div> <</if>> </div> </div> </div> <</for>> </div> <div style="text-align: center;"> <<link "<div style='background: #555; padding: 15px 40px; border-radius: 10px; display: inline-block; color: white; font-weight: bold;'>← Back to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #e67e22 0%, #d35400 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #e67e22;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Fishing Poles</h1> <p style="color: #fdebd0; margin: 0; font-size: 16px; text-align: center;">Your Money: $<<print $money || 0>> | Current: <<print setup.fishing.getCurrentPole().name>></p> </div> <div style="display: grid; gap: 20px; margin-bottom: 25px;"> <<for _tier, _pole range setup.fishing.fishingPoles>> <<set $maxRodTier = Math.max($maxRodTier || 0, Math.min($fishingPole || 0, 3))>> <<set _owned = ($maxRodTier || 0) >= _tier>> <<set _canBuy = !_owned && ($money || 0) >= _pole.price && _pole.price > 0>> <div style="border: 3px solid <<if _owned>>#2ecc71<<elseif _canBuy>>#e67e22<<else>>#555<</if>>; border-radius: 12px; padding: 20px; background: #2a2a2a;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div style="flex: 1; min-width: 200px;"> <h3 style="color: <<if _owned>>#2ecc71<<else>>#e67e22<</if>>; margin: 0 0 8px 0;">Tier <<print _tier>>: <<print _pole.name>></h3> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;"><<print _pole.description>></p> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 12px;"> Max Rarity: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity>></span> </div> </div> <div style="text-align: right;"> <<if _pole.price > 0>> <div style="color: #2ecc71; font-size: 24px; font-weight: bold; margin-bottom: 10px;">$<<print _pole.price>></div> <<else>> <div style="color: #888; font-size: 18px; margin-bottom: 10px;">Starter Rod</div> <</if>> <<if _owned>> <div style="background: #2ecc71; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Owned</div> <<elseif _canBuy>> <<capture _tier, _pole>> <<link "<div style='background: #e67e22; color: white; padding: 10px 20px; border-radius: 6px; font-weight: bold; cursor: pointer;'>Purchase</div>">> <<set $money -= _pole.price>> <<set $maxRodTier = Math.max($maxRodTier || 0, _tier)>> <<set $fishingPole = _tier>> <<goto "DealershipPoles">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #666; padding: 10px 20px; border-radius: 6px; font-weight: bold;">Not Enough Money</div> <</if>> </div> </div> </div> <</for>> </div> <div style="text-align: center;"> <<link "<div style='background: #555; padding: 15px 40px; border-radius: 10px; display: inline-block; color: white; font-weight: bold;'>← Back to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<goto "FishingDealership">> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _boat = setup.fishing.getCurrentBoat()>> <!-- Check if player is exhausted --> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #ff6b6b;"> <div style="font-size: 64px; margin-bottom: 20px;">🎣</div> <h2 style="color: #ff6b6b; margin: 0 0 15px 0;">Too Exhausted to Fish</h2> <p style="color: #aaa; margin: 0 0 20px 0;">You need to sleep before you can go ocean fishing. Get some rest!</p> <<link "<div style='background: #3498db; color: white; padding: 15px 30px; border-radius: 10px; font-weight: bold;'>Go to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <!-- Check if player has a fishing rod --> <<elseif !_hasRod>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #e74c3c;"> <div style="font-size: 64px; margin-bottom: 20px;">🎣</div> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">No Fishing Rod!</h2> <p style="color: #aaa; margin: 0 0 20px 0;">You need a fishing rod before you can go ocean fishing. Visit the Fishing Dealership to purchase one.</p> <<link "<div style='background: #3498db; color: white; padding: 15px 30px; border-radius: 10px; font-weight: bold;'>Go to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <!-- Check if player has a boat --> <<elseif !$boat>> <div style="background: linear-gradient(180deg, #1a3a5c 0%, #0d1f33 100%); min-height: 100vh; padding: 20px; display: flex; flex-direction: column; justify-content: center; align-items: center;"> <div style="background: #2a2a2a; padding: 40px; border-radius: 20px; max-width: 500px; text-align: center; border: 3px solid #e74c3c;"> <div style="font-size: 64px; margin-bottom: 20px;">⛵</div> <h2 style="color: #e74c3c; margin: 0 0 15px 0;">No Boat!</h2> <p style="color: #aaa; margin: 0 0 20px 0;">You need a boat to go ocean fishing. Visit the Fishing Dealership to purchase one.</p> <<link "<div style='background: #3498db; color: white; padding: 15px 30px; border-radius: 10px; font-weight: bold;'>Go to Dealership</div>">> <<goto "FishingDealership">> <</link>> </div> </div> <<else>> <div style="background: linear-gradient(180deg, #0a2a4a 0%, #051525 50%, #000510 100%); min-height: 100vh; padding: 20px;"> <div style="background: linear-gradient(135deg, #0a3d62 0%, #1a5276 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4); border: 2px solid #3498db;"> <h1 style="color: white; margin: 0 0 8px 0; font-size: 32px; text-align: center;">Ocean Fishing</h1> <p style="color: #aed6f1; margin: 0; font-size: 16px; text-align: center;">Deep waters hold legendary creatures. Be careful out there!</p> </div> <!-- Boat Status --> <div style="background: #2a2a2a; padding: 15px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #3498db;"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 15px; text-align: center;"> <div> <div style="color: #3498db; font-size: 18px; font-weight: bold;"><<print _boat.name>></div> <div style="color: #aaa; font-size: 12px;">Your Boat</div> </div> <div> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invPercent = Math.round((_invCount / _maxInv) * 100)>> <div style="color: <<if _invPercent >= 100>>#e74c3c<<elseif _invPercent >= 75>>#f39c12<<else>>#2ecc71<</if>>; font-size: 18px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #aaa; font-size: 12px;">Fish Inventory</div> <div style="background: #1a1a1a; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: <<if _invPercent >= 100>>#e74c3c<<elseif _invPercent >= 75>>#f39c12<<else>>#2ecc71<</if>>; height: 100%; width: <<print _invPercent>>%;"></div> </div> </div> <div> <div style="color: #3498db; font-size: 18px; font-weight: bold;">Level <<print _level>></div> <div style="color: #aaa; font-size: 12px;">Fishing Skill</div> </div> </div> </div> <!-- Ocean Zones --> <h3 style="color: #3498db;">Choose Fishing Zone</h3> <div style="display: grid; gap: 15px; margin-bottom: 25px;"> <!-- Shallow Ocean --> <<set _canAccessShallow = setup.fishing.canAccessZone("shallowOcean")>> <div style="border: 3px solid <<if _canAccessShallow>>#3498db<<else>>#555<</if>>; border-radius: 12px; padding: 20px; background: #2a2a2a;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div> <h3 style="color: #3498db; margin: 0 0 8px 0;">Shallow Ocean</h3> <p style="color: #aaa; margin: 0; font-size: 14px;">Near-shore waters. Common to Rare fish. Safest zone.</p> </div> <<if _canAccessShallow>> <<link "<div style='background: #3498db; color: white; padding: 12px 25px; border-radius: 8px; font-weight: bold;'>Fish Here</div>">> <<set $fishingLocation = "shallowOcean">> <<goto "FishingQTE">> <</link>> <<else>> <div style="background: #444; color: #666; padding: 12px 25px; border-radius: 8px; font-weight: bold;">Locked</div> <</if>> </div> </div> <!-- Deep Ocean --> <<set _canAccessDeep = setup.fishing.canAccessZone("deepOcean")>> <div style="border: 3px solid <<if _canAccessDeep>>#9b59b6<<else>>#555<</if>>; border-radius: 12px; padding: 20px; background: #2a2a2a; opacity: <<if _canAccessDeep>>1<<else>>0.6<</if>>;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div> <h3 style="color: <<if _canAccessDeep>>#9b59b6<<else>>#555<</if>>; margin: 0 0 8px 0;">Deep Ocean</h3> <p style="color: #aaa; margin: 0; font-size: 14px;"><<if _canAccessDeep>>Far from shore. Rare to Legendary fish. Requires Tier 2+ boat.<<else>>Requires Fishing Boat or better.<</if>></p> </div> <<if _canAccessDeep>> <<link "<div style='background: #9b59b6; color: white; padding: 12px 25px; border-radius: 8px; font-weight: bold;'>Fish Here</div>">> <<set $fishingLocation = "deepOcean">> <<goto "FishingQTE">> <</link>> <<else>> <div style="background: #444; color: #666; padding: 12px 25px; border-radius: 8px; font-weight: bold;">Need Better Boat</div> <</if>> </div> </div> <!-- Abyssal Zone --> <<set _canAccessAbyssal = setup.fishing.canAccessZone("abyssal")>> <div style="border: 3px solid <<if _canAccessAbyssal>>#e74c3c<<else>>#555<</if>>; border-radius: 12px; padding: 20px; background: #2a2a2a; opacity: <<if _canAccessAbyssal>>1<<else>>0.6<</if>>;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;"> <div> <h3 style="color: <<if _canAccessAbyssal>>#e74c3c<<else>>#555<</if>>; margin: 0 0 8px 0;">Abyssal Zone</h3> <p style="color: #aaa; margin: 0; font-size: 14px;"><<if _canAccessAbyssal>>The deep unknown. Legendary and Mythical creatures. Requires Charter Vessel.<<else>>Requires Charter Vessel.<</if>></p> </div> <<if _canAccessAbyssal>> <<link "<div style='background: #e74c3c; color: white; padding: 12px 25px; border-radius: 8px; font-weight: bold;'>Fish Here</div>">> <<set $fishingLocation = "abyssal">> <<goto "FishingQTE">> <</link>> <<else>> <div style="background: #444; color: #666; padding: 12px 25px; border-radius: 8px; font-weight: bold;">Need Charter Vessel</div> <</if>> </div> </div> </div> <!-- Navigation --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #555; padding: 15px 30px; border-radius: 10px; text-align: center; color: white; font-weight: bold;'>← Return to Docks</div>">> <<set $fishingLocation = null>> <<goto $lastLocation>> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomRenovation">> <<set _size = $renovateRoomSize || "small">> <<set _index = $renovateRoomIndex || 0>> <<set _returnPassage = $renovateReturnPassage || "PlayerSuburbanHome">> <<set _options = setup.roomRenovations[_size] || []>> <<set _home = setup.getCurrentHome()>> <!-- Initialize if needed --> <<if !$homeRenovations>><<set $homeRenovations = {}>><</if>> <<if !$homeRenovations[_home]>><<set $homeRenovations[_home] = {small: [], medium: [], large: []}>><</if>> <!-- Check if this is a re-renovation --> <<set _existingRoom = $homeRenovations[_home][_size][_index] || null>> <<set _isReRenovation = _existingRoom !== null>> <<set _sizeColors = { small: "#51cf66", medium: "#ffd700", large: "#e74c3c" }>> <<set _sizeColor = _sizeColors[_size] || "#667eea">> <<set _sizeLabels = { small: "Small Room", medium: "Medium Room", large: "Large Room" }>> <<set _sizeLabel = _sizeLabels[_size] || "Room">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: <<print _sizeColor>>; text-align: center;">🔧 <<if _isReRenovation>>Re-Renovate<<else>>Room Renovation<</if>></h1> <<if _isReRenovation>> <<set _existingData = setup.roomRenovations[_size].find(function(r) { return r.id === _existingRoom; })>> <div style="padding: 15px; background: #3a2a2a; border-radius: 10px; margin-bottom: 20px; border: 2px solid #e74c3c;"> <p style="color: #e74c3c; font-size: 16px; margin: 0; text-align: center;"> ⚠️ Currently: <<print _existingData.icon>> <<print _existingData.name>> </p> <p style="color: #888; font-size: 13px; margin: 5px 0 0 0; text-align: center;"> Re-renovating will return any decor from this room to storage. </p> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, <<print _sizeColor>> 0%, <<print _sizeColor>>99 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid <<print _sizeColor>>;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Choose what to convert this <<print _sizeLabel.toLowerCase()>> into. </p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #ffd700; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 25px;"> <<for _option range _options>> <<set _renoDiscountPct = setup.skillTree.getEffect("renovationDiscount") || 0>> <<set _discountedCost = Math.floor(_option.cost * (1 - _renoDiscountPct / 100))>> <<if _option.id === "laboratory" && setup.skillTree.getEffect("freeLabRenovation")>><<set _discountedCost = 0>><</if>> <<set _canAfford = $money >= _discountedCost>> <<set _isSameRoom = _existingRoom === _option.id>> <<set _isComingSoon = _option.comingSoon || false>> <div style="border: 3px solid <<if _isSameRoom || _isComingSoon>>#666<<else>><<print _option.color>><</if>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); <<if _isSameRoom || _isComingSoon>>opacity: 0.6;<</if>>"> <h3 style="color: <<if _isSameRoom || _isComingSoon>>#666<<else>><<print _option.color>><</if>>; margin: 0 0 10px 0;"><<print _option.icon>> <<print _option.name>><<if _isSameRoom>> (Current)<</if>><<if _isComingSoon>> <span style="color: #ffa500; font-size: 12px;">(Coming Soon)</span><</if>></h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 10px 0;"><<print _option.description>></p> <p style="color: #51cf66; font-size: 13px; margin: 0 0 15px 0;">✓ <<print _option.benefit>></p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 15px 0;">Cost: <<if _discountedCost < _option.cost>><span style="text-decoration: line-through; color: #888;">$<<print _option.cost>></span> <span style="color: #51cf66;">$<<print _discountedCost>></span><<else>>$<<print _option.cost>><</if>></p> <<if _isComingSoon>> <div style="background: #3a3a3a; color: #ffa500; padding: 12px; border-radius: 6px; text-align: center; border: 1px solid #ffa500;">🚧 Coming Soon</div> <<elseif _isSameRoom>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Already This Room</div> <<elseif _canAfford>> <<capture _option, _size, _index, _returnPassage, _home, _existingRoom, _isReRenovation>> <<set _btnLabel = "<div style='background: linear-gradient(135deg, " + _option.color + " 0%, " + _option.color + "cc 100%); color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Renovate ($" + _discountedCost + ")</div>">> <<link _btnLabel>> <!-- Handle re-renovation cleanup --> <<if _isReRenovation>> <!-- Return decor from this room to storage --> <<set _roomKey = _size + "_" + _index>> <<if $homeDecor[_home] && $homeDecor[_home].placedDecor>> <<for _decorKey, _placedItem range $homeDecor[_home].placedDecor>> <<if _placedItem && _placedItem.room === _roomKey>> <!-- Move decor back to storage --> <<if !$decorStorage>><<set $decorStorage = []>><</if>> <<run $decorStorage.push({ id: _placedItem.id, name: _placedItem.name, icon: _placedItem.icon, category: _placedItem.category, rarity: _placedItem.rarity })>> <<run delete $homeDecor[_home].placedDecor[_decorKey]>> <</if>> <</for>> <</if>> <!-- Remove old room bonuses --> <<if _existingRoom === "home_office">> <<set $bonusDailyTrades = Math.max(0, ($bonusDailyTrades || 0) - 2)>> <<elseif _existingRoom === "small_fish_tank">> <!-- Return fish to inventory --> <<if $homeFishTanks && $homeFishTanks[_home] && $homeFishTanks[_home].small>> <<for _fish range $homeFishTanks[_home].small.fish>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<run $fishInventory.push(_fish)>> <</for>> <<run delete $homeFishTanks[_home].small>> <</if>> <<elseif _existingRoom === "medium_fish_tank">> <!-- Return fish to inventory --> <<if $homeFishTanks && $homeFishTanks[_home] && $homeFishTanks[_home].medium>> <<for _fish range $homeFishTanks[_home].medium.fish>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<run $fishInventory.push(_fish)>> <</for>> <<run delete $homeFishTanks[_home].medium>> <</if>> <</if>> <</if>> <!-- Pay for renovation (with skill tree discount) --> <<set _finalCost = Math.floor(_option.cost * (1 - (setup.skillTree.getEffect("renovationDiscount") || 0) / 100))>> <<if _option.id === "laboratory" && setup.skillTree.getEffect("freeLabRenovation")>><<set _finalCost = 0>><</if>> <<set $money -= _finalCost>> <!-- Set or replace room at index --> <<if _isReRenovation>> <<set $homeRenovations[_home][_size][_index] = _option.id>> <<else>> <!-- New renovation - push if array isn't long enough --> <<if $homeRenovations[_home][_size].length <= _index>> <<run $homeRenovations[_home][_size].push(_option.id)>> <<else>> <<set $homeRenovations[_home][_size][_index] = _option.id>> <</if>> <</if>> <!-- Apply new room bonuses --> <<if _option.id === "small_fish_tank">> <<if !$homeFishTanks>><<set $homeFishTanks = {}>><</if>> <<if !$homeFishTanks[_home]>><<set $homeFishTanks[_home] = {}>><</if>> <<set $homeFishTanks[_home].small = {fish: [], capacity: 5}>> <<elseif _option.id === "medium_fish_tank">> <<if !$homeFishTanks>><<set $homeFishTanks = {}>><</if>> <<if !$homeFishTanks[_home]>><<set $homeFishTanks[_home] = {}>><</if>> <<set $homeFishTanks[_home].medium = {fish: [], capacity: 15}>> <<elseif _option.id === "home_office">> <<set $bonusDailyTrades = ($bonusDailyTrades || 0) + 2>> <</if>> <<run setup.achievements.unlock("first_renovation")>> <<goto "RoomRenovationManager">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Cannot Afford</div> <</if>> </div> <</for>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Cancel</div>">> <<goto "RoomRenovationManager">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomHomeGym">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <<if !$homeGymHoursToday || $lastHomeGymDay !== $dayNumber>> <<set $homeGymHoursToday = 0>> <<set $lastHomeGymDay = $dayNumber>> <</if>> <<set _hoursRemaining = 3 - $homeGymHoursToday>> <<set _isGymBunny = $physicalTraits.includes("Gym Bunny")>> <<set _isCerberus = $physicalTraits.includes("Cerberus")>> <<set _canBypassCap = _isGymBunny || _isCerberus>> <<set _canTrain = _hoursRemaining > 0 || _canBypassCap>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomHomeGym")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #e74c3c; text-align: center;">🏋️ Home Gym</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e74c3c;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Your personal workout space. No gym membership required! </p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <<if _canBypassCap>> <p style="color: #51cf66; font-size: 16px; margin: 0;">⏰ Training Time: <strong>Unlimited</strong> (<<if _isGymBunny>>🐰 Gym Bunny<<else>>🔥 Cerberus<</if>>)</p> <<else>> <p style="color: #ffd700; font-size: 16px; margin: 0;">⏰ Training Time Remaining Today: <strong><<print _hoursRemaining>> / 3 hours</strong></p> <</if>> </div> <<set _isLizardmanHome = $physicalTraits.includes("Lizardman")>> <<set _isKakuenHome = $physicalTraits.includes("Kakuen")>> <<set _isAutomatonHome = $physicalTraits.includes("Automaton")>> <<set _homeStrMultiplier = _isLizardmanHome ? 3 : (_isCerberus ? 4 : (_isGymBunny ? 4 : 1))>> <<set _homeDexMultiplier = _isCerberus ? 4 : (_isGymBunny ? 4 : 1)>> <<if _isAutomatonHome>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #888; margin-bottom: 20px;"> <p style="color: #888; margin: 0; text-align: center; font-size: 14px; font-weight: bold;"> ✗ Automaton: Your mechanical body cannot benefit from physical training. </p> </div> <<elseif _isGymBunny || _isCerberus || _isLizardmanHome || _isKakuenHome>> <div style="background: linear-gradient(135deg, #3a1a4a 0%, #2a0a3e 100%); padding: 10px; border-radius: 8px; border: 2px solid #ff6b6b; margin-bottom: 20px; box-shadow: 0 0 15px rgba(255,107,107,0.4);"> <p style="color: #ff6b6b; margin: 0; text-align: center; font-size: 14px; font-weight: bold; text-shadow: 0 0 8px rgba(255,107,107,0.5);"> <<if _isGymBunny>>✓ Gym Bunny: 4x Workout Gains | Unlimited Training | Removes Compulsion<<elseif _isCerberus>>✓ Cerberus: 4x Workout Gains | Unlimited Training<<elseif _isLizardmanHome>>✓ Lizardman: 3x Strength Training (Strength Only)<<elseif _isKakuenHome>>✓ Kakuen: Strength Training also grants +1 Charisma and +1 Intelligence<</if>> </p> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e74c3c; margin: 0 0 15px 0;">💪 Strength Training</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Build muscle with weights.</p> <p style="color: #51cf66; font-size: 13px; margin-bottom: 10px;">Gains: +<<print _homeStrMultiplier>> Strength<<if _isKakuenHome>>, +1 Charisma, +1 Intelligence<</if>></p> <<if _isAutomatonHome>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Unavailable (Automaton)</div> <<elseif _canTrain>> <<link "<div style='background: #e74c3c; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Train Strength (1 hour)</div>">> <<set $homeGymHoursToday += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<run advanceTime(60)>> <<set $stats.strength = Math.max($stats.strength, Math.min($statMaxCaps.strength, $stats.strength + _homeStrMultiplier))>> <<if $physicalTraits.includes("Kakuen")>> <<set $stats.charisma = Math.max($stats.charisma, Math.min($statMaxCaps.charisma, $stats.charisma + 1))>> <<set $stats.intelligence = Math.max($stats.intelligence, Math.min($statMaxCaps.intelligence, $stats.intelligence + 1))>> <</if>> <<goto "RoomHomeGym">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Too tired to train more today</div> <</if>> </div> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: <<if _isLizardmanHome || _isAutomatonHome>>#666<<else>>#f39c12<</if>>; margin: 0 0 15px 0;">🏃 Agility Training</h3> <<if _isAutomatonHome>> <p style="color: #666; font-size: 14px; margin-bottom: 15px;">Your mechanical body cannot benefit from physical training.</p> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Unavailable (Automaton)</div> <<elseif _isLizardmanHome>> <p style="color: #666; font-size: 14px; margin-bottom: 15px;">Your Lizardman body is built for raw power, not agility.</p> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Unavailable (Lizardman)</div> <<elseif _canTrain>> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Improve coordination and speed.</p> <p style="color: #51cf66; font-size: 13px; margin-bottom: 10px;">Gains: +<<print _homeDexMultiplier>> Dexterity</p> <<link "<div style='background: #f39c12; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Train Dexterity (1 hour)</div>">> <<set $homeGymHoursToday += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<run advanceTime(60)>> <<set $stats.dexterity = Math.max($stats.dexterity, Math.min($statMaxCaps.dexterity, $stats.dexterity + _homeDexMultiplier))>> <<goto "RoomHomeGym">> <</link>> <<else>> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Improve coordination and speed.</p> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Too tired to train more today</div> <</if>> </div> </div> <div style="text-align: center;"> <<link "<div style='background: #e74c3c; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomArtStudio">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomArtStudio")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #9b59b6; text-align: center;">🎨 Art Studio</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Express your creativity on canvas. </p> </div> <!-- Check for art-related traits --> <<set _canPaint = ($skills && ($skills.includes("Art") || $skills.includes("Painting"))) || ($mentalTraits && ($mentalTraits.includes("Artistic") || $mentalTraits.includes("Creative")))>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid <<if _canPaint>>#51cf66<<else>>#666<</if>>; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: <<if _canPaint>>#51cf66<<else>>#888<</if>>; margin: 0 0 15px 0;">🖼️ Create a Painting</h3> <<if _canPaint>> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Express yourself on canvas. Your creation will be stored in your decoration collection.</p> <<link "<div style='background: #51cf66; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Painting</div>">> <<goto "ArtStudioPaint">> <</link>> <<else>> <p style="color: #888; font-size: 14px; margin-bottom: 10px;">You lack the artistic ability to create paintings.</p> <p style="color: #ffd700; font-size: 12px; margin: 0;">Required traits: Art, Artistic, Creative, or Painting</p> <</if>> </div> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffd700; margin: 0 0 15px 0;">📊 Studio Stats</h3> <p style="color: #ccc; font-size: 14px;">Paintings Created: <span style="color: #51cf66;"><<print ($playerPaintings ? $playerPaintings.length : 0)>></span></p> <p style="color: #888; font-size: 12px; margin-top: 10px;">Each painting takes 2 hours to complete and is stored in your decorations.</p> </div> </div> <div style="text-align: center;"> <<link "<div style='background: #9b59b6; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "ArtStudioPaint">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <!-- Check for art-related traits --> <<set _canPaint = ($skills && ($skills.includes("Art") || $skills.includes("Painting"))) || ($mentalTraits && ($mentalTraits.includes("Artistic") || $mentalTraits.includes("Creative")))>> <<if !_canPaint>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px; max-width: 600px; margin: 0 auto; text-align: center;"> <h1 style="color: #ff6b6b;">❌ Cannot Paint</h1> <p style="color: #ccc; font-size: 16px; margin: 20px 0;">You lack the artistic ability to create paintings.</p> <p style="color: #ffd700; font-size: 14px; margin-bottom: 30px;">Required traits: Art, Artistic, Creative, or Painting</p> <<link "<div style='background: #9b59b6; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Back to Studio</div>">><<goto "RoomArtStudio">><</link>> </div> </div> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px; max-width: 600px; margin: 0 auto;"> <h1 style="color: #9b59b6; text-align: center;">🎨 Create Your Painting</h1> <div style="padding: 15px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> Paint your masterpiece on the canvas below! </p> </div> <!-- Painting Title --> <div style="margin-bottom: 15px;"> <label style="color: #9b59b6; font-weight: bold; display: block; margin-bottom: 8px;">Painting Title:</label> <<textbox "$tempPaintingTitle" "" autofocus>> </div> <!-- Drawing Canvas --> <div class="art-canvas-container"> <canvas id="artCanvas" class="art-canvas" width="400" height="300"></canvas> <!-- Color Palette --> <div id="art-palette" class="art-color-palette"></div> <!-- Tools Row --> <div class="art-tools-row"> <button id="art-tool-brush" class="art-tool-btn selected">🖌️ Brush</button> <button id="art-tool-eraser" class="art-tool-btn">🧽 Eraser</button> <button id="art-tool-clear" class="art-tool-btn">🗑️ Clear</button> </div> <!-- Brush Size --> <div class="art-brush-size"> <span>Brush Size:</span> <input type="range" id="art-brush-size" min="1" max="40" value="5"> <span id="art-size-label">5px</span> <div id="art-brush-preview" class="art-brush-preview"></div> </div> </div> <p style="color: #888; font-size: 14px; text-align: center; margin-top: 15px;">⏱️ Painting will take 2 hours to complete</p> <div style="display: flex; gap: 15px; justify-content: center; margin-top: 20px;"> <<link "<div style='background: #51cf66; color: white; padding: 15px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>🖌️ Finish Painting</div>">> <<if $tempPaintingTitle && $tempPaintingTitle.trim() !== "">> <<run advanceTime(120)>> <<if !$playerPaintings>><<set $playerPaintings = []>><</if>> <<set _imageData = window.ArtCanvas.getImageData()>> <<set _paintingId = "painting_" + Date.now()>> <<run setup.paintingStorage.save(_paintingId, _imageData)>> <<set _newPainting = { title: $tempPaintingTitle.trim(), createdDay: $dayNumber, id: _paintingId }>> <<run $playerPaintings.push(_newPainting)>> <<set $lastCreatedPainting = _newPainting>> <<set $tempPaintingTitle = "">> <<goto "ArtStudioPaintResult">> <<else>> <<replace "#paint-error">> <p style="color: #ff6b6b; margin-top: 15px; text-align: center;">Please enter a title for your painting!</p> <</replace>> <</if>> <</link>> <<link "<div style='background: #666; color: white; padding: 15px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Cancel</div>">> <<set $tempPaintingTitle = "">> <<goto "RoomArtStudio">> <</link>> </div> <span id="paint-error"></span> </div></div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "ArtStudioPaintResult">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #51cf66; text-align: center;">🎨 Masterpiece Complete!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #51cf66 0%, #2f9e44 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #51cf66;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> You step back from the easel and admire your work... </p> </div> <div style="background: #2a2a2a; padding: 30px; border-radius: 10px; margin-bottom: 25px; border: 2px solid #9b59b6; text-align: center;"> <<if setup.paintingStorage.getImage($lastCreatedPainting)>> <img @src="setup.paintingStorage.getImage($lastCreatedPainting)" class="painting-display-large" alt="Your Painting" style="margin-bottom: 20px;"> <<else>> <div style="font-size: 80px; margin-bottom: 20px;">🖼️</div> <</if>> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">"<<print $lastCreatedPainting.title>>"</h2> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; display: inline-block;"> <p style="color: #51cf66; margin: 0;">✓ Painting added to your collection!</p> <p style="color: #888; font-size: 12px; margin: 5px 0 0 0;">Total paintings: <<print $playerPaintings.length>></p> </div> </div> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='background: #9b59b6; color: white; padding: 15px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>🎨 Paint Another</div>">> <<goto "ArtStudioPaint">> <</link>> <<link "<div style='background: #51cf66; color: white; padding: 15px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Back to Studio</div>">> <<goto "RoomArtStudio">> <</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "DecorHangPainting">> <<set _home = setup.getCurrentHome()>> <<set _painting = $selectedPaintingForHanging>> <<set _currentlyHungIn = setup.roomPaintings.isHung(_painting.id)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px; max-width: 600px; margin: 0 auto;"> <h1 style="color: #9b59b6; text-align: center;">🖼️ Hang Painting</h1> <div style="padding: 15px; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <p style="color: white; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> Choose where to display your artwork </p> </div> <!-- Selected Painting Preview --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #9b59b6; text-align: center;"> <<if setup.paintingStorage.getImage(_painting)>> <img @src="setup.paintingStorage.getImage(_painting)" class="painting-display-large" alt="Painting"> <<else>> <div style="font-size: 80px; margin-bottom: 10px;">🎨</div> <</if>> <h3 style="color: #9b59b6; margin: 15px 0 5px 0;">"<<print _painting.title>>"</h3> <<if _currentlyHungIn>> <p style="color: #51cf66; font-size: 14px; margin: 0;">Currently hung in: <<print _currentlyHungIn>></p> <<else>> <p style="color: #888; font-size: 14px; margin: 0;">Not currently displayed</p> <</if>> </div> <!-- Room Selection --> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #51cf66;"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">Select a Room</h3> <<set _availableRooms = setup.roomPaintings.getAvailableRooms()>> <<if _availableRooms.length === 0>> <p style="color: #888;">You need to renovate rooms before you can hang paintings!</p> <p style="color: #666; font-size: 12px;">Visit the Renovation Manager to add rooms to your home.</p> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px;"> <<for _room range _availableRooms>> <<set _roomHasPainting = setup.roomPaintings.getPainting(_room.id)>> <<set _isCurrentRoom = _currentlyHungIn === _room.id>> <<capture _room, _painting>> <<link "<div style='background: <<if _isCurrentRoom>>#51cf66<<elseif _roomHasPainting>>#666<<else>>#3a3a3a<</if>>; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; border: 2px solid <<if _isCurrentRoom>>#51cf66<<else>>#555<</if>>;'><<print _room.name>><<if _roomHasPainting && !_isCurrentRoom>> 🖼️<</if>><<if _isCurrentRoom>> ✓<</if>></div>">> <<run setup.roomPaintings.assignToRoom(_painting.id, _room.id)>> <<goto "HomeDecorManager">> <</link>> <</capture>> <</for>> </div> <p style="color: #666; font-size: 11px; margin-top: 10px; text-align: center;">🖼️ = Room already has a painting (will be replaced)</p> <</if>> </div> <!-- Remove from Wall Option --> <<if _currentlyHungIn>> <div style="background: #3a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #ff6b6b; text-align: center;"> <<link "<div style='background: #ff6b6b; color: white; padding: 12px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>🗑️ Remove from Wall</div>">> <<run setup.roomPaintings.removeFromRoom(_currentlyHungIn)>> <<goto "HomeDecorManager">> <</link>> </div> <</if>> <div style="text-align: center;"> <<link "<div style='background: #666; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Back to Decor Manager</div>">> <<set $selectedPaintingForHanging = null>> <<goto "HomeDecorManager">> <</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomStudy">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomStudy")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #8b4513; text-align: center;">📚 Study</h1> <div style="padding: 20px; background: linear-gradient(135deg, #8b4513 0%, #654321 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8b4513;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A quiet space for reading and contemplation. </p> </div> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Coming Soon</h2> <p style="color: #ccc;">Book collection and reading features will be added in a future update!</p> </div> <div style="text-align: center;"> <<link "<div style='background: #8b4513; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomGuestBedroom">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomGuestBedroom")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #3498db; text-align: center;">🛏️ Guest Bedroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #3498db;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A comfortable space for overnight guests. </p> </div> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Coming Soon</h2> <p style="color: #ccc;">NPC sleepover features will be added in a future update!</p> <p style="color: #888; font-size: 14px;">Requires level 2+ relationship with NPC</p> </div> <div style="text-align: center;"> <<link "<div style='background: #3498db; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomSmallFishTank">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <<if !$homeFishTanks>><<set $homeFishTanks = {}>><</if>> <<if !$homeFishTanks[_home]>><<set $homeFishTanks[_home] = {}>><</if>> <<if !$homeFishTanks[_home].small>><<set $homeFishTanks[_home].small = {fish: [], capacity: 5}>><</if>> <<set _tank = $homeFishTanks[_home].small>> <<set _capacity = _tank.capacity || 5>> <div style="background: linear-gradient(180deg, #0a1628 0%, #1a3a5c 50%, #0a1628 100%); min-height: 100vh; padding: 20px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomSmallFishTank")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #1e90ff; text-align: center;">🐠 Small Fish Tank</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #0d6efd 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A modest aquarium for your fish collection. </p> </div> <div style="display: flex; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center;"> <div style="background: #1a1a1a; padding: 15px 25px; border-radius: 8px;"> <span style="color: #1e90ff;">🐟 Fish:</span> <span style="color: #51cf66;"><<print _tank.fish.length>> / <<print _capacity>></span> </div> <div style="background: #1a1a1a; padding: 15px 25px; border-radius: 8px;"> <span style="color: #ffd700;">⚠️ Limit:</span> <span style="color: #ccc;">Common to Epic only</span> </div> </div> <style> @keyframes fishSwim { 0%, 100% { transform: translateX(0px) translateY(0px); } 25% { transform: translateX(5px) translateY(-3px); } 50% { transform: translateX(0px) translateY(0px); } 75% { transform: translateX(-5px) translateY(3px); } } .fish-swimming { animation: fishSwim 3s ease-in-out infinite; } </style> <div style="background: linear-gradient(180deg, #0d47a1 0%, #1565c0 30%, #0d47a1 100%); border-radius: 15px; padding: 30px; min-height: 200px; position: relative; overflow: hidden; margin-bottom: 25px; border: 3px solid #1e90ff;"> <<if _tank.fish.length === 0>> <p style="text-align: center; color: #90caf9; padding-top: 60px; font-size: 18px;">The tank is empty. Transfer some fish from your inventory!</p> <<else>> <div style="display: flex; flex-wrap: wrap; gap: 15px; justify-content: center;"> <<for _i, _fish range _tank.fish>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <<set _animDelay = (_i * 0.5) % 3>> <div class="fish-swimming" style="background: rgba(0,0,0,0.5); border: 2px solid <<print _rarityColor>>; border-radius: 10px; padding: 15px; text-align: center; min-width: 100px; animation-delay: <<print _animDelay>>s;"> <<if _fish.icon && _fish.icon.indexOf("Images/") === 0>> <img @src="_fish.icon" style="width: 48px; height: 48px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 2em;">🐟</span> <<else>> <div style="font-size: 2em;"><<print _fish.icon || "🐟">></div> <</if>> <p style="color: <<print _rarityColor>>; margin: 5px 0; font-weight: bold; font-size: 14px;"><<print _fish.name>></p> <p style="font-size: 11px; color: #90caf9; text-transform: capitalize; margin: 0;"><<print _fish.rarity>></p> </div> <</for>> </div> <</if>> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #51cf66; border-radius: 10px; background: #2a2a2a; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🐟 Manage Fish</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">Add or remove fish from your tank.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Manage Fish</div>">> <<set $fishTankType = "small">> <<goto "FishTankTransfer">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Return Home</div>">> <<goto _returnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomMediumFishTank">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <<if !$homeFishTanks>><<set $homeFishTanks = {}>><</if>> <<if !$homeFishTanks[_home]>><<set $homeFishTanks[_home] = {}>><</if>> <<if !$homeFishTanks[_home].medium>><<set $homeFishTanks[_home].medium = {fish: [], capacity: 15}>><</if>> <<set _tank = $homeFishTanks[_home].medium>> <<set _capacity = _tank.capacity || 15>> <div style="background: linear-gradient(180deg, #0a1628 0%, #1a3a5c 50%, #0a1628 100%); min-height: 100vh; padding: 20px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomMediumFishTank")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #1e90ff; text-align: center;">🐟 Medium Aquarium</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1e90ff 0%, #0d6efd 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1e90ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A spacious aquarium for your growing collection. </p> </div> <div style="display: flex; gap: 20px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center;"> <div style="background: #1a1a1a; padding: 15px 25px; border-radius: 8px;"> <span style="color: #1e90ff;">🐟 Fish:</span> <span style="color: #51cf66;"><<print _tank.fish.length>> / <<print _capacity>></span> </div> <div style="background: #1a1a1a; padding: 15px 25px; border-radius: 8px;"> <span style="color: #ffd700;">⚠️ Limit:</span> <span style="color: #ccc;">Common to Epic only</span> </div> </div> <style> @keyframes fishSwim { 0%, 100% { transform: translateX(0px) translateY(0px); } 25% { transform: translateX(5px) translateY(-3px); } 50% { transform: translateX(0px) translateY(0px); } 75% { transform: translateX(-5px) translateY(3px); } } .fish-swimming { animation: fishSwim 3s ease-in-out infinite; } </style> <div style="background: linear-gradient(180deg, #0d47a1 0%, #1565c0 30%, #0d47a1 100%); border-radius: 15px; padding: 30px; min-height: 250px; position: relative; overflow: hidden; margin-bottom: 25px; border: 3px solid #1e90ff;"> <<if _tank.fish.length === 0>> <p style="text-align: center; color: #90caf9; padding-top: 80px; font-size: 18px;">The tank is empty. Transfer some fish from your inventory!</p> <<else>> <div style="display: flex; flex-wrap: wrap; gap: 15px; justify-content: center;"> <<for _i, _fish range _tank.fish>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <<set _animDelay = (_i * 0.5) % 3>> <div class="fish-swimming" style="background: rgba(0,0,0,0.5); border: 2px solid <<print _rarityColor>>; border-radius: 10px; padding: 15px; text-align: center; min-width: 100px; animation-delay: <<print _animDelay>>s;"> <<if _fish.icon && _fish.icon.indexOf("Images/") === 0>> <img @src="_fish.icon" style="width: 48px; height: 48px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 2em;">🐟</span> <<else>> <div style="font-size: 2em;"><<print _fish.icon || "🐟">></div> <</if>> <p style="color: <<print _rarityColor>>; margin: 5px 0; font-weight: bold; font-size: 14px;"><<print _fish.name>></p> <p style="font-size: 11px; color: #90caf9; text-transform: capitalize; margin: 0;"><<print _fish.rarity>></p> </div> <</for>> </div> <</if>> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #51cf66; border-radius: 10px; background: #2a2a2a; padding: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🐟 Manage Fish</h3> <p style="color: #ccc; font-size: 14px; margin: 0 0 15px 0;">Add or remove fish from your tank.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Manage Fish</div>">> <<set $fishTankType = "medium">> <<goto "FishTankTransfer">> <</link>> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #1e90ff; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Return Home</div>">> <<goto _returnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomLaboratory">><<set $extractionResult = null>> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <!-- Initialize lab variables if needed --> <<if !$labResearchHoursToday || $lastLabDay !== $dayNumber>> <<set $labResearchHoursToday = 0>> <<set $lastLabDay = $dayNumber>> <</if>> <<set _hoursRemaining = 4 - $labResearchHoursToday>> <div style="background: linear-gradient(180deg, #0a1f1c 0%, #0d2a26 50%, #0a1f1c 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #00d4aa; text-align: center;">🧪 Laboratory</h1> <div style="padding: 20px; background: linear-gradient(135deg, #00d4aa 0%, #008b7a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00d4aa;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A state-of-the-art research facility for scientific self-improvement and trait research. </p> </div> <!-- Research Hours Display --> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #00d4aa; font-size: 16px; margin: 0;">🔬 Research Time Remaining Today: <strong><<print _hoursRemaining>> / 4 hours</strong></p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <!-- Intelligence Training --> <div style="border: 3px solid #4dabf7; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">📚 Research Study</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Study scientific journals and conduct experiments to improve your intelligence.</p> <p style="color: #51cf66; font-size: 13px; margin-bottom: 15px;">+1 Intelligence per hour</p> <<if ($stats.intelligence || 0) >= 100>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Nothing left to learn here</div> <<elseif _hoursRemaining > 0>> <<link "<div style='background: #4dabf7; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Study (1 hour)</div>">> <<set $labResearchHoursToday += 1>> <<run advanceTime(60)>> <<set $stats.intelligence = Math.max(($stats.intelligence || 0), Math.min(100, ($stats.intelligence || 0) + 1))>> <<goto "RoomLaboratory">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Brain needs rest - study again tomorrow</div> <</if>> </div> <!-- Trait Extractor --> <<set _ext = setup.getExtractableTrait()>> <div style="border: 3px solid #e040fb; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #e040fb; margin: 0 0 10px 0;">🧬 Trait Extractor</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Draw the lesser trait out of certain transformations. The transformation is destroyed; the trait within is left behind.</p> <<if _ext>> <p style="color: #51cf66; font-size: 13px; margin-bottom: 15px;">Ready: extract <<= _ext.trait>> from your <<= $activeTransformation>> Trait</p> <<else>> <p style="color: #888; font-size: 13px; margin-bottom: 15px;">Only works while in certain transformations</p> <</if>> <<link "<div style='background: #e040fb; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Open Extractor</div>">> <<goto "LabTraitExtractor">> <</link>> </div> <!-- Trait Combiner --> <div style="border: 3px solid #ff6b35; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #ff6b35; margin: 0 0 10px 0;">⚗️ Trait Combiner</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Combine compatible traits to create more powerful versions.</p> <p style="color: #ffd43b; font-size: 13px; margin-bottom: 15px;">Costs 1 daily trade per attempt</p> <<if setup.cafe.isPlayerLifeswappedAsMaid()>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center; font-weight: bold;">Not while in <<= $lifeSwapPortraitSource>>'s body</div> <<elseif $tradesRemainingToday > 0>> <<link "<div style='background: #ff6b35; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Open Combiner</div>">> <<goto "LabTraitCombiner">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">No trades remaining today</div> <</if>> </div> </div> <!-- Return Button --> <div style="text-align: center; margin-top: 30px;"> <<if _returnPassage === "Hospital">> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Return to Hospital</div>">> <<goto _returnPassage>> <</link>> <<else>> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Return Home</div>">> <<goto _returnPassage>> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set _ext = setup.getExtractableTrait()>> <div style="background: linear-gradient(180deg, #0a1f1c 0%, #0d2a26 50%, #0a1f1c 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #e040fb; text-align: center;">🧬 Trait Extractor</h1> <<if $extractionResult>> <<set _r = $extractionResult>> <<set _rb = setup.traitBonuses[_r.trait] ? setup.labCombiner.bonusText(setup.traitBonuses[_r.trait]) : "">> <div style="background: #14331f; border: 2px solid #51cf66; border-radius: 12px; padding: 22px; margin: 0 auto 25px auto; max-width: 600px; text-align: center;"> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0 0 8px 0;">✓ Extraction complete</p> <p style="color: #ddd; font-size: 15px; margin: 0 0 6px 0;">You drew <span style="color:#e040fb; font-weight:bold;"><<= _r.trait>></span> out of your <<= _r.tf>> Trait. The transformation is gone.</p> <<if _rb>><p style="color: #9be7c4; font-size: 13px; margin: 0;"><<= _rb>></p><</if>> </div> <div style="text-align:center;"> <<link "<div style='display:inline-block; background:#667eea; color:white; padding:12px 30px; border-radius:8px; font-weight:bold; cursor:pointer;'>← Back to the lab</div>">> <<set $extractionResult = null>> <<goto "RoomLaboratory">> <</link>> </div> <<elseif _ext>> <<set _eb = setup.traitBonuses[_ext.trait] ? setup.labCombiner.bonusText(setup.traitBonuses[_ext.trait]) : "">> <div style="background: #1a1a1a; border: 3px solid #e040fb; border-radius: 12px; padding: 22px; margin: 0 auto 20px auto; max-width: 600px;"> <p style="color: #ccc; font-size: 15px; margin: 0 0 14px 0;">The extractor can draw a single lesser trait out of your current transformation. Doing so <span style="color:#ff6b6b; font-weight:bold;">permanently destroys</span> the transformation.</p> <div style="background:#0d2a26; border-radius:8px; padding:14px; margin-bottom:14px;"> <p style="color:#9aa7b5; font-size:13px; margin:0 0 6px 0;">Current Trait</p> <p style="color:#00d4aa; font-size:18px; font-weight:bold; margin:0 0 12px 0;"><<= $activeTransformation>></p> <p style="color:#9aa7b5; font-size:13px; margin:0 0 6px 0;">Trait left behind</p> <p style="color:#e040fb; font-size:18px; font-weight:bold; margin:0;">🧬 <<= _ext.trait>></p> <<if _eb>><p style="color:#9be7c4; font-size:13px; margin:6px 0 0 0;"><<= _eb>></p><</if>> </div> <div id="extractAction" style="text-align:center;"> <<link "<div style='display:inline-block; background:#e040fb; color:white; padding:12px 28px; border-radius:8px; font-weight:bold; cursor:pointer;'>Extract the trait</div>">> <<replace "#extractAction">> <p style="color:#ff6b6b; font-size:14px; margin:0 0 12px 0;">This permanently destroys your <<= $activeTransformation>> Trait. Are you sure?</p> <<link "<div style='display:inline-block; background:#c0392b; color:white; padding:10px 24px; border-radius:8px; font-weight:bold; cursor:pointer; margin:4px;'>Yes, extract it</div>">> <<run setup.extractTraitFromTransformation()>> <<goto "LabTraitExtractor">> <</link>> <<link "<div style='display:inline-block; background:#2a2a3e; color:#aab5c5; padding:10px 24px; border-radius:8px; cursor:pointer; margin:4px;'>Cancel</div>">> <<goto "LabTraitExtractor">> <</link>> <</replace>> <</link>> </div> </div> <div style="text-align:center;"> <<link "<div style='display:inline-block; background:#667eea; color:white; padding:12px 30px; border-radius:8px; font-weight:bold; cursor:pointer;'>← Back to the lab</div>">> <<goto "RoomLaboratory">> <</link>> </div> <<else>> <div style="background: #1a1a1a; border: 3px solid #555; border-radius: 12px; padding: 22px; margin: 0 auto 20px auto; max-width: 600px;"> <p style="color: #ccc; font-size: 15px; margin: 0 0 12px 0;">The extractor pulls the lesser trait out of certain transformations, destroying the transformation in the process. You do not currently have a Trait it can work on.</p> <p style="color: #9aa7b5; font-size: 13px; margin: 0 0 6px 0;">Forms it can extract from:</p> <ul style="color:#ddd; font-size:13px; line-height:1.7; margin:0; padding-left:20px;"> <li>Raiju → Electrified</li> <li>Cheshire Cat → Mirrored</li> <li>Lizardman → Scaled</li> <li>Angel → Blessed</li> <li>Automaton → Cog</li> <li>Kitsune → Mystic</li> <li>Anubis → Guardian</li> </ul> </div> <div style="text-align:center;"> <<link "<div style='display:inline-block; background:#667eea; color:white; padding:12px 30px; border-radius:8px; font-weight:bold; cursor:pointer;'>← Back to the lab</div>">> <<goto "RoomLaboratory">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "LabTraitAnalysis">> <div style="background: linear-gradient(180deg, #0a1f1c 0%, #0d2a26 50%, #0a1f1c 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #e040fb; text-align: center;">🧬 Trait Analysis</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e040fb 0%, #9c27b0 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e040fb;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Your complete genetic and trait profile analysis. </p> </div> <!-- Gather all player traits --> <<set _allTraits = []>> <<if $physicalTraits>> <<for _t range $physicalTraits>> <<run _allTraits.push({name: _t, type: "Physical"})>> <</for>> <</if>> <<if $mentalTraits>> <<for _t range $mentalTraits>> <<run _allTraits.push({name: _t, type: "Mental"})>> <</for>> <</if>> <!-- Trait Count Summary --> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #e040fb; font-size: 16px; margin: 0;">Total Traits: <strong><<print _allTraits.length>></strong></p> </div> <!-- Traits Display --> <<if _allTraits.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _i, _traitObj range _allTraits>> <<set _traitData = setup.traits ? setup.traits.find(function(t) { return t.name === _traitObj.name; }) : null>> <<set _traitColor = _traitData && _traitData.color ? _traitData.color : "#00d4aa">> <<set _traitDesc = _traitData && _traitData.description ? _traitData.description : "No data available">> <<capture _traitObj, _traitData, _traitColor, _traitDesc>> <<link "<div style='border: 2px solid " + _traitColor + "; border-radius: 10px; padding: 15px; background: #1a1a1a; cursor: pointer; transition: all 0.2s;' onmouseover='this.style.background=\"#2a2a2a\"; this.style.transform=\"scale(1.02)\"' onmouseout='this.style.background=\"#1a1a1a\"; this.style.transform=\"scale(1)\"'><h4 style='color: " + _traitColor + "; margin: 0 0 8px 0;'>" + _traitObj.name + "</h4><p style='color: #888; font-size: 12px; margin: 0 0 5px 0; text-transform: uppercase;'>" + _traitObj.type + "</p><p style='color: #ccc; font-size: 13px; margin: 0;'>" + _traitDesc + "</p><p style='color: #e040fb; font-size: 11px; margin: 10px 0 0 0;'>Click to analyze</p></div>">> <<set $analyzeTraitName = _traitObj.name>> <<set $analyzeTraitType = _traitObj.type>> <<goto "LabTraitDetail">> <</link>> <</capture>> <</for>> </div> <<else>> <div style="background: #2a2a2a; padding: 30px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #888; font-size: 16px; margin: 0;">No traits detected. Acquire traits through gameplay to analyze them here.</p> </div> <</if>> <!-- Return Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Laboratory</div>">> <<goto "RoomLaboratory">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "LabTraitDetail">> <<set _traitName = $analyzeTraitName || "Unknown">> <<set _traitType = $analyzeTraitType || "Unknown">> <<set _traitData = setup.traits ? setup.traits.find(function(t) { return t.name === _traitName; }) : null>> <<set _traitColor = _traitData && _traitData.color ? _traitData.color : "#e040fb">> <div style="background: linear-gradient(180deg, #0a1f1c 0%, #0d2a26 50%, #0a1f1c 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: <<print _traitColor>>; text-align: center;">🔬 Trait Analysis: <<print _traitName>></h1> <div style="padding: 20px; background: linear-gradient(135deg, <<print _traitColor>> 0%, #2a2a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid <<print _traitColor>>;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Detailed genetic analysis of your <<print _traitName>> trait. </p> </div> <div style="background: #1a1a1a; border: 3px solid <<print _traitColor>>; border-radius: 15px; padding: 25px; margin-bottom: 25px;"> <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 20px;"> <div style="font-size: 60px;">🧬</div> <div> <h2 style="color: <<print _traitColor>>; margin: 0 0 5px 0;"><<print _traitName>></h2> <p style="color: #888; text-transform: uppercase; margin: 0; font-size: 14px;"><<print _traitType>> Trait</p> </div> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; margin-bottom: 20px;"> <h3 style="color: #e040fb; margin: 0 0 15px 0;">📋 Description</h3> <<if _traitData && _traitData.description>> <p style="color: #ccc; font-size: 15px; line-height: 1.6; margin: 0;"><<print _traitData.description>></p> <<else>> <p style="color: #888; font-style: italic; margin: 0;">No detailed description available for this trait.</p> <</if>> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; text-align: center;"> <p style="color: #888; margin: 0 0 5px 0; font-size: 12px;">TRAIT TYPE</p> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0;"><<print _traitType>></p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; text-align: center;"> <p style="color: #888; margin: 0 0 5px 0; font-size: 12px;">RARITY</p> <<if _traitData && _traitData.rarity>> <p style="color: #ffd700; font-size: 18px; font-weight: bold; margin: 0; text-transform: capitalize;"><<print _traitData.rarity>></p> <<else>> <p style="color: #ffd700; font-size: 18px; font-weight: bold; margin: 0;">Standard</p> <</if>> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; text-align: center;"> <p style="color: #888; margin: 0 0 5px 0; font-size: 12px;">STATUS</p> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0;">Active</p> </div> </div> </div> <!-- Effects Section --> <div style="background: #1a1a1a; border: 2px solid #444; border-radius: 10px; padding: 20px; margin-bottom: 25px;"> <h3 style="color: #e040fb; margin: 0 0 15px 0;">⚡ Known Effects</h3> <<if _traitData && _traitData.effects>> <ul style="color: #ccc; margin: 0; padding-left: 20px;"> <<for _effect range _traitData.effects>> <li style="margin-bottom: 8px;"><<print _effect>></li> <</for>> </ul> <<else>> <p style="color: #888; font-style: italic; margin: 0;">Effects of this trait are still being researched...</p> <</if>> </div> <!-- Return Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #e040fb; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Trait List</div>">> <<goto "LabTraitAnalysis">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Initialize selection variables --> <<if !$combinerSelectedTraits>><<set $combinerSelectedTraits = []>><</if>> <<if $combinerAgeTrait === undefined>><<set $combinerAgeTrait = null>><</if>> <!-- Gather all player traits --> <<set _allTraits = []>> <<if $physicalTraits>> <<for _t range $physicalTraits>> <<run _allTraits.push({name: _t, type: "Physical"})>> <</for>> <</if>> <<if $mentalTraits>> <<for _t range $mentalTraits>> <<run _allTraits.push({name: _t, type: "Mental"})>> <</for>> <</if>> <<if $skills>> <<for _t range $skills>> <<run _allTraits.push({name: _t, type: "Skill"})>> <</for>> <</if>> <!-- Sort traits alphabetically by name --> <<run _allTraits.sort(function(a, b) { return a.name.localeCompare(b.name); })>> <<if $physicalTraits && $physicalTraits.indexOf("Oni") !== -1>> <div style="background: linear-gradient(180deg, #1a0f0a 0%, #2d1810 50%, #1a0f0a 100%); min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #c4a040; text-align: center;">⚗️ Trait Combiner</h1> <div style="max-width: 600px; margin: 40px auto; padding: 30px; background: #1a1308; border: 2px solid #c4a040; border-radius: 12px; text-align: center;"> <p style="color: #ddd4b8; font-size: 18px; line-height: 1.6; font-style: italic;">The lab equipment shrinks from your touch. Glass cracks where your nails brush it. Whatever you are now, the combiner will not accept it.</p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #6a3a10; color: #fff; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Leave the Lab</div>">> <<goto "LabTraitAnalysis">> <</link>> </div> </div> <<else>> <div style="background: linear-gradient(180deg, #1a0f0a 0%, #2d1810 50%, #1a0f0a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b35; text-align: center;">⚗️ Trait Combiner</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b35 0%, #c44d20 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b35;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Combine 3 traits to create a transformation. Select traits carefully - some combinations unlock powerful forms! </p> </div> <!-- Failed Combination Message --> <<if $lastCombineFailed>> <div style="background: linear-gradient(135deg, #444 0%, #555 100%); border-radius: 10px; padding: 20px; margin-bottom: 25px; text-align: center; border: 2px solid #ff6b6b;"> <p style="color: #ff6b6b; font-size: 20px; font-weight: bold; margin: 0 0 10px 0;">✗ EXPERIMENT FAILED</p> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0;"><<print $lastCombineMessage>></p> <p style="color: #51cf66; font-size: 14px; margin: 0;">Your traits have been preserved. This combination has been recorded as incompatible.</p> </div> <<set $lastCombineFailed = false>> <</if>> <!-- Trades Remaining Display --> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #ff6b35; font-size: 16px; margin: 0;">🔄 Trades Remaining Today: <strong><<print $tradesRemainingToday>> / <<print 5 + ($bonusDailyTrades || 0)>></strong></p> </div> <!-- Selected Traits Display --> <div style="background: #1a1a1a; border: 3px solid #ff6b35; border-radius: 10px; padding: 20px; margin-bottom: 25px;"> <h3 style="color: #ff6b35; margin: 0 0 15px 0; text-align: center;">Selected Traits (<<print $combinerSelectedTraits.length>>/3)</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; min-height: 50px;"> <<if $combinerSelectedTraits.length === 0>> <p style="color: #666; margin: 0;">Select 3 traits from the list below</p> <<else>> <<for _i, _trait range $combinerSelectedTraits>> <<capture _i, _trait>> <<link "<div style='background: #2d1810; color: #ff6b35; padding: 10px 15px; border-radius: 8px; display: inline-flex; align-items: center; gap: 10px; cursor: pointer;'><<print _trait>> <span style='color: #888;'>✕</span></div>">> <<run $combinerSelectedTraits.splice(_i, 1)>> <<goto "LabTraitCombiner">> <</link>> <</capture>> <</for>> <</if>> </div> <<if $combinerSelectedTraits.length > 0>> <div style="text-align: center; margin-top: 15px;"> <<link "<span style='color: #888; cursor: pointer;'>Clear All</span>">> <<set $combinerSelectedTraits = []>> <<set $combinerAgeTrait = null>> <<goto "LabTraitCombiner">> <</link>> </div> <</if>> </div> <!-- Color Legend --> <div style="background: #1a1a1a; border: 2px solid #555; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h4 style="color: #888; margin: 0 0 10px 0; text-align: center;">🎨 Trait Colors</h4> <div style="display: flex; flex-wrap: wrap; gap: 15px; justify-content: center; font-size: 13px;"> <span style="color: #ff9800;">🟠 In a recipe</span> <span style="color: #ffeb3b;">🟡 Partial match</span> <span style="color: #4caf50;">🟢 Two traits match</span> <span style="background: linear-gradient(90deg, #ff0000, #ff9800, #ffeb3b, #4caf50, #2196f3, #9c27b0); -webkit-background-clip: text; -webkit-text-fill-color: transparent; font-weight: bold;">🌈 Complete recipe!</span> </div> </div> <!-- Available Traits Selection --> <div style="background: #1a1a1a; border: 2px solid #555; border-radius: 10px; padding: 20px; margin-bottom: 25px;"> <h3 style="color: #ccc; margin: 0 0 15px 0; text-align: center;">Available Traits</h3> <div style="max-height: 300px; overflow-y: auto; display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;"> <<for _trait range _allTraits>> <<capture _trait>> <<set _isSelected = $combinerSelectedTraits.indexOf(_trait.name) !== -1>> <<set _canSelect = $combinerSelectedTraits.length < 3>> <<set _recipeStatus = setup.getTraitRecipeStatus(_trait.name, $combinerSelectedTraits)>> <!-- Determine colors based on recipe status --> <<if _recipeStatus === 'complete'>> <<set _bgColor = 'linear-gradient(90deg, #ff0000, #ff9800, #ffeb3b, #4caf50, #2196f3, #9c27b0)'>> <<set _borderColor = '#fff'>> <<set _textColor = 'white'>> <<set _glowStyle = 'box-shadow: 0 0 15px rgba(255,255,255,0.6), 0 0 30px rgba(255,0,255,0.4); animation: rainbow-glow 2s ease-in-out infinite;'>> <<elseif _recipeStatus === 'twoMatch'>> <<set _bgColor = '#2e7d32'>> <<set _borderColor = '#4caf50'>> <<set _textColor = 'white'>> <<set _glowStyle = 'box-shadow: 0 0 8px rgba(76,175,80,0.5);'>> <<elseif _recipeStatus === 'partialMatch'>> <<set _bgColor = '#f9a825'>> <<set _borderColor = '#ffeb3b'>> <<set _textColor = '#1a1a1a'>> <<set _glowStyle = ''>> <<elseif _recipeStatus === 'inRecipe'>> <<set _bgColor = '#e65100'>> <<set _borderColor = '#ff9800'>> <<set _textColor = 'white'>> <<set _glowStyle = ''>> <<else>> <<set _bgColor = '#2a2a2a'>> <<set _borderColor = '#555'>> <<set _textColor = '#888'>> <<set _glowStyle = ''>> <</if>> <<if _isSelected>> <div style="background: #ff6b35; color: white; padding: 8px 12px; border-radius: 5px; border: 2px solid #ff8c42;"> <<print _trait.name>> <span style="font-size: 11px; opacity: 0.8;">(<<print _trait.type>>)</span> ✓ </div> <<elseif _canSelect>> <<set _styleStr = "background: " + _bgColor + "; color: " + _textColor + "; padding: 8px 12px; border-radius: 5px; cursor: pointer; border: 2px solid " + _borderColor + "; " + _glowStyle>> <<link `"<div style='" + _styleStr + "'>" + _trait.name + " <span style='font-size: 11px; opacity: 0.8;'>(" + _trait.type + ")</span></div>"`>> <<run $combinerSelectedTraits.push(_trait.name)>> <<goto "LabTraitCombiner">> <</link>> <<else>> <div style="background: #222; color: #555; padding: 8px 12px; border-radius: 5px; border: 2px solid #333;"> <<print _trait.name>> <span style="font-size: 11px;">(<<print _trait.type>>)</span> </div> <</if>> <</capture>> <</for>> </div> </div> <!-- Age Trait Add-on (optional, alongside 3-trait combination) --> <<set _hasYouthful = $physicalTraits.includes("Youthful") && !$combinerSelectedTraits.includes("Youthful")>> <<set _hasMature = $physicalTraits.includes("Mature") && !$combinerSelectedTraits.includes("Mature")>> <<set _currentAge = $appearance.age || "Adult">> <<set _canUseYouthful = _hasYouthful && _currentAge === "Mature Adult">> <<set _canUseMature = _hasMature && _currentAge === "Adult">> <div style="background: #1a1a1a; border: 2px solid #9b59b6; border-radius: 10px; padding: 20px; margin-bottom: 25px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0; text-align: center;">🔮 Age Add-on (Optional)</h3> <p style="color: #aaa; font-size: 13px; text-align: center; margin: 0 0 15px 0;">Add a Youthful or Mature trait to your combination to also change your age during the transformation. The trait will be consumed.</p> <<if $combinerAgeTrait>> <!-- Show selected age trait with remove option --> <div style="text-align: center;"> <<link "<div style='background: #9b59b6; color: white; padding: 10px 20px; border-radius: 8px; display: inline-flex; align-items: center; gap: 10px; cursor: pointer;'>🔮 <<print $combinerAgeTrait>> → <<if $combinerAgeTrait === \"Youthful\">>Adult<<else>>Mature Adult<</if>> <span style='color: #ddd;'>✕</span></div>">> <<set $combinerAgeTrait = null>> <<goto "LabTraitCombiner">> <</link>> </div> <<else>> <div style="display: flex; flex-wrap: wrap; gap: 15px; justify-content: center;"> <!-- Youthful → Adult --> <<if _canUseYouthful>> <<link "<div style='background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); color: white; padding: 10px 18px; border-radius: 8px; cursor: pointer; font-weight: bold; text-align: center; min-width: 160px;'>✨ Youthful → Adult</div>">> <<set $combinerAgeTrait = "Youthful">> <<goto "LabTraitCombiner">> <</link>> <<elseif _hasYouthful>> <div style="background: #333; color: #666; padding: 10px 18px; border-radius: 8px; text-align: center; min-width: 160px; cursor: not-allowed;">✨ Youthful<br><span style="font-size: 12px;">Already Adult</span></div> <<else>> <div style="background: #222; color: #444; padding: 10px 18px; border-radius: 8px; text-align: center; min-width: 160px; cursor: not-allowed;">✨ Youthful<br><span style="font-size: 12px;">Not available</span></div> <</if>> <!-- Mature → Mature Adult --> <<if _canUseMature>> <<link "<div style='background: linear-gradient(135deg, #8e44ad 0%, #6c3483 100%); color: white; padding: 10px 18px; border-radius: 8px; cursor: pointer; font-weight: bold; text-align: center; min-width: 160px;'>✨ Mature → Mature Adult</div>">> <<set $combinerAgeTrait = "Mature">> <<goto "LabTraitCombiner">> <</link>> <<elseif _hasMature>> <div style="background: #333; color: #666; padding: 10px 18px; border-radius: 8px; text-align: center; min-width: 160px; cursor: not-allowed;">✨ Mature<br><span style="font-size: 12px;">Already Mature Adult</span></div> <<else>> <div style="background: #222; color: #444; padding: 10px 18px; border-radius: 8px; text-align: center; min-width: 160px; cursor: not-allowed;">✨ Mature<br><span style="font-size: 12px;">Not available</span></div> <</if>> </div> <</if>> </div> <!-- Combine Button --> <div style="text-align: center; margin-bottom: 25px;"> <<if $combinerSelectedTraits.length === 3>> <<set _isBlacklisted = setup.hasFailedCombination($combinerSelectedTraits)>> <<if _isBlacklisted>> <div style="background: #333; color: #888; padding: 15px 40px; border-radius: 8px; display: inline-block;"> ❌ This combination has already been tried and failed </div> <<elseif $tradesRemainingToday <= 0>> <div style="background: #333; color: #888; padding: 15px 40px; border-radius: 8px; display: inline-block;"> No trades remaining today </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #ff6b35 0%, #ff8c42 100%); color: white; padding: 15px 40px; border-radius: 8px; font-weight: bold; font-size: 18px; display: inline-block; cursor: pointer; box-shadow: 0 4px 15px rgba(255,107,53,0.4);'>⚗️ Combine Traits</div>">> <<if setup.canCombineTap()>> <!-- Store pre-transformation body stats for description variations --> <<set $preTransformChest = $bodyParts.chest || "medium">> <<set $preTransformButt = $bodyParts.butt || "medium">> <<set $preTransformGenitals = $bodyParts.genitals || "vagina">> <<set $preTransformGender = $bodyParts.gender || "female">> <<set $preTransformAge = $appearance.age || "Adult">> <<set $lastCombineResult = setup.attemptTraitCombination($combinerSelectedTraits)>> <<if $lastCombineResult.consumed>> <<set $tradesRemainingToday -= 1>> <</if>> <<if $lastCombineResult.success>> <!-- Remove source traits --> <<for _trait range $combinerSelectedTraits>> <<run $physicalTraits.delete(_trait)>> <<run $mentalTraits.delete(_trait)>> <<run $skills.delete(_trait)>> <</for>> <!-- Apply age add-on if selected --> <<if $combinerAgeTrait>> <<run $physicalTraits.delete($combinerAgeTrait)>> <<if $combinerAgeTrait === "Youthful">> <<set $appearance.age = "Adult">> <<elseif $combinerAgeTrait === "Mature">> <<set $appearance.age = "Mature Adult">> <</if>> <<set $ageTransformApplied = $combinerAgeTrait>> <<set $combinerAgeTrait = null>> <<else>> <<set $ageTransformApplied = null>> <</if>> <<set $combinerSourceTraits = $combinerSelectedTraits.slice()>> <<if $ageTransformApplied>> <<run $combinerSourceTraits.push($ageTransformApplied + " (Age)")>> <</if>> <<set $combinerSelectedTraits = []>> <!-- All combinations are full transformations --> <!-- Cerberus uses its own volcano statue cutscene (applies the form and ejects to the Volcano) instead of the generic lab reveal. --> <<if $lastCombineResult.newTrait === "Cerberus">> <<goto "CerberusTransformation">> <<else>> <<if $lastCombineResult.newTrait === "Half-Dragon Gyaru">><<goto "DragonGyaruTransformation">><<else>><<run setup.applyFullTransformation($lastCombineResult.newTrait)>> <<goto "LabTransformationScene">><</if>> <</if>> <<else>> <!-- Failed combination - stay on combiner page with message --> <<set $lastCombineFailed = true>> <<set $lastCombineMessage = $lastCombineResult.message>> <<set $combinerSelectedTraits = []>> <<set $combinerAgeTrait = null>> <<goto "LabTraitCombiner">> <</if>> <</if>> <</link>> <</if>> <<else>> <div style="background: #333; color: #888; padding: 15px 40px; border-radius: 8px; display: inline-block;"> Select 3 traits to combine </div> <</if>> </div> <!-- Discovered Recipes Section --> <<set _discoveredRecipes = setup.getDiscoveredRecipes().filter(function(r){ return r && Array.isArray(r.traits); })>> <<if _discoveredRecipes && _discoveredRecipes.length > 0>> <style> @keyframes rainbow-border { 0% { border-color: #ff0000; box-shadow: 0 0 15px #ff0000; } 16% { border-color: #ff9800; box-shadow: 0 0 15px #ff9800; } 33% { border-color: #ffeb3b; box-shadow: 0 0 15px #ffeb3b; } 50% { border-color: #4caf50; box-shadow: 0 0 15px #4caf50; } 66% { border-color: #2196f3; box-shadow: 0 0 15px #2196f3; } 83% { border-color: #9c27b0; box-shadow: 0 0 15px #9c27b0; } 100% { border-color: #ff0000; box-shadow: 0 0 15px #ff0000; } } .discovered-recipe { animation: rainbow-border 3s linear infinite; border-width: 3px; border-style: solid; } </style> <div style="background: #1a1a1a; border-radius: 10px; padding: 20px; margin-bottom: 25px;"> <h3 style="background: linear-gradient(90deg, #ff0000, #ff9800, #ffeb3b, #4caf50, #2196f3, #9c27b0); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin: 0 0 15px 0; text-align: center; font-size: 20px;">🌈 Discovered Recipes (<<print _discoveredRecipes.length>>)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px;"> <<for _recipe range _discoveredRecipes>> <div class="discovered-recipe" style="background: linear-gradient(135deg, #1a0a2e 0%, #2d1052 100%); border-radius: 10px; padding: 15px;"> <h4 style="color: #fff; margin: 0 0 10px 0; text-align: center;">✨ <<print _recipe.result>></h4> <div style="display: flex; flex-wrap: wrap; gap: 5px; justify-content: center;"> <<for _t range _recipe.traits>> <span style="background: #3a2060; color: #e0b0ff; padding: 4px 8px; border-radius: 4px; font-size: 12px;"><<print _t>></span> <</for>> </div> </div> <</for>> </div> </div> <</if>> <!-- Research Notes Link --> <<set _failedCount = ($failedTraitCombinations && $failedTraitCombinations.length) || 0>> <div style="text-align: center; margin-bottom: 25px;"> <<link "<div style='display: inline-block; background: #2a2a2a; color: #888; padding: 10px 20px; border-radius: 8px; border: 2px solid #555; cursor: pointer;'>📓 Research Notes (Tested Combinations: <<print _failedCount>>)</div>">> <<goto "LabResearchNotes">> <</link>> </div> <!-- Return Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Laboratory</div>">> <<set $combinerSelectedTraits = []>> <<goto "RoomLaboratory">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a0f0a 0%, #2d1810 50%, #1a0f0a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #888; text-align: center;">📓 Research Notes</h1> <div style="padding: 20px; background: linear-gradient(135deg, #444 0%, #333 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #555;"> <p style="color: #aaa; font-size: 16px; margin: 0; text-align: center; font-style: italic;"> A record of all trait combinations you've tested that didn't produce a transformation. </p> </div> <!-- Failed Combinations List --> <<if $failedTraitCombinations && $failedTraitCombinations.length > 0>> <div style="background: #1a1a1a; border: 2px solid #555; border-radius: 10px; padding: 20px; margin-bottom: 25px;"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">❌ Failed Combinations (<<print $failedTraitCombinations.length>>)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 10px; max-height: 400px; overflow-y: auto;"> <<for _i, _combo range $failedTraitCombinations>> <<set _traits = _combo.split("|")>> <div style="background: #2a2a2a; padding: 12px; border-radius: 8px; border-left: 4px solid #ff6b6b;"> <div style="display: flex; flex-wrap: wrap; gap: 5px;"> <<for _t range _traits>> <span style="background: #3a2020; color: #ff9999; padding: 4px 8px; border-radius: 4px; font-size: 12px;"><<print _t>></span> <</for>> </div> </div> <</for>> </div> </div> <<else>> <div style="background: #1a1a1a; border: 2px solid #555; border-radius: 10px; padding: 30px; margin-bottom: 25px; text-align: center;"> <p style="color: #666; font-size: 16px; margin: 0;">No failed combinations recorded yet. Start experimenting!</p> </div> <</if>> <!-- Return Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #ff6b35; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Trait Combiner</div>">> <<goto "LabTraitCombiner">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "LabTransformationScene">> <!-- Store pre-transformation body stats for description variations --> <<set _preChest = $preTransformChest || $bodyParts.chest || "medium">> <<set _preButt = $preTransformButt || $bodyParts.butt || "medium">> <<set _preGenitals = $preTransformGenitals || $bodyParts.genitals || "vagina">> <<set _preGender = $preTransformGender || "female">> <<set _preAge = $preTransformAge || $appearance.age || "Adult">> <<set _transformName = $lastCombineResult.newTrait>> <<set _transform = setup.fullTransformations[_transformName]>> <!-- Determine gradient colors based on transformation type --> <<set _gradientTop = "#0d0015">> <<set _gradientMid = "#1a0a2e">> <<set _gradientPeak = "#2d1052">> <<set _accentColor = "#ff00ff">> <<set _bannerGradient = "linear-gradient(135deg, #8b00ff 0%, #ff00ff 50%, #8b00ff 100%)">> <<if _transformName === "Voluptuous Succubus" || (_transformName === "Succubus" || _transformName === "Voluptuous Succubus") || _transformName === "Imp" || _transformName === "Cerberus">> <!-- Demonic - Deep crimson/hellfire --> <<set _gradientTop = "#1a0505">> <<set _gradientMid = "#3d0a0a">> <<set _gradientPeak = "#6b1515">> <<set _accentColor = "#ff3333">> <<set _bannerGradient = "linear-gradient(135deg, #8b0000 0%, #ff4444 50%, #8b0000 100%)">> <<elseif _transformName === "Werecat" || _transformName === "Werewolf" || _transformName === "Werebunny" || _transformName === "Werefox" || _transformName === "Weresheep" || _transformName === "Hucow">> <!-- Were-creatures - Earthy brown/amber --> <<set _gradientTop = "#0d0805">> <<set _gradientMid = "#2a1a0a">> <<set _gradientPeak = "#4d3319">> <<set _accentColor = "#ffa500">> <<set _bannerGradient = "linear-gradient(135deg, #8b4513 0%, #ffa500 50%, #8b4513 100%)">> <<elseif _transformName === "Trophy Wife" || _transformName === "Gym Bunny" || _transformName === "E-Girl" || _transformName === "Punk" || _transformName === "Gyaru">> <!-- Aesthetic - Pink/glamour --> <<set _gradientTop = "#1a050d">> <<set _gradientMid = "#3d0a1f">> <<set _gradientPeak = "#6b1542">> <<set _accentColor = "#ff69b4">> <<set _bannerGradient = "linear-gradient(135deg, #c71585 0%, #ff69b4 50%, #c71585 100%)">> <<elseif _transformName === "Siren" || _transformName === "Living Doll">> <!-- Supernatural - Ethereal blue/cyan --> <<set _gradientTop = "#050d1a">> <<set _gradientMid = "#0a1f3d">> <<set _gradientPeak = "#154266">> <<set _accentColor = "#00ffff">> <<set _bannerGradient = "linear-gradient(135deg, #1e90ff 0%, #00ffff 50%, #1e90ff 100%)">> <<elseif _transformName === "Dominatrix" || _transformName === "Slut" || _transformName === "Himbo">> <!-- Dominant/Corruption - Deep purple/violet --> <<set _gradientTop = "#0d0515">> <<set _gradientMid = "#1f0a3d">> <<set _gradientPeak = "#3d1566">> <<set _accentColor = "#9932cc">> <<set _bannerGradient = "linear-gradient(135deg, #4b0082 0%, #9932cc 50%, #4b0082 100%)">> <</if>> <div style="background: linear-gradient(180deg, <<print _gradientTop>> 0%, <<print _gradientMid>> 30%, <<print _gradientPeak>> 50%, <<print _gradientMid>> 70%, <<print _gradientTop>> 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <!-- Header with glow effect --> <div style="text-align: center; margin-bottom: 30px;"> <h1 style="color: <<print _accentColor>>; font-size: 42px; margin: 0; text-shadow: 0 0 30px <<print _accentColor>>, 0 0 60px <<print _accentColor>>;">🔮 TRANSFORMATION 🔮</h1> </div> <!-- Result Banner - Trade Result Style --> <div style="background: <<print _bannerGradient>>; padding: 30px; border-radius: 15px; margin-bottom: 30px; box-shadow: 0 0 40px rgba(139,0,255,0.6), inset 0 0 30px rgba(255,255,255,0.1); border: 2px solid <<print _accentColor>>; text-align: center;"> <p style="color: #eeccff; margin: 0 0 10px 0; font-size: 18px; text-transform: uppercase; letter-spacing: 2px;">You have become</p> <p style="color: white; font-size: 48px; font-weight: bold; margin: 0; text-shadow: 0 0 20px rgba(255,255,255,0.8), 0 4px 8px rgba(0,0,0,0.5);"><<print _transformName>></p> <<if _transform && _transform.description>> <p style="color: #ddaaff; font-style: italic; margin: 15px 0 0 0; font-size: 16px;"><<print _transform.description>></p> <</if>> </div> <!-- Transformation Story Section --> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16162a 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; border: 2px solid <<print _accentColor>>; box-shadow: 0 4px 20px rgba(0,0,0,0.5);"> <h2 style="color: <<print _accentColor>>; margin: 0 0 20px 0; text-align: center; font-size: 24px;">✨ The Transformation Begins ✨</h2> <div style="color: #ddd; font-size: 17px; line-height: 2; text-align: justify;"> <p>You stand completely naked and alone in the center of the laboratory's transformation chamber. The heavy doors have sealed behind you, leaving you in private isolation as the cool air raises goosebumps across your bare skin. <em>No one can see me here... no one can interrupt. It's just me and the machine.</em> The apparatus hums to life around you, arcane energies swirling as the traits you've sacrificed are consumed in brilliant flashes of light.</p> <p>A tingling sensation begins at your extremities - your fingers, your toes, the tips of your ears - then rapidly spreads inward. Your breath catches as the magic seeps into every fiber of your being. <em>Oh god, I can feel it... it's actually happening!</em> Your naked body is completely vulnerable and exposed to the transformative energies. Alone in this chamber, with no one watching, you're free to experience every sensation fully.</p> <<print setup.getFullTransformationText(_transformName, true, _preGender)>> <<if $ageTransformApplied>> <<if $ageTransformApplied === "Youthful">> <p>As the other transformations settle into your body, a deeper, slower change begins to ripple through you. The youthful softness in your face starts to shift - your jawline defining itself with elegant precision, your cheekbones rising into sharper, more striking angles. <em>I look... older? No... more mature. More refined.</em> You watch in the chamber's reflection as your features lose their innocent roundness, replaced by a confident, alluring beauty that radiates experience. Your skin remains smooth and flawless, but now it stretches over the body of someone who knows exactly what they want. Your hips settle with a subtle new weight, your posture straightening with an unconscious authority. <em>I feel... powerful. Like I've grown into myself.</em> The transformation burns through your muscles, filling them with a quiet, assured strength. Your eyes catch the light differently now - deeper, knowing, with a smoldering intensity that wasn't there before. You run your hands down your transformed naked body, feeling every curve and line with fresh appreciation. <em>This is what it feels like to be in my prime... and god, does it feel good.</em> The youthful energy that once defined you has been consumed by the machine, replaced by the magnetic allure of someone in the full bloom of adulthood.</p> <<elseif $ageTransformApplied === "Mature">> <<set _genderForAge = (_transform && _transform.genderLock) ? _transform.genderLock : $gender>> <<if _genderForAge === "male">> <p>As the other changes ripple through your body, a slow, smoldering heat begins to spread from deep within your core. Your mature trait is consumed in a flash of golden light, and the energy seeps into every fiber of your being. <em>Something's changing... something deeper than the rest.</em> Your jawline sharpens with rugged distinction, a shadow of distinguished stubble darkening your face. Fine lines appear at the corners of your eyes - not signs of weakness, but marks of experience, of confidence, of a man who has lived and conquered. Your shoulders broaden imperceptibly, your chest settling with a powerful, commanding presence. <em>I feel... incredible. Like I've finally become the man I was meant to be.</em> Silver threads weave through your hair at the temples, giving you a devastatingly handsome salt-and-pepper look. Your muscles don't shrink - they become denser, more defined, the body of a man in his absolute prime. Your voice resonates deeper in your chest. When you catch your reflection, the person staring back exudes raw, magnetic authority - a total DILF who commands attention without trying. <em>God... I look like I could make anyone weak in the knees just by walking into a room.</em> Your transformed body radiates the irresistible confidence and sexual magnetism of a mature man who knows exactly what he's doing.</p> <<else>> <p>As the other changes ripple through your body, a slow, smoldering heat begins to spread from deep within your core. Your mature trait is consumed in a flash of golden light, and the energy seeps into every fiber of your being. <em>Something's changing... something deeper than the rest.</em> Your features shift with exquisite subtlety - your cheekbones becoming more prominent, your lips fuller and more inviting, fine laugh lines appearing at the corners of your eyes that somehow make you even more beautiful. Your body doesn't age - it ripens. Your hips widen ever so slightly, settling into lush, motherly curves that scream fertility and sensuality. <em>Oh god... I can feel myself becoming...</em> Your breasts feel heavier, sitting with a perfect, gravity-defying fullness. Your skin takes on a warm, golden glow - the radiance of a woman in her absolute prime. You run your hands over your transformed body and every touch sends shivers of pleasure through you. When you catch your reflection, the woman staring back is devastatingly gorgeous - a total MILF with bedroom eyes, curves that could stop traffic, and an aura of confident sensuality that's almost intoxicating. <em>I look like every fantasy come to life... I look like I could seduce anyone I wanted.</em> Your transformed body radiates the irresistible allure of a mature woman who knows exactly what she wants and exactly how to get it.</p> <</if>> <</if>> <</if>> </div> </div> <!-- Body Changes Section with Pre-transformation variations --> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16162a 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; border: 2px solid <<print _accentColor>>; box-shadow: 0 4px 20px rgba(0,0,0,0.5);"> <h2 style="color: <<print _accentColor>>; margin: 0 0 25px 0; text-align: center; font-size: 24px;">🌀 Your Body Transforms 🌀</h2> <div style="color: #ccc; font-size: 16px; line-height: 1.9;"> <!-- Chest Transformation with pre-size variations --> <<if _transform && _transform.setsChest>> <div style="background: rgba(255,107,157,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ff6b9d;"> <p style="margin: 0;"><strong style="color: #ff6b9d; font-size: 18px;">💗 Chest</strong></p> <p style="margin: 10px 0 0 0;"> <<if _preChest === "flat" || _preChest === "flat masculine">> Your eyes drift down to your flat, bare chest as an unfamiliar warmth begins to bloom beneath the skin. Your nipples stiffen instantly, becoming incredibly sensitive as the magic concentrates there. <em>Something's happening... I can feel it starting...</em> <<if _transform.setsChest === "gigantic">> You gasp sharply as flesh begins to push outward from nothing - tiny bumps at first, then rapidly swelling mounds that grow larger with each heartbeat. <em>Oh fuck... they're growing! They won't stop growing!</em> Your hands fly to your chest instinctively, but you can't contain the growth. The flesh overflows between your fingers as your breasts surge larger and larger, the skin stretching taut over the expanding tissue. Waves of intense, building pleasure radiate from your swelling chest - each pulse of growth sending another surge of ecstasy through your body. Your nipples drag across your palms, sending electric jolts of pleasure that make your knees buckle. <em>Oh god... oh god yes!</em> The pleasure builds and builds with every inch of growth, becoming almost overwhelming as your breasts reach their massive final size. A loud, uncontrollable moan escapes you as the growth completes, leaving you trembling with residual pleasure. <em>So heavy... so sensitive... that felt incredible!</em> The weight becomes staggering as they finally settle into absolutely massive, wobbling tits that hang heavy from your chest. Your once-flat chest now sports gigantic breasts that bounce and sway with your ragged breathing, nipples fat and achingly erect. <em>I can't believe these are mine now...</em> <<elseif _transform.setsChest === "giant">> A moan escapes your lips as flesh pushes outward, small mounds appearing where there was nothing before. Pleasure blooms in your chest, growing stronger with each inch of expansion. You watch, transfixed, as they swell larger and larger, the skin growing warm and sensitive. <em>It feels so good... the bigger they get, the better it feels!</em> Your hands can't help but cup the growing masses as they expand into giant, heavy breasts, waves of pleasure washing through you with each surge of growth. The growth slows, leaving you panting and flushed with lingering pleasure, enormous tits that feel impossibly sensitive hanging from your chest. <<elseif _transform.setsChest === "huge">> You watch in fascination as flesh pushes outward from your flat chest, forming soft mounds that rapidly swell. The sensation is intoxicating - a warm, pleasurable pressure that grows stronger as your breasts expand larger and larger. <em>Mmm... it feels amazing!</em> They expand into huge, heavy orbs, pleasure pulsing through you with each wave of growth. Your hands cup them to feel their incredible new weight and sensitivity, the pleasure leaving you breathless. <<elseif _transform.setsChest === "large">> Warmth spreads across your chest as flesh begins to form, soft mounds pushing outward and swelling steadily. A pleasant, building pleasure accompanies the growth, making you bite your lip. <em>That feels nice...</em> Large, shapely breasts take shape, leaving you with a satisfied warmth from the growth. <<elseif _transform.setsChest === "medium">> A gentle warmth spreads through your chest as flesh begins to swell outward, forming modest but noticeable breasts. A soft tingle of pleasure accompanies the growth, leaving you with beautifully shaped medium breasts that feel wonderfully sensitive to every sensation. <<else>> Transformative energy washes over your bare chest, reshaping the flesh into a <<print _transform.setsChest>> form. Every nerve ending seems to come alive as your new shape settles. <</if>> <<elseif _preChest === "small">> Your small, bare breasts begin to tingle intensely, the nipples hardening to stiff peaks as magic floods through the sensitive tissue. <<if _transform.setsChest === "gigantic">> A deep moan tears from your throat as your modest breasts surge outward with explosive growth. Intense, overwhelming pleasure floods through your chest - waves of ecstasy that grow stronger with every inch of expansion. <em>Oh god! Oh fuck yes!</em> You can feel every millimeter of expansion, the pleasure building and building as the flesh stretches and swells. Your small breasts rapidly become massive, then enormous, then truly gigantic, each surge of growth sending another spike of almost unbearable pleasure through your trembling body. <em>Don't stop! It feels so good!</em> The weight is staggering, pulling you forward as these impossible tits finally stop growing, the final wave of pleasure leaving you gasping and weak-kneed. Your nipples have become thick and incredibly sensitive, and you can feel the heavy masses wobbling and bouncing with every breath. From small to absolutely massive - your new gigantic tits dominate your naked body completely. <em>That was incredible!</em> <<elseif _transform.setsChest === "giant">> The tingling intensifies into waves of pleasurable pressure as your breasts begin to swell. Strong pleasure pulses through your chest with each surge of growth. <em>Mmm... bigger!</em> You watch your reflection in the chamber's polished walls, seeing your modest chest rapidly expand. Larger and larger they grow, pushing outward in waves of warm, sensitive flesh until giant breasts hang heavy from your chest. The growth is intoxicating to feel and watch, leaving you flushed with lingering pleasure. <<elseif _transform.setsChest === "huge">> The small mounds push outward eagerly, flesh swelling with each pulse of magic. Pleasure accompanies the growth, making you moan softly. <em>Yes... growing!</em> You cup them instinctively, feeling them overflow your hands as they grow into huge, attention-commanding breasts. They bounce heavily with your excited breathing, nipples stiff and tingling. <<elseif _transform.setsChest === "large">> Your breasts swell pleasantly larger, filling with warm, sensitive flesh. A gentle pleasure accompanies the growth. You feel them pushing outward, growing heavier, until large, generous handfuls sit proudly on your chest. They feel wonderful - fuller, heavier, more sensitive than before. <<elseif _transform.setsChest === "flat" || _transform.setsChest === "flat masculine">> A strange sensation washes over your small breasts as they begin to tingle and shrink. The flesh recedes, drawing back into your body until your chest is completely smooth and flat. Your nipples shrink to small, masculine nubs. <<else>> The transformation magic washes through your bare breasts, reshaping them into a <<print _transform.setsChest>> size. Every sensation is heightened as the changes complete. <</if>> <<elseif _preChest === "medium">> Your medium-sized breasts pulse with transformative energy, the bare flesh tingling as magic saturates every cell. Your nipples stiffen to hard points, incredibly sensitive. <<if _transform.setsChest === "gigantic">> <em>They're... growing?!</em> You cry out in shocked pleasure as your breasts explode with growth. The flesh surges outward, swelling larger and larger as you watch in disbelief. Medium becomes large, large becomes huge, and still they keep growing. <em>They won't stop! How big are they going to get?!</em> Your hands try to contain them but fail utterly as the flesh overflows, expanding into absolutely gigantic tits that hang heavy and wobbling from your chest. The weight is incredible, pulling you forward. Your nipples have become thick, fat peaks of sensitivity. Every breath makes these massive mounds bounce and sway. <em>I went from average to... to THIS!</em> <<elseif _transform.setsChest === "giant">> <em>I can feel them swelling!</em> The flesh swells outward hungrily, your breasts expanding with waves of pleasurable pressure. You feel them growing heavier, pushing further from your body as they become giant, attention-demanding curves. The transformation leaves you panting, cupping your new massive tits in wonder. <em>So much bigger than before... they're huge!</em> <<elseif _transform.setsChest === "huge">> <em>They're getting bigger...</em> Your breasts swell substantially, the flesh pushing outward as they grow into huge, heavy orbs. The sensation of growth is incredible - a warm, tingling pressure that leaves you breathless. Your new huge tits feel incredible as they settle into their new size. <em>Such a nice upgrade...</em> <<elseif _transform.setsChest === "small">> <em>Wait... they're shrinking?</em> A cooling sensation spreads through your breasts as they begin to tingle and diminish. The flesh recedes, drawing inward as you watch them become smaller and smaller. <em>I'm losing them...</em> When the sensation fades, only small, perky mounds remain. Though smaller, they feel incredibly sensitive. <em>They're so tiny now... but they tingle so much!</em> <<elseif _transform.setsChest === "flat" || _transform.setsChest === "flat masculine">> <em>Something's wrong... they're getting smaller!</em> Your breasts tingle with an odd cooling sensation as they begin to shrink. The flesh pulls inward, becoming smaller and smaller. <em>They're disappearing!</em> You watch as your breasts vanish entirely, leaving your chest completely flat and smooth. <em>They're... gone. I'm completely flat now.</em> <<else>> Transformative energy reshapes your bare chest into a <<print _transform.setsChest>> form. Every nerve sings with heightened sensitivity. <</if>> <<elseif _preChest === "large" || _preChest === "huge" || _preChest === "giant" || _preChest === "gigantic">> Your already impressive bare breasts pulse with energy, the heavy flesh tingling as magic concentrates in the sensitive tissue. Your stiff nipples ache with anticipation. <<if _transform.setsChest === "gigantic" && _preChest !== "gigantic">> <em>Even bigger?! They're already so big!</em> You moan deeply as your already ample breasts surge with new growth. The heavy flesh swells even more, growing impossibly huge as you struggle to support their increasing weight. <em>So heavy... they're so incredibly heavy now!</em> Larger and larger until absolutely gigantic tits hang from your chest, nipples thick and hypersensitive. The weight is staggering, these massive mounds bouncing and swaying dramatically with every movement. <em>I thought they were big before... now they're absolutely massive!</em> <<elseif _transform.setsChest === "giant" && (_preChest === "large" || _preChest === "huge")>> <em>They're still growing!</em> The flesh continues to swell, pushing outward as your breasts expand into truly giant proportions. You feel the increasing weight, the heightened sensitivity as they settle into their new, impressive size. <em>Even more than before...</em> <<elseif _transform.setsChest === "small" || _transform.setsChest === "flat">> <em>Wait... what's happening? They're shrinking!</em> A strange cooling sensation spreads through your heavy breasts as they begin to diminish. The flesh recedes steadily, the weight disappearing as they become smaller and smaller. <em>All that weight... it's just vanishing!</em> The heavy masses draw inward until only <<print _transform.setsChest>> breasts remain. The sudden lightness feels strange after bearing such weight. <em>I used to have so much... now there's barely anything left.</em> <<else>> The magic reshapes your impressive breasts, the flesh shifting and settling into a <<print _transform.setsChest>> size. <</if>> <<else>> Transformative energy washes over your bare chest, reshaping the flesh into <<print _transform.setsChest>> breasts. Every sensation is magnified as the changes complete. <</if>> </p> </div> <</if>> <!-- Butt Transformation with pre-size variations --> <<if _transform && _transform.setsButt>> <div style="background: rgba(255,215,0,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ffd700;"> <p style="margin: 0;"><strong style="color: #ffd700; font-size: 18px;">🍑 Rear</strong></p> <p style="margin: 10px 0 0 0;"> <<if _preButt === "flat" || _preButt === "flat masculine">> Your flat, bare backside begins to tingle and warm, the skin prickling with sensation as magic concentrates there. <em>I feel something back there...</em> <<if _transform.setsButt === "gigantic">> You feel an intense pressure building deep in your glutes as flesh begins to form from nothing. Your flat ass starts to push outward, each cheek swelling and growing with alarming speed. <em>It's getting bigger... so much bigger!</em> Intense pleasure surges through your lower body with each inch of growth, waves of ecstasy building stronger and stronger as your ass becomes more and more massive. You reach back to feel the growth - soft, warm flesh ballooning under your fingertips, pleasure pulsing through you with every touch. <em>Oh god... the bigger it gets, the better it feels!</em> Larger and larger they swell, each cheek becoming a massive globe of jiggling flesh, the pleasure becoming almost overwhelming. A moan escapes you as the growth finally completes, leaving you trembling. <em>I had nothing before... and now I have all of this!</em> From completely flat to massively thick - your new enormous rear jiggles and sways behind you. <<elseif _transform.setsButt === "giant">> Flesh begins to form and swell, your flat cheeks pushing outward dramatically. Strong waves of pleasure pulse through your lower body as they fill out, growing larger and larger. You moan as they expand into giant, grabbable globes, each surge of growth sending another spike of pleasure through you. <em>Mmm... so good!</em> Your new giant ass bounces heavily as you shift your weight. <<elseif _transform.setsButt === "huge">> Warm flesh pushes outward as your flat rear swells into huge, bouncy cheeks. Pleasure pulses through you with each wave of growth, making you bite your lip. <em>That feels really nice!</em> You can feel them growing behind you, soft and round and incredibly sensitive. They wobble enticingly with every movement. <<elseif _transform.setsButt === "large">> Your backside fills out nicely, flesh forming and swelling into a plump, shapely rear. A pleasant warmth and gentle pleasure accompanies the growth. The new curves feel soft and warm, bouncing gently as you shift. <<else>> Transformative energy reshapes your bare rear into a <<print _transform.setsButt>> form. The new flesh tingles with sensitivity. <</if>> <<elseif _preButt === "small">> Your small, bare rear begins to pulse with warmth, the modest cheeks tingling intensely. <em>What's happening back there?</em> <<if _transform.setsButt === "gigantic">> Your eyes widen as your small cheeks begin to swell rapidly. <em>It's growing! My ass is actually growing!</em> Intense pleasure floods through your lower body, growing stronger with every inch of expansion. The flesh expands outward, growing and growing as you feel your ass becoming enormous behind you. You reach back, feeling the soft masses balloon under your palms - larger than your hands, larger than anything you've felt - each touch sending another wave of ecstasy through you. <em>It won't stop growing! It feels so fucking good!</em> They don't stop until you have a truly gigantic ass that bounces and wobbles dramatically with every breath, the final surge of growth leaving you moaning and trembling. <em>From practically nothing to... to THIS!</em> From modest to absolutely massive. <<elseif _transform.setsButt === "giant">> <em>I can feel it swelling!</em> Strong pleasure pulses through you as the cheeks expand dramatically, flesh swelling outward in waves of ecstatic growth. <em>Oh yes... bigger!</em> Your small rear becomes giant, attention-grabbing globes that bounce heavily as you shift your naked body. <em>So much bigger now... that felt amazing!</em> <<elseif _transform.setsButt === "huge">> <em>It's getting bigger!</em> Pleasure accompanies the growth as the flesh expands eagerly, your small rear swelling into huge, bouncy cheeks. <em>Mmm... yes!</em> You feel them pushing outward, growing heavier and rounder behind you. <em>Such a nice, big upgrade!</em> <<elseif _transform.setsButt === "large">> <em>It's filling out!</em> Your backside swells pleasantly with a gentle warmth, the modest cheeks growing into a shapely, large rear that bounces softly. <em>Much better than before!</em> <<else>> Transformative energy reshapes your bare rear into <<print _transform.setsButt>>. The new shape tingles with sensitivity. <</if>> <<elseif _preButt === "large" || _preButt === "huge" || _preButt === "giant" || _preButt === "gigantic">> Your already generous bare backside pulses with energy, the soft cheeks tingling as magic floods through them. <<if _transform.setsButt === "gigantic" && _preButt !== "gigantic">> <em>It's getting even bigger!</em> The already impressive flesh swells even larger, each cheek ballooning outward. Pleasure pulses through you with each surge of growth, stronger and stronger as your ass becomes more massive. You feel your ass growing heavier, rounder, bigger and bigger. <em>I already had a big ass... now it's becoming enormous! And it feels incredible!</em> The growth continues, waves of pleasure washing over you, until you have a truly gigantic rear that dominates your lower half. The massive cheeks bounce and wobble dramatically with every tiny movement. <em>So much jiggle! That felt so good!</em> <<elseif _transform.setsButt === "flat" || _transform.setsButt === "small">> <em>Wait... it's shrinking?!</em> A cooling sensation spreads through your plump cheeks as they begin to diminish. The soft flesh recedes, drawing inward as you feel the familiar bounce and jiggle fading. <em>All that ass... it's disappearing!</em> The flesh continues to shrink until only a <<print _transform.setsButt>> rear remains. <em>It's all gone... I used to have so much back there!</em> The sudden absence of the weight and bounce feels strange. <<else>> The magic reshapes your generous rear, the flesh settling into a <<print _transform.setsButt>> size. <</if>> <<else>> Transformative energy washes over your bare rear, reshaping it into a <<print _transform.setsButt>> form. <</if>> </p> </div> <</if>> <!-- Genital Transformation with pre-type variations --> <<if _transform && _transform.setsGenitals>> <div style="background: rgba(255,107,53,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ff6b35;"> <p style="margin: 0;"><strong style="color: #ff6b35; font-size: 18px;">🔥 Intimate Areas</strong></p> <p style="margin: 10px 0 0 0;"> <<if _preGenitals.includes("penis") || _preGenitals.includes("cock")>> <!-- Starting with penis --> Intense heat floods through your exposed groin, centering on your naked cock. You look down, watching as the magic begins its intimate work on your most sensitive area. <em>What's happening down there...?</em> <<if _transform.setsGenitals.includes("vagina") || _transform.setsGenitals.includes("pussy")>> <<if _preGenitals.includes("big") || _preGenitals.includes("huge")>> Your impressive cock throbs once, then begins to shrink before your eyes. <em>It's... it's shrinking!</em> The thick shaft becomes smaller and smaller, but instead of discomfort, waves of intense pleasure surge through your groin - pleasure unlike anything you've felt before. You moan loudly as your manhood pulls inward - shorter, thinner, each moment of transformation sending another spike of ecstasy through your entire body. <em>Oh god... oh fuck... it feels so good!</em> The pleasure intensifies to an almost unbearable peak as the head begins to split, flesh parting and folding into delicate, glistening lips. Your whole body shudders with overwhelming pleasure as the transformation completes, leaving you gasping and trembling. Where your proud cock once hung, soft folds now glisten with arousal. <em>I have a... I'm a... that was incredible!</em> You feel the emptiness inside you - a void that aches to be filled. Your new pussy pulses with need, already dripping wet. <em>It feels so empty inside... I need something to fill me...</em> <<else>> Your exposed cock tingles intensely, then begins to pull inward. <em>No way... it's actually changing!</em> Immense pleasure floods through your groin as the transformation begins - far more intense than anything you've experienced before. You cry out, knees weakening as your shaft shrinks away, each moment of change sending waves of ecstasy through your entire body. <em>Oh god yes! It feels amazing!</em> The skin parts and folds, sensitive tissues forming into delicate pink petals, the pleasure building to an almost unbearable crescendo. A loud, uncontrollable moan escapes you as your new pussy completes its formation, your whole body shuddering with the intensity of it. The fresh folds are already slick with arousal. <em>That was... that was incredible!</em> The emptiness inside you is strange but exciting - a hungry void between your thighs. <em>I can feel the air on it... so sensitive...</em> <</if>> <<elseif _transform.setsGenitals.includes("big penis")>> <em>It's... growing?!</em> Your shaft throbs and swells with each heartbeat, growing thicker and longer before your eyes. <em>Bigger... it's getting bigger!</em> You can feel the blood rushing in, the flesh expanding. Your balls grow heavier, churning with new potency as your cock becomes impressively, almost intimidatingly large. The veins pulse visibly along your enhanced length. <em>Look at the size of it now!</em> <<elseif _transform.setsGenitals === "both">> Your cock throbs with the magic but remains, changing subtly as new sensations bloom below your balls. <em>What's happening down there... below my cock?</em> You feel flesh parting, sensitive folds forming beneath your shaft. When the magic fades, you look down to find you now have both - a throbbing cock standing proud above a wet, sensitive pussy. <em>I have... both?! I can feel both of them!</em> You can feel both, incredibly aware of each set of genitals. <<else>> Transformative magic washes over your exposed genitals, the flesh tingling and reshaping into: <<print _transform.setsGenitals>>. <</if>> <<elseif _preGenitals.includes("vagina") || _preGenitals.includes("pussy")>> <!-- Starting with vagina --> Intense heat pulses through your exposed pussy, the sensitive folds tingling and clenching involuntarily. You look down at your most intimate area as the magic begins its work. <em>Something's happening... I can feel it changing!</em> <<if _transform.setsGenitals.includes("penis") || _transform.setsGenitals.includes("cock")>> <<if _preGenitals.includes("tight")>> Your tight little pussy clenches one last time, the walls squeezing against nothing. Then the sensitive folds begin to close, sealing together, and suddenly immense pleasure explodes through your groin - more intense than any orgasm you've ever experienced. <em>OH GOD!</em> You cry out as flesh pushes outward from your mound, every nerve ending on fire with ecstasy. A cock emerges from where your entrance once was - first a small nub, then rapidly growing, each inch of growth sending another wave of overwhelming pleasure through your trembling body. <em>It feels... it feels incredible!</em> The new shaft hardens with arousal, rising from your groin as you gasp and moan uncontrollably. You can feel it twitching, throbbing with your heartbeat. <em>I have a cock now... I can feel it pulsing! That was the most amazing thing I've ever felt!</em> The sensation of having a cock is overwhelming - heavy, sensitive, powerful. <<elseif _preGenitals.includes("loose")>> Your well-used pussy tingles strangely as the folds begin to shrink and close. The stretched entrance tightens, then seals, and suddenly immense pleasure floods through your entire body. <em>FUCK! Oh fuck yes!</em> You moan loudly as flesh pushes outward, waves of ecstasy pulsing through you with each moment of transformation. A thick cock grows from your former entrance, the shaft hardening and lengthening, every inch of growth sending another spike of overwhelming pleasure through your trembling body. <em>So good... it feels so fucking good!</em> The sensation is unlike anything - your new cock twitches and throbs with eager sensitivity. <em>I can feel every heartbeat in it... that was incredible!</em> <<else>> Your pussy clenches involuntarily, then begins to change. The sensitive folds seal shut as pressure builds from within, and suddenly immense, overwhelming pleasure explodes through your groin. <em>OH GOD YES!</em> You cry out uncontrollably as flesh pushes outward, forming into a shaft that rapidly hardens. Every moment of the transformation sends waves of ecstasy through your entire body, pleasure more intense than anything you've experienced before. <em>It feels amazing! Don't stop!</em> Your new cock stands erect, twitching and throbbing, the final surge of growth leaving you gasping and trembling. <em>I have a cock... a real cock! I can feel it throbbing! That was the best thing I've ever felt!</em> The sensation of having a cock - the weight, the sensitivity, the pulsing need - is overwhelming and intoxicating. <</if>> <<elseif _transform.setsGenitals.includes("tight")>> <em>It's getting tighter!</em> Your inner walls clench and tighten, muscles strengthening as the magic reshapes you. When it fades, you have a deliciously tight pussy that grips at nothing, the sensitive walls aching to squeeze around something. <em>So tight now... I can feel every little movement inside me!</em> Every clench sends sparks of pleasure through you. <<elseif _transform.setsGenitals.includes("loose")>> <em>It's... relaxing? Opening up?</em> The walls of your pussy relax and loosen, the entrance becoming soft and welcoming. The sensation is strange but arousing - a ready, eager openness between your thighs. <em>It feels so open now... so ready...</em> <<elseif _transform.setsGenitals === "both">> Your pussy remains but pressure builds on your mound above it. <em>Something's growing above my pussy!</em> Flesh extends outward as a cock grows above your wet folds. When the magic fades, you have both - a stiff cock standing proud above your dripping pussy. <em>I have both! A cock AND a pussy! I can feel them both!</em> You can feel each separately, incredibly aware of both sets of sensations. <<else>> Transformative magic washes over your exposed intimate areas, reshaping them into: <<print _transform.setsGenitals>>. <</if>> <<else>> Intense magic floods your exposed intimate areas, tingling and reshaping the sensitive flesh into: <<print _transform.setsGenitals>>. <</if>> </p> </div> <</if>> <!-- Gender Identity --> <<if _transform && _transform.genderLock && _preGender !== _transform.genderLock>> <div style="background: rgba(155,89,182,0.1); padding: 20px; border-radius: 10px; border-left: 4px solid #9b59b6;"> <p style="margin: 0;"><strong style="color: #9b59b6; font-size: 18px;">✨ Identity</strong></p> <p style="margin: 10px 0 0 0;"> As the physical changes complete, something deeper begins to shift. The magic seeps into your mind, into your very sense of self. <em>My thoughts... they feel different...</em> Thoughts and memories subtly realign. The way you see yourself, the way you feel in your transformed naked body - it all changes. <em>I'm not... I was never really...</em> You are no longer <<print _preGender>>. Looking at your transformed reflection, touching your changed body, you feel completely, utterly <strong><<print _transform.genderLock>></strong>. <em>This is who I am. This is who I've always been.</em> This is who you were always meant to be. This body, this identity - it feels right. It feels like home. </p> </div> <</if>> </div> </div> <!-- Full Body Image Display - After Identity Section --> <!-- Build the image path directly based on transformation name --> <<set _ageStr = $appearance.age === "Mature Adult" ? "Mature" : "Adult">> <<set _genderRaw = _transform.genderLock || "female">> <<set _genderStr = (_genderRaw === "male" || _genderRaw === "Male") ? "Male" : "Female">> <<set _transformFileName = String(_transformName).replace(/ /g, "")>> <<if !$imageSettings>><<set $imageSettings = {imagesEnabled: true, eroticImagesEnabled: true}>><</if>> <<if $imageSettings.eroticImagesEnabled !== false>> <!-- Special case: Voluptuous Succubus uses a single image file --> <<if _transformName === "Voluptuous Succubus">> <<set _fullBodyImageHTML = '<div style="text-align: center; margin-bottom: 30px;"><h3 style="color: #b19cd9; margin-bottom: 20px;">Your New Form</h3><div style="display: inline-block; padding: 5px; background: linear-gradient(135deg, #b19cd9 0%, #8b7ab8 100%); border-radius: 12px; border: 3px solid #b19cd9; box-shadow: 0 0 20px rgba(177, 156, 217, 0.4);"><img src="Images/Transformation/Large_Succubus.webp" style="max-width: 450px; max-height: 600px; border-radius: 8px; display: block;" onerror="this.parentElement.parentElement.style.display=\'none\';"></div></div>'>> <<else>> <<set _fullBodyImageHTML = '<div style="text-align: center; margin-bottom: 30px;"><h3 style="color: #b19cd9; margin-bottom: 20px;">Your New Form</h3><div style="display: inline-block; padding: 5px; background: linear-gradient(135deg, #b19cd9 0%, #8b7ab8 100%); border-radius: 12px; border: 3px solid #b19cd9; box-shadow: 0 0 20px rgba(177, 156, 217, 0.4);"><img src="Images/Transformation/' + _transformFileName + '_' + _genderStr + '_' + _ageStr + '_FullBody.webp" style="max-width: 450px; max-height: 600px; border-radius: 8px; display: block;" onerror="this.parentElement.parentElement.style.display=\'none\';"></div></div>'>> <</if>> <<print _fullBodyImageHTML>> <</if>> <!-- Traits Consumed --> <div style="background: #2a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #dc3545;"> <h3 style="color: #dc3545; margin: 0 0 15px 0; text-align: center;">📤 Traits Consumed</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<for _trait range $combinerSourceTraits>> <span style="background: #3d1a1a; color: #ff6b6b; padding: 8px 15px; border-radius: 8px; font-size: 15px;"><<print _trait>></span> <</for>> </div> </div> <!-- Traits Gained --> <<if _transform>> <div style="background: #1a2a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #28a745;"> <h3 style="color: #28a745; margin: 0 0 15px 0; text-align: center;">📥 Traits Gained</h3> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<if _transform.grantsPhysical && _transform.grantsPhysical.length > 0>> <<for _trait range _transform.grantsPhysical>> <span style="background: #1a3d1a; color: #51cf66; padding: 8px 15px; border-radius: 8px; font-size: 15px;"><<print _trait>></span> <</for>> <</if>> <<if _transform.grantsMental && _transform.grantsMental.length > 0>> <<for _trait range _transform.grantsMental>> <span style="background: #1a1a3d; color: #9b59b6; padding: 8px 15px; border-radius: 8px; font-size: 15px;"><<print _trait>></span> <</for>> <</if>> </div> </div> <</if>> <!-- Trades Remaining --> <div style="background: #1a1a1a; border-radius: 10px; padding: 15px; margin-bottom: 30px; text-align: center;"> <p style="color: #ff6b35; margin: 0;">Trades Remaining Today: <strong><<print $tradesRemainingToday>> / <<print 5 + ($bonusDailyTrades || 0)>></strong></p> </div> <!-- Return Button Only - No try another --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 15px rgba(102,126,234,0.4);'>← Return to Laboratory</div>">> <<goto "RoomLaboratory">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _home = setup.getCurrentHome()>> <<set _tankType = $fishTankType || "small">> <<set _returnPassage = _tankType === "small" ? "RoomSmallFishTank" : "RoomMediumFishTank">> <<if !$homeFishTanks>><<set $homeFishTanks = {}>><</if>> <<if !$homeFishTanks[_home]>><<set $homeFishTanks[_home] = {}>><</if>> <<if !$homeFishTanks[_home][_tankType]>> <<set _defaultCapacity = _tankType === "small" ? 5 : 15>> <<set $homeFishTanks[_home][_tankType] = {fish: [], capacity: _defaultCapacity}>> <</if>> <<set _tank = $homeFishTanks[_home][_tankType]>> <<set _capacity = _tank.capacity>> <<set _spotsLeft = _capacity - _tank.fish.length>> <<set _allowedRarities = setup.smallTankAllowedRarities>> <<set $lastLocation = "FishTankTransfer">> <div style="background: linear-gradient(180deg, #0a1628 0%, #1a3a5c 50%, #0a1628 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #1e90ff; text-align: center;">🐟 Fish Transfer</h1> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #51cf66; font-size: 18px; margin: 0;">Select fish to transfer. <span style="color: #ffd700;"><<print _spotsLeft>> spots remaining.</span></p> <p style="color: #ff6b6b; font-size: 14px; margin: 5px 0 0 0;">⚠️ Legendary and Mythical fish require the Mansion Aquarium</p> </div> <h3 style="color: #51cf66;">Your Inventory (<<print $fishInventory ? $fishInventory.length : 0>> fish)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 30px;"> <<if $fishInventory && $fishInventory.length > 0>> <<for _i, _fish range $fishInventory>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <<set _canAdd = _allowedRarities.includes(_fish.rarity)>> <div style="border: 3px solid <<print _rarityColor>>; border-radius: 10px; background: #2a2a2a; padding: 15px; text-align: center;"> <<if _fish.icon && _fish.icon.indexOf("Images/") === 0>> <img @src="_fish.icon" style="width: 48px; height: 48px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 2em;">🐟</span> <<else>> <div style="font-size: 2em;"><<print _fish.icon || "🐟">></div> <</if>> <p style="color: <<print _rarityColor>>; margin: 5px 0; font-weight: bold;"><<print _fish.name>></p> <p style="font-size: 12px; color: #888; text-transform: capitalize; margin: 0 0 10px 0;"><<print _fish.rarity>></p> <p style="font-size: 12px; color: #51cf66; margin: 0 0 10px 0;">Value: $<<print _fish.basePrice>></p> <<if !_canAdd>> <span style="color: #ff6b6b; font-size: 12px;">Needs Mansion Aquarium</span> <<elseif _spotsLeft > 0>> <<capture _i, _fish, _tankType, _home>> <<link "<div style='background: #51cf66; color: white; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 12px;'>Add to Tank</div>">> <<run $homeFishTanks[_home][_tankType].fish.push(clone(_fish))>> <<run $fishInventory.splice(_i, 1)>> <<goto "FishTankTransfer">> <</link>> <</capture>> <<else>> <span style="color: #ff6b6b; font-size: 12px;">Tank full</span> <</if>> </div> <</for>> <<else>> <p style="color: #888;">No fish in your inventory.</p> <</if>> </div> <h3 style="color: #1e90ff;">Fish in Tank (<<print _tank.fish.length>>/<<print _capacity>>)</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 15px; margin-bottom: 30px;"> <<if _tank.fish.length > 0>> <<for _i, _fish range _tank.fish>> <<set _rarityColor = setup.fishRarityColors[_fish.rarity] || "#9e9e9e">> <div style="border: 3px solid <<print _rarityColor>>; border-radius: 10px; background: #1a3a5c; padding: 15px; text-align: center;"> <<if _fish.icon && _fish.icon.indexOf("Images/") === 0>> <img @src="_fish.icon" style="width: 48px; height: 48px; image-rendering: pixelated;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 2em;">🐟</span> <<else>> <div style="font-size: 2em;"><<print _fish.icon || "🐟">></div> <</if>> <p style="color: <<print _rarityColor>>; margin: 5px 0; font-weight: bold;"><<print _fish.name>></p> <p style="font-size: 12px; color: #90caf9; text-transform: capitalize; margin: 0 0 10px 0;"><<print _fish.rarity>></p> <<capture _i, _fish, _tankType, _home>> <<link "<div style='background: #ff6b6b; color: white; padding: 6px; border-radius: 4px; cursor: pointer; font-size: 12px;'>Remove</div>">> <<run $fishInventory.push(clone(_fish))>> <<run $homeFishTanks[_home][_tankType].fish.splice(_i, 1)>> <<goto "FishTankTransfer">> <</link>> <</capture>> </div> <</for>> <<else>> <p style="color: #888;">No fish in tank yet.</p> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>Done</div>">> <<goto _returnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomHomeOffice">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <<if !$homeOfficeIncomeDay || $homeOfficeIncomeDay !== $dayNumber>> <<set _incomeCollected = false>> <<else>> <<set _incomeCollected = true>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomHomeOffice")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #2c3e50; text-align: center;">💼 Home Office</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2c3e50;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A professional workspace for managing your affairs. </p> </div> <div style="background: #2a4a2a; padding: 20px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #51cf66; font-size: 18px; margin: 0;">✓ Passive Income: $10/day</p> <p style="color: #888; font-size: 14px; margin: 10px 0 0 0;">Remote freelance work and side projects generate steady income automatically at the start of each day.</p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 20px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 15px 0;">💰 How It Works</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Your home office allows you to do remote freelance work. Income is deposited automatically each morning.</p> <p style="color: #51cf66; font-size: 14px; margin: 0;">• Each office earns $10/day</p> <p style="color: #51cf66; font-size: 14px; margin: 5px 0 0 0;">• Income arrives at the start of each new day</p> <p style="color: #51cf66; font-size: 14px; margin: 5px 0 0 0;">• No action required!</p> </div> </div> <div style="text-align: center;"> <<link "<div style='background: #2c3e50; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomProfessionalGym">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <<if !$proGymHoursToday || $lastProGymDay !== $dayNumber>> <<set $proGymHoursToday = 0>> <<set $lastProGymDay = $dayNumber>> <</if>> <<set _hoursRemaining = 3 - $proGymHoursToday>> <<set _trainerBonus = $personalTrainer ? 1.5 : 1>> <<set _cerberusBonus = $physicalTraits.includes("Cerberus") ? 4 : ($physicalTraits.includes("Gym Bunny") ? 4 : ($physicalTraits.includes("Himbo") ? 2 : 1))>> <<set _strGain = Math.floor(2 * _trainerBonus * _cerberusBonus)>> <<set _dexGain = Math.floor(2 * _trainerBonus * _cerberusBonus)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomProfessionalGym")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #e74c3c; text-align: center;">🏆 Professional Gym</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e74c3c;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Professional-grade equipment for serious training. Double stat gains! </p> </div> <div style="display: flex; gap: 20px; flex-wrap: wrap; justify-content: center; margin-bottom: 25px;"> <div style="background: #2a2a2a; padding: 15px 25px; border-radius: 10px;"> <p style="color: #ffd700; font-size: 16px; margin: 0;">⏰ Training Time: <strong><<print _hoursRemaining>> / 3 hours</strong></p> </div> <<if $personalTrainer>> <div style="background: #2a4a2a; padding: 15px 25px; border-radius: 10px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 16px; margin: 0;">✓ Personal Trainer Active (+50% gains!)</p> </div> <</if>> <<if _cerberusBonus > 1>> <div style="background: linear-gradient(135deg, #4a1a2a 0%, #3e0a1e 100%); padding: 15px 25px; border-radius: 10px; border: 2px solid #ff6b6b;"> <p style="color: #ff6b6b; font-size: 16px; margin: 0;">✓ <<if $physicalTraits.includes("Cerberus")>>Cerberus<<elseif $physicalTraits.includes("Gym Bunny")>>Gym Bunny<<else>>Himbo<</if>>: <<print _cerberusBonus>>x Workout Gains</p> </div> <</if>> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #e74c3c; margin: 0 0 15px 0;">💪 Strength Training</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Build muscle with weights and machines. (+<<print _strGain>> Strength)</p> <<if _hoursRemaining > 0>> <<link "<div style='background: #e74c3c; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Train Strength (1 hour)</div>">> <<set $proGymHoursToday += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<run advanceTime(60)>> <<set $stats.strength = Math.max($stats.strength, Math.min($statMaxCaps.strength, $stats.strength + _strGain))>> <<goto "RoomProfessionalGym">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Too tired to train more today</div> <</if>> </div> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #f39c12; margin: 0 0 15px 0;">🏃 Agility Training</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Improve coordination and speed. (+<<print _dexGain>> Dexterity)</p> <<if _hoursRemaining > 0>> <<link "<div style='background: #f39c12; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Train Dexterity (1 hour)</div>">> <<set $proGymHoursToday += 1>> <<if $physicalTraits.includes("Gym Bunny")>> <<run setup.recordGymWorkout()>> <<run setup.removeDebuff("compulsion")>> <<run setup.addBuff("satisfied", 480)>> <<run setup.achievements.unlock("tireless_trainer")>> <</if>> <<run advanceTime(60)>> <<set $stats.dexterity = Math.max($stats.dexterity, Math.min($statMaxCaps.dexterity, $stats.dexterity + _dexGain))>> <<goto "RoomProfessionalGym">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 12px; border-radius: 6px; text-align: center;">Too tired to train more today</div> <</if>> </div> </div> <!-- Personal Trainer Section --> <div style="border: 3px solid #ffd700; border-radius: 15px; padding: 25px; background: #2a2a2a; margin-bottom: 25px; text-align: center;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🏅 Personal Trainer</h2> <<if $personalTrainer>> <p style="color: #51cf66; font-size: 16px; margin-bottom: 15px;">✓ You have a personal trainer! (+50% to all gains)</p> <p style="color: #888; font-size: 14px; margin-bottom: 15px;">Cost: $20,000/month (billed automatically)</p> <<link "<div style='background: #c0392b; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>Cancel Trainer</div>">> <<set $personalTrainer = false>> <<goto "RoomProfessionalGym">> <</link>> <<else>> <p style="color: #ccc; font-size: 16px; margin-bottom: 15px;">Hire a personal trainer for +50% gains on all exercises!</p> <p style="color: #ffd700; font-size: 18px; font-weight: bold; margin-bottom: 15px;">$20,000 / month</p> <<if $money >= 20000>> <<link "<div style='background: #51cf66; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>Hire Trainer</div>">> <<set $money -= 20000>> <<set $personalTrainer = true>> <<goto "RoomProfessionalGym">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 12px 30px; border-radius: 8px; display: inline-block;">Not enough money</div> <</if>> <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomStreamingStudio">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <!-- Room Painting Display --> <<set _roomPainting = setup.roomPaintings.getPainting("RoomStreamingStudio")>> <<if _roomPainting>> <div class="room-painting-display"> <div class="room-painting-frame"> <img @src="setup.paintingStorage.getImage(_roomPainting)" @alt="_roomPainting.title" class="room-painting-image"> </div> <p class="room-painting-title">"<<print _roomPainting.title>>"</p> </div> <</if>> <h1 style="color: #9146ff; text-align: center;">📺 Streaming Studio</h1> <div style="padding: 20px; background: linear-gradient(135deg, #9146ff 0%, #7c3aed 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9146ff;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Professional streaming setup with top-tier equipment. </p> </div> <div style="background: #2a4a2a; padding: 20px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #51cf66; font-size: 18px; margin: 0;">✓ Active Bonus: +15% to all stream categories</p> <p style="color: #888; font-size: 14px; margin: 10px 0 0 0;">Applies to viewer count and engagement.</p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #9146ff; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #9146ff; margin: 0 0 15px 0;">🎙️ Equipment</h3> <p style="color: #ccc; font-size: 14px;">Professional microphone, ring light, green screen, dual monitors, and streaming PC.</p> </div> <div style="border: 3px solid #667eea; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #667eea; margin: 0 0 15px 0;">📊 Stream Here</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Access your streaming platforms with studio bonus.</p> <<if $hasLaptop>> <<link "<div style='background: #667eea; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Go to Computer</div>">> <<set $streamingFromStudio = true>> <<set $laptopReturnLocation = "RoomStreamingStudio">> <<goto "UseLaptop">> <</link>> <<else>> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-style: italic;'>No Laptop</div> <</if>> </div> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<set $streamingFromStudio = false>><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomHomeTheater">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #c0392b; text-align: center;">🎬 Home Theater</h1> <div style="padding: 20px; background: linear-gradient(135deg, #c0392b 0%, #922b21 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #c0392b;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A luxurious theater room with surround sound and plush seating. </p> </div> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 30px; background: #2a2a2a; text-align: center; margin-bottom: 25px;"> <h2 style="color: #ffd700; margin: 0 0 15px 0;">🚧 Coming Soon</h2> <p style="color: #ccc;">Movie night features with NPCs will be added in a future update!</p> <p style="color: #888; font-size: 14px;">Requires level 2+ relationship with NPC</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomDungeon">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #0d0d0d; min-height: 100vh; padding: 20px;"> <div style="background: rgba(30,30,30,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #8b0000; text-align: center;">⛓️ Dungeon</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2c3e50 0%, #1a252f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8b0000;"> <p style="color: #ccc; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A private space for exploring your darker desires. </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #8b0000; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #8b0000; margin: 0 0 15px 0;">👑 Domination Practice</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Practice taking control.</p> <<link "<div style='background: #8b0000; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Practice (1 hour)</div>">> <<run advanceTime(60)>> <<set $sexualSkills.domination.exp = ($sexualSkills.domination.exp || 0) + 20>> <<replace "#dom-result">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 1px solid #8b0000;"> <p style="color: #8b0000; margin: 0;">You feel more commanding. +20 Domination XP</p> </div> <</replace>> <</link>> <span id="dom-result"></span> </div> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🔒 Submission Practice</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Practice letting go.</p> <<link "<div style='background: #9b59b6; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Practice (1 hour)</div>">> <<run advanceTime(60)>> <<set $sexualSkills.submission.exp = ($sexualSkills.submission.exp || 0) + 20>> <<replace "#sub-result">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 1px solid #9b59b6;"> <p style="color: #9b59b6; margin: 0;">You feel more at ease. +20 Submission XP</p> </div> <</replace>> <</link>> <span id="sub-result"></span> </div> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #e83e8c; margin: 0 0 15px 0;">🎭 Roleplay Practice</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Practice different scenarios.</p> <<link "<div style='background: #e83e8c; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Practice (1 hour)</div>">> <<run advanceTime(60)>> <<set $sexualSkills.roleplay.exp = ($sexualSkills.roleplay.exp || 0) + 20>> <<replace "#rp-result">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 1px solid #e83e8c;"> <p style="color: #e83e8c; margin: 0;">Your imagination expands. +20 Roleplay XP</p> </div> <</replace>> <</link>> <span id="rp-result"></span> </div> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 20px; background: #1a1a1a;"> <h3 style="color: #f39c12; margin: 0 0 15px 0;">🔥 Fetish Exploration</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Explore your kinks.</p> <<link "<div style='background: #f39c12; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Practice (1 hour)</div>">> <<run advanceTime(60)>> <<set $sexualSkills.fetishPlay.exp = ($sexualSkills.fetishPlay.exp || 0) + 20>> <<replace "#fetish-result">> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 1px solid #f39c12;"> <p style="color: #f39c12; margin: 0;">New experiences gained. +20 Fetish Play XP</p> </div> <</replace>> <</link>> <span id="fetish-result"></span> </div> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomDanceStudio">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #e83e8c; text-align: center;">💃 Dance Studio</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #c9379d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Mirrored walls and a sprung floor for practice. </p> </div> <div style="background: #2a4a2a; padding: 20px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #51cf66; font-size: 18px; margin: 0;">✓ Active Bonus: +20% Stripper Job Performance</p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 25px;"> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #e83e8c; margin: 0 0 15px 0;">🎵 Rhythm Practice</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Improve your sense of rhythm and movement.</p> <<link "<div style='background: #e83e8c; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Practice Dancing (1 hour)</div>">> <<run advanceTime(60)>> <<set $sexualSkills.rhythm.exp = ($sexualSkills.rhythm.exp || 0) + 20>> <<replace "#dance-result">> <div style="background: #2a4a2a; padding: 15px; border-radius: 8px; margin-top: 15px;"> <p style="color: #51cf66; margin: 0;">Your moves are smoother! +20 Rhythm XP</p> </div> <</replace>> <</link>> <span id="dance-result"></span> </div> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 20px; background: #2a2a2a;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🎪 Pole Practice</h3> <p style="color: #ccc; font-size: 14px; margin-bottom: 15px;">Work on your pole dancing skills.</p> <<link "<div style='background: #9b59b6; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Practice Pole (1 hour)</div>">> <<run advanceTime(60)>> <<set $sexualSkills.rhythm.exp = ($sexualSkills.rhythm.exp || 0) + 15>> <<set $stats.dexterity += 1>> <<replace "#pole-result">> <div style="background: #2a4a2a; padding: 15px; border-radius: 8px; margin-top: 15px;"> <p style="color: #51cf66; margin: 0;">Great workout! +15 Rhythm XP, +1 Dexterity</p> </div> <</replace>> <</link>> <span id="pole-result"></span> </div> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Return Home</div>">><<goto _returnPassage>><</link>> </div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoomRenovationManager">> <<set _home = setup.getCurrentHome()>> <<set _returnPassage = $renovateReturnPassage || _home>> <!-- Initialize renovation tracking for this home if needed --> <<if !$homeRenovations>><<set $homeRenovations = {}>><</if>> <<if !$homeRenovations[_home]>><<set $homeRenovations[_home] = {small: [], medium: [], large: []}>><</if>> <!-- Define room counts per home type --> <<set _roomCounts = { "PlayerSuburbanHome": {small: 1, medium: 1, large: 0}, "PlayerExpensiveHome": {small: 2, medium: 2, large: 1}, "PlayerModernMansion": {small: 4, medium: 3, large: 2} }>> <<set _counts = _roomCounts[_home] || {small: 0, medium: 0, large: 0}>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #f39c12; text-align: center;">🔧 Room Renovation Manager</h1> <div style="padding: 20px; background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f39c12;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> Customize your home with specialized rooms. </p> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #ffd700; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <!-- SMALL ROOMS --> <<if _counts.small > 0>> <h2 style="color: #51cf66;">🏠 Small Rooms (<<print $homeRenovations[_home].small.length>>/<<print _counts.small>> Renovated)</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _i = 0; _i < _counts.small; _i++>> <<capture _i>> <<set _renovatedRoom = $homeRenovations[_home].small[_i] || null>> <<if _renovatedRoom>> <<set _roomData = setup.roomRenovations.small.find(function(r) { return r.id === _renovatedRoom; })>> <div style="border: 3px solid <<print _roomData.color>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: <<print _roomData.color>>; margin: 0 0 10px 0;"><<print _roomData.icon>> <<print _roomData.name>></h3> <p style="font-size: 13px; color: #51cf66; margin: 0 0 10px 0;">✓ <<print _roomData.benefit>></p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Re-Renovate</div>">> <<set $renovateRoomSize = "small">> <<set $renovateRoomIndex = _i>> <<set $renovateReturnPassage = _returnPassage>> <<goto "RoomRenovation">> <</link>> </div> <<else>> <div style="border: 3px solid #51cf66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">🧱 Small Custom Room <<print _i + 1>></h3> <p style="font-size: 14px; color: #888; margin: 0 0 10px 0;">An empty room ready for renovation.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Renovate</div>">> <<set $renovateRoomSize = "small">> <<set $renovateRoomIndex = _i>> <<set $renovateReturnPassage = _returnPassage>> <<goto "RoomRenovation">> <</link>> </div> <</if>> <</capture>> <</for>> </div> <</if>> <!-- MEDIUM ROOMS --> <<if _counts.medium > 0>> <h2 style="color: #ffd700;">🏡 Medium Rooms (<<print $homeRenovations[_home].medium.length>>/<<print _counts.medium>> Renovated)</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _i = 0; _i < _counts.medium; _i++>> <<capture _i>> <<set _renovatedRoom = $homeRenovations[_home].medium[_i] || null>> <<if _renovatedRoom>> <<set _roomData = setup.roomRenovations.medium.find(function(r) { return r.id === _renovatedRoom; })>> <div style="border: 3px solid <<print _roomData.color>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: <<print _roomData.color>>; margin: 0 0 10px 0;"><<print _roomData.icon>> <<print _roomData.name>></h3> <p style="font-size: 13px; color: #51cf66; margin: 0 0 10px 0;">✓ <<print _roomData.benefit>></p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Re-Renovate</div>">> <<set $renovateRoomSize = "medium">> <<set $renovateRoomIndex = _i>> <<set $renovateReturnPassage = _returnPassage>> <<goto "RoomRenovation">> <</link>> </div> <<else>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🧱 Medium Custom Room <<print _i + 1>></h3> <p style="font-size: 14px; color: #888; margin: 0 0 10px 0;">An empty room ready for renovation.</p> <<link "<div style='background: #ffd700; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Renovate</div>">> <<set $renovateRoomSize = "medium">> <<set $renovateRoomIndex = _i>> <<set $renovateReturnPassage = _returnPassage>> <<goto "RoomRenovation">> <</link>> </div> <</if>> <</capture>> <</for>> </div> <</if>> <!-- LARGE ROOMS --> <<if _counts.large > 0>> <h2 style="color: #e74c3c;">🏰 Large Rooms (<<print $homeRenovations[_home].large.length>>/<<print _counts.large>> Renovated)</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _i = 0; _i < _counts.large; _i++>> <<capture _i>> <<set _renovatedRoom = $homeRenovations[_home].large[_i] || null>> <<if _renovatedRoom>> <<set _roomData = setup.roomRenovations.large.find(function(r) { return r.id === _renovatedRoom; })>> <div style="border: 3px solid <<print _roomData.color>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: <<print _roomData.color>>; margin: 0 0 10px 0;"><<print _roomData.icon>> <<print _roomData.name>></h3> <p style="font-size: 13px; color: #51cf66; margin: 0 0 10px 0;">✓ <<print _roomData.benefit>></p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Re-Renovate</div>">> <<set $renovateRoomSize = "large">> <<set $renovateRoomIndex = _i>> <<set $renovateReturnPassage = _returnPassage>> <<goto "RoomRenovation">> <</link>> </div> <<else>> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🧱 Large Custom Room <<print _i + 1>></h3> <p style="font-size: 14px; color: #888; margin: 0 0 10px 0;">An empty room ready for renovation.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Renovate</div>">> <<set $renovateRoomSize = "large">> <<set $renovateRoomIndex = _i>> <<set $renovateReturnPassage = _returnPassage>> <<goto "RoomRenovation">> <</link>> </div> <</if>> <</capture>> <</for>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Home</div>">> <<goto _returnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Jungle")>> <<run $visitedLocations.push("Jungle")>> <</if>> <<set $lastLocation = "Jungle">> <div style="background: #1a1a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #2ecc71; text-align: center;">🌴 Jungle</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Jungle.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Jungle"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1b5e20 0%, #2ecc71 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Dense tropical jungle stretches endlessly in every direction. Massive ferns tower overhead, vines hang like curtains between ancient trees, and the air is thick with humidity and the calls of unseen creatures. Shafts of light barely penetrate the canopy above, casting everything in a green-tinted twilight. </p> </div> <!-- Materials counter (if gathering has started but camp not built) --> <<if $jungleMaterials && $jungleMaterials > 0 && !$jungleCampBuilt>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #8B4513; text-align: center;"> <p style="color: #D2691E; margin: 0; font-size: 16px;">🪵 Gathered Materials: <strong><<print $jungleMaterials>></strong> / 10</p> </div> <</if>> <h2 style="color: #2ecc71;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Explore the Jungle --> <div style="border: 3px solid #27ae60; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #27ae60; margin: 0 0 10px 0;">🌿 Explore the Jungle</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Venture deeper into the dense undergrowth. You might find something interesting... or gather useful materials.</p> <<link "<div style='background: #27ae60; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Explore (30 min)</div>">> <<advancetime 30>> <<goto "JungleExplore">> <</link>> </div> <!-- Mysterious Beam (only if discovered) --> <<if $foundMysteriousBeam>> <div style="border: 3px solid #e1bee7; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(225,190,231,0.2); display: flex; flex-direction: column;"> <h3 style="color: #e1bee7; margin: 0 0 10px 0;">✨ Mysterious Beam</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A strange beam of light pierces the canopy in a distant clearing. It never seems to fade.</p> <<link "<div style='background: linear-gradient(135deg, #9c27b0 0%, #e1bee7 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit the Beam</div>">> <<advancetime 15>> <<goto "MysteriousBeam">> <</link>> </div> <</if>> <!-- Overgrown Ruins (only if discovered) --> <<if $foundRuins>> <div style="border: 3px solid #4a6741; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(74,103,65,0.2); display: flex; flex-direction: column;"> <h3 style="color: #4a6741; margin: 0 0 10px 0;">🏚️ Overgrown Ruins</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Ancient stone structures covered in moss and vine. Something sleeps within.</p> <<link "<div style='background: linear-gradient(135deg, #4a6741 0%, #2d4a28 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Ruins (20 min)</div>">> <<set $ruinsPathOrder = []>> <<advancetime 20>> <<goto "OvergrownRuins">> <</link>> </div> <</if>> <!-- Sunfish Temple (only if discovered, part of the Sunfish Cuff questline) --> <<if $cuffTempleDiscovered>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(201,169,255,0.2); display: flex; flex-direction: column;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🐟 Sunfish Temple</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A weathered temple swallowed by the canopy. Mola carved on every stone. Something is missing from a plinth at its center.</p> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6e4ea8 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Temple (15 min)</div>">> <<advancetime 15>> <<goto "JungleSunfishTemple">> <</link>> </div> <</if>> <!-- Overgrown Lab (only after security disabled) --> <<if $labSecurityDisabled>> <div style="border: 3px solid #8cff66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(140,255,102,0.2); display: flex; flex-direction: column;"> <h3 style="color: #8cff66; margin: 0 0 10px 0;">🧪 Overgrown Lab</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A ruined research station swallowed by the jungle. Its mixing apparatus still hums at the heart of the room.</p> <<link "<div style='background: linear-gradient(135deg, #5a9e3a 0%, #8cff66 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Lab (15 min)</div>">> <<advancetime 15>> <<goto "OvergrownLab">> <</link>> </div> <</if>> <!-- Jungle Camp (only if built) --> <<if $jungleCampBuilt>> <div style="border: 3px solid #8B4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(139,69,19,0.2); display: flex; flex-direction: column;"> <h3 style="color: #D2691E; margin: 0 0 10px 0;">🏕️ Jungle Camp</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Your makeshift shelter in the jungle. A place to rest and regroup.</p> <<link "<div style='background: linear-gradient(135deg, #8B4513 0%, #D2691E 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Camp</div>">> <<goto "JungleCamp">> <</link>> </div> <</if>> <!-- Build Camp (only if enough materials and not yet built) --> <<if $jungleMaterials >= 10 && !$jungleCampBuilt>> <div style="border: 3px solid #ff9800; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255,152,0,0.3); display: flex; flex-direction: column;"> <h3 style="color: #ff9800; margin: 0 0 10px 0;">🔨 Build Camp</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">You have enough materials to build a shelter! (<<print $jungleMaterials>>/10 materials)</p> <<link "<div style='background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Build Camp (60 min)</div>">> <<advancetime 60>> <<goto "JungleBuild">> <</link>> </div> <</if>> </div> <h2 style="color: #2ecc71;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Return to The Nest --> <div style="border: 3px solid #D2691E; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #D2691E; margin: 0 0 10px 0;"> The Nest</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Climb back up to the giant nest above.</p> <<link "<div style='background: #D2691E; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to The Nest</div>">> <<advancetime 30>> <<goto "The Nest">> <</link>> </div> <!-- Hidden Lagoon (only if discovered) --> <<if $discoveredHiddenLagoon>> <div style="border: 3px solid #4dd0e1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(77,208,225,0.2); display: flex; flex-direction: column;"> <h3 style="color: #4dd0e1; margin: 0 0 10px 0;">🌊 Hidden Lagoon</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A still glass water lagoon nestled in the cliffs. Quiet. Beautiful.</p> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel (15 min)</div>">> <<advancetime 15>> <<goto "HiddenLagoon">> <</link>> </div> <</if>> <!-- Path to the Desert --> <div style="border: 3px solid #c2953a; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #c2953a; margin: 0 0 10px 0;">🏜️ The Desert</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A scorched trail leads beyond the jungle treeline to an open expanse of sand and rock.</p> <<set _dHour = Math.floor($timeInMinutes / 60) % 24>> <<if (_dHour >= 6 && _dHour < 12) || (_dHour >= 18 && _dHour < 22)>> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Desert (30 min)</div>">> <<advancetime 30>> <<goto "Desert">> <</link>> <<elseif _dHour >= 12 && _dHour < 18>> <<if $physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton")>> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Desert (30 min)</div>">> <<advancetime 30>> <<goto "Desert">> <</link>> <<else>> <div style="background: #3a2a1a; color: #c2953a; padding: 10px; border-radius: 6px; text-align: center; margin-top: 10px; font-style: italic;">🔥 The midday sun blazes overhead. You'd need some kind of heat tolerance to survive out there right now.</div> <</if>> <<elseif _dHour >= 22 || _dHour < 6>> <<if $physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Automaton")>> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Desert (30 min)</div>">> <<advancetime 30>> <<goto "Desert">> <</link>> <<else>> <div style="background: #1a1a2a; color: #7ba3c9; padding: 10px; border-radius: 6px; text-align: center; margin-top: 10px; font-style: italic;">❄️ The desert is freezing at night. You'd need some kind of cold tolerance to survive out there right now.</div> <</if>> <</if>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Desert")>> <<run $visitedLocations.push("Desert")>> <</if>> <<set $lastLocation = "Desert">> <!-- Time-based passout check --> <<set _hour = Math.floor($timeInMinutes / 60) % 24>> <<set _isDay = _hour >= 12 && _hour < 18>> <<set _isNight = _hour >= 22 || _hour < 6>> <<if !$desertExposureSteps>><<set $desertExposureSteps = 0>><</if>> <<set _hasDesertHeat = setup.skillTree.getEffect("heatImmunity") || $physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Salamander") || $mentalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Automaton")>> <<set _hasDesertCold = setup.skillTree.getEffect("coldImmunity") || $physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow")>> <<if _isDay && !_hasDesertHeat>> <<set $desertExposureSteps += 1>> <<if $desertExposureSteps >= 3>> <<set $desertExposureSteps = 0>> <<goto "DesertPassout">> <</if>> <<elseif _isNight && !_hasDesertCold>> <<set $desertExposureSteps += 1>> <<if $desertExposureSteps >= 3>> <<set $desertExposureSteps = 0>> <<goto "DesertPassout">> <</if>> <<elseif (_isDay && _hasDesertHeat) || (_isNight && _hasDesertCold)>> <<set $desertExposureSteps = 0>> <<else>> <<set $desertExposureSteps = 0>> <</if>> <!-- Desert exposure warnings --> <<if (_isDay && !_hasDesertHeat && $desertExposureSteps === 1) || (_isNight && !_hasDesertCold && $desertExposureSteps === 1)>> <div style="background: #3a2a00; padding: 12px; border-radius: 8px; border: 2px solid #f4a261; margin-bottom: 15px; text-align: center; position: relative; z-index: 5;"> <<if _isDay>> <p style="color: #f4a261; font-size: 15px; font-weight: bold; margin: 0;">🌡️ The relentless sun beats down on you. Your throat is parched and your head throbs. You should find shelter soon.</p> <<else>> <p style="color: #82b1ff; font-size: 15px; font-weight: bold; margin: 0;">❄️ The desert cold bites through your clothing. Your fingers are going numb and your teeth won’t stop chattering. You need warmth soon.</p> <</if>> </div> <<elseif (_isDay && !_hasDesertHeat && $desertExposureSteps === 2) || (_isNight && !_hasDesertCold && $desertExposureSteps === 2)>> <div style="background: #4a1a00; padding: 12px; border-radius: 8px; border: 2px solid #ff0000; margin-bottom: 15px; text-align: center; position: relative; z-index: 5;"> <<if _isDay>> <p style="color: #ff4444; font-size: 16px; font-weight: bold; margin: 0;">🔥 Your vision blurs and your legs feel like lead. The desert heat is consuming you. One more step and you won’t be conscious to take another.</p> <<else>> <p style="color: #4488ff; font-size: 16px; font-weight: bold; margin: 0;">❄️ Your body is shutting down. The cold has seeped into your core. You can barely keep your eyes open. One more step and the desert will claim you.</p> <</if>> </div> <</if>> <style> @keyframes heatShimmer { 0%, 100% { opacity: 0.3; transform: translateY(0px) scaleY(1); } 25% { opacity: 0.5; transform: translateY(-2px) scaleY(1.02); } 50% { opacity: 0.35; transform: translateY(-4px) scaleY(1.04); } 75% { opacity: 0.45; transform: translateY(-1px) scaleY(1.01); } } @keyframes starTwinkle { 0%, 100% { opacity: 0.2; } 50% { opacity: 0.8; } } .desert-heat-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 0%, rgba(255,160,0,0.08) 0%, transparent 70%); pointer-events: none; z-index: 0; animation: heatShimmer 4s ease-in-out infinite; } .desert-night-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 0%, rgba(50,50,120,0.12) 0%, transparent 70%); pointer-events: none; z-index: 0; } </style> <<if _isDay>> <div class="desert-heat-overlay"></div> <<elseif _isNight>> <div class="desert-night-overlay"></div> <</if>> <div style="background: #1a1508; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #c2953a; text-align: center;">🏜️ The Desert</h1> <!-- Location Image (Day/Night Cycle) --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <<set _timeOfDay = getTimeOfDay()>> <<if _timeOfDay === "morning">> <<set _locationImg = "Images/Locations/Desert.webp">> <<elseif _timeOfDay === "afternoon">> <<set _locationImg = "Images/Locations/DesertDay.webp">> <<else>> <<set _locationImg = "Images/Locations/DesertNight.webp">> <</if>> <div style="text-align: center; margin: 20px 0;"> <img @src="_locationImg" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #c2953a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Desert"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #8B6914 0%, #c2953a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #c2953a;"> <<if _isDay>> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> An endless sea of golden sand stretches to the horizon, broken only by jagged rock formations and the bleached bones of long-dead trees. The sun beats down mercilessly, distorting the air with waves of shimmering heat. Every breath feels dry and heavy. </p> <<elseif _isNight>> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The desert is transformed under starlight. Pale dunes glow silver-blue beneath a sky packed with more stars than you've ever seen. The temperature has plummeted, and your breath comes out in thin wisps. The silence is vast, broken only by the occasional hiss of wind across sand. </p> <<elseif _hour >= 6 && _hour < 12>> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Dawn paints the desert in soft golds and pinks. The sand is still cool from the night, and the air carries a brief, pleasant stillness before the heat sets in. Long shadows stretch from the rock formations like dark fingers reaching across the dunes. </p> <<else>> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The sun sinks low, setting the western sky ablaze in deep oranges and crimson. The brutal heat of the day is fading, replaced by a comfortable warmth. The desert takes on a rust-red hue, every dune and stone cast in dramatic relief. </p> <</if>> </div> <h2 style="color: #c2953a;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Explore the Desert --> <div style="border: 3px solid #a07830; border-radius: 10px; padding: 15px; background: #2a2a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #c2953a; margin: 0 0 10px 0;">🏜️ Explore the Desert</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Wander the dunes and rock formations. Who knows what you might find half-buried in the sand.</p> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Explore (30 min)</div>">> <<advancetime 30>> <<goto "DesertExplore">> <</link>> </div> <!-- Stone Tablet (only if discovered) --> <<if $foundStoneTablet>> <div style="border: 3px solid #8B7355; border-radius: 10px; padding: 15px; background: #2a2a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(139,115,85,0.2); display: flex; flex-direction: column;"> <h3 style="color: #d4a76a; margin: 0 0 10px 0;">📜 Stone Tablet</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An ancient weathered tablet covered in mysterious inscriptions. Something about it radiates power.</p> <<link "<div style='background: linear-gradient(135deg, #8B7355 0%, #6B5335 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Examine the Tablet</div>">> <<goto "StoneTablet">> <</link>> </div> <</if>> <!-- Oasis (only if discovered) --> <<if $discoveredOasis>> <div style="border: 3px solid #1abc9c; border-radius: 10px; padding: 15px; background: #1a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(26,188,156,0.2); display: flex; flex-direction: column;"> <h3 style="color: #1abc9c; margin: 0 0 10px 0;">🏝️ Desert Oasis</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A hidden spring-fed pool nestled among the dunes. Fish dart beneath the surface of the crystal-clear water.</p> <<link "<div style='background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit the Oasis (15 min)</div>">> <<advancetime 15>> <<goto "Oasis">> <</link>> </div> <</if>> <<if $discoveredDesertRuins>> <div style="border: 3px solid #c2953a; border-radius: 10px; padding: 15px; background: #2a2010; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(194,149,58,0.2); display: flex; flex-direction: column;"> <h3 style="color: #c2953a; margin: 0 0 10px 0;">🏛️ The Sunken Ruins</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A ring of toppled pillars and buried doorways, half swallowed by the dunes. Older than any story the island still tells.</p> <<link "<div style='background: linear-gradient(135deg, #8B6914 0%, #c2953a 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit the Ruins</div>">> <<goto "DesertRuins">> <</link>> </div> <</if>> <!-- Sandcut Mine --> <div style="border: 3px solid #c2953a; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e0b860; margin: 0 0 10px 0;">🏜 Sandcut Mine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A wind-scoured desert shaft, six floors deep. Topaz and tigers-eye glint among the silver veins. Sand cave-ins are the danger here.</p> <<link "<div style='background: #c2953a; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Sandcut (10 min)</div>">> <<advancetime 10>> <<goto "SandcutMineEntrance">> <</link>> </div> </div> <h2 style="color: #c2953a;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Return to Jungle --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🌴 The Jungle</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Head back through the treeline into the dense jungle.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Jungle (30 min)</div>">> <<advancetime 30>> <<goto "Jungle">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Volcano")>> <<run $visitedLocations.push("Volcano")>> <</if>> <<set $lastLocation = "Volcano">> <!-- Heat tolerance check with grace period --> <<set _hasHeatImmunity = setup.skillTree.getEffect("heatImmunity") || $physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Salamander") || $mentalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Automaton")>> <<if _hasHeatImmunity>> <<set $volcanoHeatSteps = 0>> <<else>> <<set $volcanoHeatSteps += 1>> <<if $volcanoHeatSteps >= 3>> <<set $volcanoHeatSteps = 0>> <<goto "VolcanoPassout">> <</if>> <</if>> <!-- Heat warning --> <<if !_hasHeatImmunity && $volcanoHeatSteps === 1>> <div style="background: #4a1a00; padding: 12px; border-radius: 8px; border: 2px solid #ff5722; margin-bottom: 15px; text-align: center; position: relative; z-index: 5;"> <p style="color: #ff8a65; font-size: 15px; font-weight: bold; margin: 0;">🌡️ The searing heat presses against your skin. Sweat drips from every pore. You need to leave soon or the volcano will claim you.</p> </div> <<elseif !_hasHeatImmunity && $volcanoHeatSteps === 2>> <div style="background: #5a0a00; padding: 12px; border-radius: 8px; border: 2px solid #ff0000; margin-bottom: 15px; text-align: center; position: relative; z-index: 5;"> <p style="color: #ff4444; font-size: 16px; font-weight: bold; margin: 0;">🔥 Your vision swims. The air scorches your lungs with every breath. One more step and you won’t be walking out of here.</p> </div> <</if>> <style> @keyframes lavaGlow { 0%, 100% { opacity: 0.3; } 50% { opacity: 0.5; } } @keyframes emberFloat { 0% { transform: translateY(0px); opacity: 0.6; } 50% { transform: translateY(-3px); opacity: 0.8; } 100% { transform: translateY(0px); opacity: 0.6; } } .volcano-heat-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 100%, rgba(255,87,34,0.08) 0%, transparent 70%); pointer-events: none; z-index: 0; animation: lavaGlow 4s ease-in-out infinite; } </style> <div class="volcano-heat-overlay"></div> <div style="background: #1a0a00; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #ff5722; text-align: center;">🌋 The Volcano</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Volcano.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #ff5722; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Volcano"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #bf360c 0%, #e64a19 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff5722;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> A massive volcanic peak dominates the landscape, its slopes streaked with black basalt and rust-red stone. Rivers of molten lava trace glowing orange veins down the mountainside, pooling in cracks and crevices that hiss with heat. The air shimmers, thick with sulfur and ash, and every breath burns slightly. </p> </div> <h2 style="color: #ff5722;">Volcano</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Explore the Volcano --> <div style="border: 3px solid #e64a19; border-radius: 10px; padding: 15px; background: #2a1a0a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff5722; margin: 0 0 10px 0;">🌋 Explore the Volcano</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Venture into the volcanic terrain. Lava flows, obsidian fields, sulfurous vents, and strange discoveries await the bold.</p> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Explore the Volcano (30 min)</div>">> <<advancetime 30>> <<goto "VolcanoExplore">> <</link>> </div> <!-- Lava Pool (discovered) --> <<if $discoveredLavaPool>> <div style="border: 3px solid #ff3d00; border-radius: 10px; padding: 15px; background: #2a1a0a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(255,61,0,0.15); display: flex; flex-direction: column;"> <h3 style="color: #ff3d00; margin: 0 0 10px 0;">🔥 Bubbling Lava Pool</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A pool of molten rock bubbles and hisses at the base of a cliff. Only a creature born of fire could survive bathing in it.</p> <<link "<div style='background: linear-gradient(135deg, #ff3d00 0%, #dd2c00 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Approach the Lava Pool</div>">> <<goto "VolcanoLavaPool">> <</link>> </div> <</if>> <!-- Broken Wolf Statue (only if discovered) --> <<if $discoveredWolfStatue>> <div style="border: 3px solid #c77dff; border-radius: 10px; padding: 15px; background: #1a0a28; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(199,125,255,0.15); display: flex; flex-direction: column;"> <h3 style="color: #c77dff; margin: 0 0 10px 0;">🐺 The Broken Wolf Statue</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A headless stone wolf ringed with dark runes. The heat around it is murderous.</p> <<link "<div style='background: #c77dff; color: #1a0a2e; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Approach the Statue</div>">> <<goto "VolcanoWolfStatue">> <</link>> </div> <</if>> <!-- Magmaheart Hollow — visible only after the Heart of the Volcano quest is complete --> <<if $quests && $quests.magmaheartUnlocked === "complete">> <div style="border: 3px solid #ff5722; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a0500 0%, #1a0500 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255,87,34,0.25); display: flex; flex-direction: column;"> <h3 style="color: #ff8a65; margin: 0 0 10px 0;">🌋 Magmaheart Hollow</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A glowing crack in the volcano's heart, opened by ancient smiths. Fourteen floors of obsidian and mithril, fire opal and sunstone. The deepest, hottest, richest mine known.</p> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #b03a17 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend into the Hollow (45 min)</div>">> <<advancetime 45>> <<goto "MagmaheartHollowEntrance">> <</link>> </div> <</if>> <!-- Cup of Iron bowl (only if discovered; Oni transformation, New Moon at Night) --> <<if $discoveredIronBowl>> <div style="border: 3px solid #b85c5c; border-radius: 10px; padding: 15px; background: #241a1a; box-shadow: 0 0 14px rgba(184,92,92,0.15);"> <h3 style="color: #b85c5c; margin: 0 0 10px 0;">🍶 An Iron Bowl</h3> <p style="font-size: 14px; color: #ddc4c4; margin: 0 0 12px 0; line-height: 1.5;">A heavy iron rimmed stone bowl wedged into the black rock near the caldera edge. Old. Older than the city.</p> <<if $giftInventory && ($giftInventory.sake_bottle || 0) > 0>> <<link "<div style='background: #b85c5c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Pour sake into the bowl</div>">> <<run setup.oni && setup.oni.tryCupOfIron && setup.oni.tryCupOfIron()>> <<goto "Volcano">> <</link>> <<else>> <p style="font-size: 13px; color: #888; font-style: italic; margin: 0;">You have no sake to pour.</p> <</if>> <<if $oniLastBowlMessage>> <p style="font-size: 14px; color: #ddd; font-style: italic; margin: 12px 0 0 0; line-height: 1.5;">$oniLastBowlMessage</p> <</if>> </div> <</if>> </div> <h2 style="color: #ff5722;">The Peak</h2> <<if _hasHeatImmunity>> <p style="color: #aaa; font-size: 14px; margin: -10px 0 15px 0;">The summit radiates lethal heat, but your body can withstand it.</p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #ff1744; border-radius: 10px; padding: 15px; background: #2a0a0a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255,23,68,0.2); display: flex; flex-direction: column;"> <h3 style="color: #ff1744; margin: 0 0 10px 0;">🌋 Ascend to the Peak</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The summit of the volcano. Only those with true heat resistance can survive the climb.</p> <<link "<div style='background: linear-gradient(135deg, #ff1744 0%, #d50000 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Climb to the Peak (30 min)</div>">> <<advancetime 30>> <<goto "VolcanoPeak">> <</link>> </div> </div> <<else>> <div style="background: #2a1a0a; padding: 15px; border-radius: 10px; border: 2px dashed #ff5722; margin-bottom: 25px; opacity: 0.6;"> <p style="color: #ff8a65; font-size: 14px; margin: 0; text-align: center;">⚠️ The peak radiates lethal heat. You’d need some form of heat resistance to survive the climb.</p> </div> <</if>> <h2 style="color: #ff5722;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Return to Mountains --> <div style="border: 3px solid #8B9DAF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8B9DAF; margin: 0 0 10px 0;">⛏️ The Mountains</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Head back down the volcanic slope to the mountain trails.</p> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend to Mountains (4 hrs)</div>">> <<advancetime 240>> <<goto "Mountains">> <</link>> </div> <!-- Return to The Nest --> <div style="border: 3px solid #D2691E; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #D2691E; margin: 0 0 10px 0;">🫹 The Nest</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Make the long trek back down to the giant nest.</p> <<link "<div style='background: linear-gradient(135deg, #D2691E 0%, #8B4513 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend to The Nest (4 hrs)</div>">> <<advancetime 240>> <<goto "The Nest">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("The Nest")>> <<run $visitedLocations.push("The Nest")>> <</if>> <<set $lastLocation = "The Nest">> <div style="background: #1a1a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #D2691E; text-align: center;"> The Nest</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/TheNest.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #D2691E; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="The Nest"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #5D4037 0%, #8B4513 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #D2691E;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> A colossal nest of woven tree trunks and giant feathers sits atop a rocky outcrop, high above the jungle canopy. The air is warm and wild, filled with the calls of unfamiliar birds and the rustle of dense foliage below. Behind you, a wall of mountains and a smoldering volcano completely block any view of Sunfish City — it feels like another world entirely. </p> </div> <!-- The Giant Chicken --> <div style="background: #2a2a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 0 20px rgba(255, 215, 0, 0.15);"> <p style="color: #d4c47a; font-size: 16px; text-align: center; margin: 0 0 10px 0;"> The giant chicken rests in the center of the nest, preening its massive golden-crimson feathers. It clucks softly as you approach, one enormous eye watching you with what might be affection. Or hunger. Hard to tell. </p> </div> <h2 style="color: #D2691E;">Surroundings</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Jungle --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🌴 Jungle</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Dense tropical jungle stretches endlessly below the nest. You can hear strange creatures within...</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend into the Jungle</div>">> <<advancetime 30>> <<goto "Jungle">> <</link>> </div> <!-- Volcano --> <div style="border: 3px solid #ff5722; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff5722; margin: 0 0 10px 0;">🌋 Volcano</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The volcano's glow is visible even from here. Heat radiates from its direction.</p> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Ascend to the Volcano (4 hrs)</div>">> <<advancetime 240>> <<goto "Volcano">> <</link>> </div> <!-- Mountains --> <div style="border: 3px solid #8B9DAF; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8B9DAF; margin: 0 0 10px 0;">⛰️ The Mountains</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Jagged peaks rise behind the nest, their upper slopes dusted with snow. A rocky trail winds upward into the thin mountain air.</p> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Climb into the Mountains (4 hrs)</div>">> <<advancetime 240>> <<goto "Mountains">> <</link>> </div> </div> <h2 style="color: #D2691E;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Return to Coral Reef via Chicken --> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a2a1a 0%, #1a1a0a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255, 215, 0, 0.3); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🐔 Ride the Chicken Back</h3> <p style="font-size: 14px; color: #d4c47a; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The giant chicken can fly you back to the Coral Reef.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #ff9800 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px; box-shadow: 0 0 10px rgba(255, 215, 0, 0.4);'>🐔 Fly Back to Coral Reef</div>">> <<advancetime 30>> <<goto "CoralReef">> <</link>> </div> </div> </div> <</nobr>>
This place will appear randomly and the door is locked but sometimes you'll see a figure in it looking at you with two black souless eyes before it dissapears. Don't actually make this a passage This is just something I want to sometimes show up in the jungle.
<<nobr>><<if !setup.oni.isPlayerInOwnBody()>><<goto "CoralReef">><</if>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <<set $lastLocation = "CoralReef">> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px; text-align: center;"> <<if !$giantChickenUnlocked>> <!-- FIRST TIME: The chicken arrives to eat the fish --> <div id="chicken-scene"> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #ff9800; font-size: 22px; font-weight: bold; text-shadow: 0 0 20px rgba(255, 152, 0, 0.5);">The sky darkens...</p> </div> <<timed 2s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">A massive shadow sweeps across the coral reef. The water ripples violently. Every fish in the ocean seems to scatter at once.</p> </div> <</timed>> <<timed 5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ff5722; font-size: 28px; font-weight: bold; text-shadow: 0 0 30px rgba(255, 87, 34, 0.6);">BWAAAAWK!</p> <p style="color: #ccc; font-size: 18px; margin-top: 15px;">A <strong style="color: #ffd700; font-size: 22px;">GIANT CHICKEN</strong> descends from the heavens, its enormous wings sending shockwaves across the water. It's easily the size of a house — feathers glistening gold and crimson in the sunlight.</p> </div> <</timed>> <<timed 9s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">The colossal bird lands at the reef's edge with a thunderous splash, its beady eyes locked onto the bucket. In one swift motion, it plunges its massive beak into the bucket and devours every last fish — all <strong style="color: #ff9800;"><<print $fishBucketCount>></strong> of them — in a single, terrifying gulp.</p> </div> <<set $fishBucketCount = 0>> <</timed>> <<timed 13s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">Satisfied, the giant chicken lets out a contented cluck that shakes the ground. Then it turns to you, lowers its body, and extends one enormous wing like a ramp.</p> <p style="color: #ffd700; font-size: 16px; font-style: italic; margin-top: 10px;">It... wants you to climb on?</p> </div> <div style="margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #ff9800 100%); color: #1a1a1a; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 18px; cursor: pointer; box-shadow: 0 0 20px rgba(255, 215, 0, 0.4);'>🐔 Climb Aboard</div>">> <<set $giantChickenUnlocked = true>> <<set $giantChickenRideCount += 1>> <<run setup.achievements.unlock("squawk")>> <<goto "GiantChickenFlight">> <</link>> </div> <</timed>> </div> <<elseif $giantChickenRideCount === 1>> <!-- SECOND RIDE: First bell ring - shorter cutscene --> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #ffd700; font-size: 22px; font-weight: bold; text-shadow: 0 0 20px rgba(255, 215, 0, 0.5);">The bell's chime echoes across the reef...</p> </div> <<timed 2s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">You hear it before you see it — the deep, rhythmic beat of enormous wings. A familiar shadow blots out the sun.</p> </div> <</timed>> <<timed 5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ff5722; font-size: 24px; font-weight: bold; text-shadow: 0 0 20px rgba(255, 87, 34, 0.5);">BWAAAAWK!</p> <p style="color: #ccc; font-size: 18px; margin-top: 15px;">The <strong style="color: #ffd700;">GIANT CHICKEN</strong> swoops down from the sky, landing at the reef's edge with a ground-shaking thud. Its enormous head tilts, one beady eye studying you with what can only be described as recognition.</p> </div> <</timed>> <<timed 9s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">It lets out a low, rumbling cluck — almost affectionate — and lowers its wing to the ground. No hesitation this time. It knows why you called, and so do you.</p> </div> <div style="margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #ff9800 100%); color: #1a1a1a; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 18px; cursor: pointer; box-shadow: 0 0 20px rgba(255, 215, 0, 0.4);'>🐔 Climb Aboard</div>">> <<set $giantChickenRideCount += 1>> <<goto "GiantChickenFlight">> <</link>> </div> <</timed>> <<else>> <!-- THIRD+ RIDE: No cutscene, just text --> <<if setup.hasDebuff("exhaustion")>> <<run setup.removeDebuff("exhaustion")>> <</if>> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #ffd700; font-size: 22px; font-weight: bold; text-shadow: 0 0 20px rgba(255, 215, 0, 0.5);">You ring the bell.</p> </div> <<timed 1.5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">The giant chicken arrives right on cue, scooping you up with practiced ease. The flight over the mountains is as breathtaking as ever, and before long you're descending toward the familiar nest.</p> </div> <div style="margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B4513 0%, #D2691E 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 18px; cursor: pointer; box-shadow: 0 0 20px rgba(139, 69, 19, 0.4);'> Arrive at The Nest</div>">> <<set $giantChickenRideCount += 1>> <<goto "The Nest">> <</link>> </div> <</timed>> <</if>> </div> <</nobr>>
<<nobr>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <div style="background: #0a0a0a; min-height: 100vh; padding: 20px; text-align: center;"> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #87ceeb; font-size: 22px; font-weight: bold; text-shadow: 0 0 20px rgba(135, 206, 235, 0.5);">You grip the feathers tightly as the chicken launches skyward...</p> </div> <<timed 2.5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">The wind howls past your ears as the reef shrinks below. Sunfish City sprawls out beneath you — the Downtown towers, the glittering Red Light District, the Docks with their tiny boats — all growing smaller by the second.</p> </div> <</timed>> <<timed 6s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">The chicken banks hard, soaring over jagged mountain peaks dusted with snow. A volcano looms ahead, its crater glowing faintly orange, heat shimmering in the air as you pass over it.</p> <<if setup.hasDebuff("exhaustion")>> <p style="color: #ffd700; font-size: 16px; margin-top: 15px; font-style: italic;">A warm, golden energy radiates from the chicken's feathers into your body. The bone-deep exhaustion that weighed you down melts away, replaced by a strange, tingling vitality. You feel completely refreshed.</p> <<run setup.removeDebuff("exhaustion")>> <</if>> </div> <</timed>> <<timed 10s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">The mountains rise behind you like a wall, completely blocking any view of the city. You're on the other side of the island now — a place you didn't even know existed. Dense jungle stretches in every direction, untouched and wild.</p> </div> <</timed>> <<timed 14s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px;">The giant chicken begins to descend, circling a massive nest perched atop a rocky outcrop. Woven from entire tree trunks and lined with enormous feathers, it's unlike anything you've ever seen.</p> <p style="color: #ffd700; font-size: 16px; font-style: italic; margin-top: 10px;">With a gentle thud, you arrive.</p> </div> <div style="margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B4513 0%, #D2691E 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 18px; cursor: pointer; box-shadow: 0 0 20px rgba(139, 69, 19, 0.4);'> Step Into The Nest</div>">> <<goto "The Nest">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <div style="background: #000; min-height: 100vh; padding: 40px 20px; text-align: center;"> <div class="fade-in" style="padding: 60px 20px;"> <p style="color: #333; font-size: 18px;">Your vision goes dark...</p> </div> <<timed 2s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #444; font-size: 16px;">You can't see anything. The sound of the ocean fills the darkness. Minutes pass... or is it longer?</p> </div> <</timed>> <<timed 5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #555; font-size: 16px;">Slowly, your vision begins to return. The coral reef fades back into view, the colors swimming before your eyes.</p> </div> <</timed>> <<timed 8s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #aaa; font-size: 18px;">You look toward the bucket. It's <strong style="color: #ff5722;">completely empty</strong>. Every single fish you dumped in is gone — vanished without a trace.</p> <p style="color: #666; font-size: 14px; font-style: italic; margin-top: 10px;">Whatever was supposed to happen... you weren't fast enough.</p> </div> <div style="margin-top: 30px;"> <<link "<div style='background: #00bcd4; color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Coral Reef</div>">> <<goto "CoralReef">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <!-- Initialize jungle tracking if needed --> <<if !$jungleMaterials>><<set $jungleMaterials = 0>><</if>> <<if $jungleCampBuilt === undefined>><<set $jungleCampBuilt = false>><</if>> <<if $foundMysteriousBeam === undefined>><<set $foundMysteriousBeam = false>><</if>> <<if $discoveredOvergrownLab === undefined>><<set $discoveredOvergrownLab = false>><</if>><<if $overgrownLabUnlocked === undefined>><<set $overgrownLabUnlocked = false>><</if>><<if $labSecurityDisabled === undefined>><<set $labSecurityDisabled = false>><</if>><<if $slimeTubeBroken === undefined>><<set $slimeTubeBroken = false>><</if>> <div style="background: #1a1a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #2ecc71; text-align: center;">🌿 Jungle Exploration</h1> <!-- TRAIT CHECK: Blocking traits prevent gathering --> <<set _isBlocked = false>> <<set _blockReason = "">> <!-- Check blocking physical traits --> <<if $physicalTraits && ($physicalTraits.includes("Weak") || $physicalTraits.includes("Clumsy"))>> <<set _isBlocked = true>> <<if $physicalTraits.includes("Weak")>> <<set _blockReason = "You're too weak to push through the dense undergrowth. Vines and branches overwhelm you at every turn.">> <<else>> <<set _blockReason = "You stumble and trip over every root and rock. After falling face-first into a mud puddle for the third time, you give up.">> <</if>> <</if>> <!-- Check blocking mental traits --> <<if !_isBlocked && $mentalTraits>> <<if $mentalTraits.includes("Lazy")>> <<set _isBlocked = true>> <<set _blockReason = "Ugh... the jungle is so far and so hot. You take two steps into the undergrowth, decide this is way too much effort, and sit down against a tree instead.">> <<elseif $mentalTraits.includes("Bimbo")>> <<set _isBlocked = true>> <<set _blockReason = "Ooh, pretty butterfly! You spend the entire time chasing a colorful insect around in circles. You don't find anything useful, but at least you had fun?">> <<elseif $mentalTraits.includes("Cowardly")>> <<set _isBlocked = true>> <<set _blockReason = "Every snap of a twig and rustle of leaves sends you into a panic. You barely make it twenty feet before running back to safety, convinced something is hunting you.">> <<elseif $mentalTraits.includes("Impatient")>> <<set _isBlocked = true>> <<set _blockReason = "This is taking forever! After five minutes of hacking through vines with no results, you throw your hands up and storm back. There has to be a faster way.">> <</if>> <</if>> <<if _isBlocked>> <!-- BLOCKED: Can't gather --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">You can't seem to manage...</h3> <p style="color: #ccc; margin: 0; line-height: 1.6;"><<print _blockReason>></p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> <<else>> <!-- NOT BLOCKED: Calculate materials gathered --> <<set _materialsFound = 1>> <!-- Helpful skill bonuses --> <<if $skills && $skills.includes("Construction")>><<set _materialsFound += 1>><</if>> <<if $skills && $skills.includes("Heavy Lifting")>><<set _materialsFound += 1>><</if>> <!-- Helpful physical trait bonuses --> <<if $physicalTraits>> <<if $physicalTraits.includes("Strong")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Muscular")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Sturdy")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Fit")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Athletic Build")>><<set _materialsFound += 1>><</if>> <!-- Transformation bonuses --> <<if $physicalTraits.includes("Werewolf")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Cerberus")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Himbo")>><<set _materialsFound += 1>><</if>> <<if $physicalTraits.includes("Gym Bunny")>><<set _materialsFound += 1>><</if>> <</if>> <!-- Helpful mental trait bonuses --> <<if $mentalTraits>> <<if $mentalTraits.includes("Resourceful")>><<set _materialsFound += 1>><</if>> <<if $mentalTraits.includes("Organized")>><<set _materialsFound += 1>><</if>> <<if $mentalTraits.includes("Hardworking")>><<set _materialsFound += 1>><</if>> <</if>> <!-- Cap at 5 per trip --> <<set _materialsFound = Math.min(_materialsFound, 5)>> <!-- Add materials if camp not yet built --> <<if !$jungleCampBuilt>> <<set $jungleMaterials += _materialsFound>> <</if>> <!-- Cabin flavor text roll (independent, 15% chance) --> <<set _cabinRoll = random(1, 100)>> <<if _cabinRoll <= 15>> <<set _cabinVariant = random(1, 4)>> <div style="background: #1a1a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #444; box-shadow: 0 4px 8px rgba(0,0,0,0.6);"> <<if _cabinVariant === 1>> <p style="color: #888; margin: 0; line-height: 1.6; font-style: italic;">Through a gap in the trees, you catch a glimpse of something man-made — a small cabin, half-swallowed by the jungle. Its door is shut tight, the wood dark and rotting. For a moment, you think you see movement in the window. Two dark, soulless eyes staring directly at you. You blink, and whatever it was is gone.</p> <<elseif _cabinVariant === 2>> <p style="color: #888; margin: 0; line-height: 1.6; font-style: italic;">You stumble upon a clearing where an old cabin stands in silence. Vines crawl across its walls like grasping fingers. The door is locked — you try the handle, but it won't budge. As you turn to leave, you feel the unmistakable weight of being watched. A figure stands in the window. It has eyes like pits of black ink. Then it's gone, as if it was never there.</p> <<elseif _cabinVariant === 3>> <p style="color: #888; margin: 0; line-height: 1.6; font-style: italic;">Something catches your eye through the foliage — a weathered cabin, barely standing. You approach, but the door is firmly locked. No sound comes from inside. You peer through a crack in the shuttered window and see only darkness. Then, from the darkness, something peers back. Two black, empty eyes. You stumble backward, and when you look again, the window shows nothing but shadow.</p> <<else>> <p style="color: #888; margin: 0; line-height: 1.6; font-style: italic;">Deep in the undergrowth, you find a cabin you're certain wasn't there before. The door is sealed shut. You circle it, looking for another way in, but there is none. For just an instant, reflected in the grimy window glass, you see a shape — humanoid, but wrong. Its eyes are two voids of absolute black. It vanishes the moment you focus on it, leaving only your own frightened reflection.</p> <</if>> </div> <</if>> /* Build list of eligible events, then shuffle and roll each independently */ <<set _events = []>> /* Mysterious Beam: 25% chance, only if not found yet */ <<if !$foundMysteriousBeam>> <<run _events.push("beam")>> <</if>> /* Overgrown Ruins: 20% chance, requires beam found, only if not found yet */ <<if !$foundRuins && $foundMysteriousBeam>> <<run _events.push("ruins")>> <</if>> /* Giant Beehive: 15% chance, skipped if already have Honey or Honeybee */ <<if !$physicalTraits.includes("Honey") && !$physicalTraits.includes("Honeybee")>> <<run _events.push("beehive")>> <</if>> /* Obelisk hint: 8% chance, once per week */ <<if Math.floor($dayNumber / 7) !== $lastObeliskWeek_jungle>> <<run _events.push("obelisk")>> <</if>> /* Manor Key: 5% chance, only if not found yet */ <<if !$hasManorKey>> <<run _events.push("manorkey")>> <</if>> /* Hidden Lagoon: 15% chance, only if not found yet */ <<if !$discoveredHiddenLagoon>> <<run _events.push("hiddenlagoon")>> <</if>> /* Sunfish Temple: 25% chance, only after the Altar witness scene */ <<if $cuffSundayWitnessSeen && !$cuffTempleDiscovered>> <<run _events.push("sunfishtemple")>> <</if>> /* Overgrown Lab: 18% chance, keeps appearing until the lab security is disabled */ <<if !$labSecurityDisabled>> <<run _events.push("overgrownlab")>> <</if>> /* Shuffle the events array (Fisher-Yates) */ <<for _i = _events.length - 1; _i > 0; _i-->> <<set _j = random(0, _i)>> <<set _temp = _events[_i]>> <<set _events[_i] = _events[_j]>> <<set _events[_j] = _temp>> <</for>> /* Roll each event independently in shuffled order; first success wins */ <<set _eventFired = false>> <<for _idx = 0; _idx < _events.length; _idx++>> <<if !_eventFired>> <<set _roll = random(1, 100)>> <<if _events[_idx] === "beam" && _roll <= 25>> <<set _eventFired = true>> <<set $foundMysteriousBeam = true>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e1bee7; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(225,190,231,0.3);"> <h3 style="color: #e1bee7; margin: 0 0 15px 0;">✨ Something Extraordinary...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> As you push through a particularly dense thicket of ferns, the jungle suddenly opens into a wide clearing. And there, in the center, you see it. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> A beam of light. Not sunlight — something else entirely. It rises from the ground like a pillar of liquid starlight, stretching impossibly high into the sky, punching straight through the canopy as if the trees don't exist. It makes no sound, casts no heat, yet it illuminates everything around it with a soft, ethereal glow. </p> <p style="color: #e1bee7; margin: 0; font-weight: bold; text-align: center; font-size: 18px;"> You've discovered the Mysterious Beam! You can now visit it from the Jungle. </p> </div> <<elseif _events[_idx] === "ruins" && _roll <= 20>> <<set _eventFired = true>> <<set $foundRuins = true>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a6741; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(74,103,65,0.3);"> <h3 style="color: #4a6741; margin: 0 0 15px 0;">🏚️ Ancient Stonework...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> As you push through a wall of hanging moss, the jungle floor changes beneath your feet. Dirt gives way to cracked stone slabs, choked with roots and ferns. You look up and see them — crumbling walls of grey-green stone, half-swallowed by the jungle. Arched doorways yawn open like dark mouths. Carved symbols cover every surface, worn nearly smooth by centuries of rain. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> This was a building once. A temple, maybe, or a palace. Whatever civilization built it is long gone. The air here feels different — heavier, older, and strangely still. Even the jungle sounds seem muted, as if the ruins exist in their own pocket of silence. </p> <p style="color: #4a6741; margin: 0; font-weight: bold; text-align: center; font-size: 18px;"> You've discovered the Overgrown Ruins! You can now visit them from the Jungle. </p> </div> <<elseif _events[_idx] === "beehive" && _roll <= 15>> <<set _eventFired = true>> <<goto "JungleBeehive">> <<elseif _events[_idx] === "obelisk" && _roll <= 8>> <<set _eventFired = true>> <<set $lastObeliskWeek_jungle = Math.floor($dayNumber / 7)>> <div style="background: #1a2030; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #c0c0c0; box-shadow: 0 0 20px rgba(192,192,192,0.3);"> <h3 style="color: #e0e0e0; margin: 0 0 15px 0;">△ A Strange Obelisk</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Half-buried beneath a tangle of roots, you spot something that doesn’t belong here — a sleek white obelisk, no taller than your forearm, jutting from the jungle floor at a slight angle. Its surface is impossibly smooth, like polished porcelain, and cool to the touch despite the humidity. Faint lines trace across it in geometric patterns — not carved, but etched from within, as though the stone itself contains circuitry. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Near the base, four interlocking gear symbols are arranged in a row. Beneath them, a sequence of numbers is inscribed in sharp, angular notation: <strong style="color: #ffd700; font-size: 20px; font-family: monospace; letter-spacing: 4px;"><<print $obeliskCodes[1][0]>> <<print $obeliskCodes[1][1]>> <<print $obeliskCodes[1][2]>> <<print $obeliskCodes[1][3]>></strong>. Below the numbers, more text — a single phrase in an angular script you can’t decipher. </p> <div style="background: #0d1520; padding: 12px; border-radius: 8px; border: 1px solid #888; text-align: center;"> <p style="color: #aaa; font-size: 14px; font-style: italic; margin: 0;">The obelisk hums faintly, then falls silent. You memorize what you saw before the jungle swallows it again.</p> </div> </div> <<elseif _events[_idx] === "manorkey" && _roll <= 5>> <<set _eventFired = true>> <<set $hasManorKey = true>> <div style="background: #1a0a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #6a0dad; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(106,13,173,0.3);"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🗝️ A Strange Key...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Your boot catches on something half-buried in the mud beneath a rotting log. You kneel down and dig it out — a key. Not a modern key, but something old and ornate, wrought from dark iron with an intricate handle shaped like intertwining thorns. It feels unnaturally cold in your hand, even in the jungle heat. Something about it makes your skin crawl, but you pocket it anyway. A key this unusual must open something important. </p> <div style="background: #0d0018; padding: 12px; border-radius: 8px; border: 1px solid #6a0dad; text-align: center;"> <p style="color: #9b59b6; font-size: 16px; font-weight: bold; margin: 0;">🗝️ You found a Strange Key!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">It looks like it could fit an old ornate lock...</p> </div> </div> <<elseif _events[_idx] === "hiddenlagoon" && _roll <= 15>> <<set _eventFired = true>> <<set $discoveredHiddenLagoon = true>> <div style="background: linear-gradient(135deg, #0f2a3a 0%, #07151f 100%); border: 2px solid #4dd0e1; border-radius: 12px; padding: 18px; margin: 15px 0; box-shadow: 0 0 20px #4dd0e144;"> <h3 style="color: #4dd0e1; margin: 0 0 10px 0;">🌊 A Hidden Lagoon</h3> <p style="color: #ddd; line-height: 1.5; margin: 0;">Pushing past a curtain of vines you stumble onto something the jungle had kept to itself. A narrow path opens to a still glass water lagoon nestled in the cliffs. The water is impossibly clear. Somewhere across it you catch a flash of movement and a glint of blue. Then nothing. You note the way back.</p> </div> <<elseif _events[_idx] === "overgrownlab" && _roll <= 18>> <<set _eventFired = true>> <<set $discoveredOvergrownLab = true>> <<goto "OvergrownLabDoor">> <<elseif _events[_idx] === "sunfishtemple" && _roll <= 25>> <<set _eventFired = true>> <<set $cuffTempleDiscovered = true>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #c9a9ff; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(201,169,255,0.25);"> <h3 style="color: #c9a9ff; margin: 0 0 15px 0;">🐟 An Old Temple in the Canopy...</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> A break in the canopy spills pale green light onto a flagstone half buried in vines. You scrape it clear with your boot. The next stone matches it. And the next. A path. You follow it through dripping moss and the smell of crushed leaves until the trees pull back and a low building leans into view, rooted by tall figs and fed by tree-runoff. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Mola mola. Sunfish. Carved on every face of every weathered block. Disc bodies, tall fins, small eyes that have watched the jungle eat the door for a long time. The portico is open. </p> <p style="color: #c9a9ff; margin: 0; font-weight: bold; text-align: center; font-size: 18px;"> You've discovered the Sunfish Temple! You can now visit it from the Jungle. </p> </div> <</if>> <</if>> <</for>> /* If no event fired, show nothing special */ <<if !_eventFired>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0; line-height: 1.6;"> <<set _exploreText = random(1, 5)>> <<if _exploreText === 1>> You hack through dense vines and scramble over fallen logs. The jungle is beautiful but unforgiving. After a while of searching, you head back with what you found. <<elseif _exploreText === 2>> Strange birds call from high above as you navigate the undergrowth. You find a few useful materials among the roots and branches. <<elseif _exploreText === 3>> The humidity is oppressive, but you press on. You gather what you can from the jungle floor — sturdy sticks, flexible vines, broad leaves that could serve as shelter. <<elseif _exploreText === 4>> You follow a narrow animal trail deeper into the jungle. The sounds of civilization have long faded. You collect some useful materials along the way. <<else>> Something rustles in the canopy above, but when you look up, you see only leaves. You focus on gathering what you can and head back. <</if>> </p> </div> <</if>> <!-- Materials gathered display (if camp not yet built) --> <<if !$jungleCampBuilt>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #8B4513; text-align: center;"> <p style="color: #D2691E; margin: 0; font-size: 16px;">🪵 You gathered <strong><<print _materialsFound>></strong> material<<if _materialsFound !== 1>>s<</if>>! (Total: <<print $jungleMaterials>> / 10)</p> <<if $jungleMaterials >= 10>> <p style="color: #ff9800; margin: 10px 0 0 0; font-weight: bold;">You have enough materials to build a camp!</p> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <div style="background: #0a0a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e1bee7; text-align: center;">✨ The Mysterious Beam</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2e 0%, #4a148c 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e1bee7;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The beam rises from a patch of bare earth in the center of a perfectly circular clearing. No plants grow near its base. The light is colorless yet somehow radiant, visible even against the brightest daylight or the darkest night sky. It stretches upward without end, as if connecting the ground to something far beyond the clouds. </p> </div> <<set _beamHour = Math.floor($timeInMinutes / 60) % 24>> <<if $currentWeather === "Stormy" && (_beamHour >= 21 || _beamHour < 3) && !$mentalTraits.includes("Blessed")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #e1bee7; box-shadow: 0 0 20px rgba(156,39,176,0.4), 0 0 40px rgba(225,190,231,0.2);"> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> Thunder cracks overhead as rain hammers the jungle canopy. Lightning illuminates the clearing in strobing flashes — and with each flash, the beam pulses brighter, wider, almost alive. The air around it hums with energy, and you feel the hair on your arms stand on end. The beam is reacting to the storm. </p> <p style="color: #e1bee7; margin: 0; font-weight: bold; text-align: center; font-size: 16px;"> The beam seems to be calling to you... </p> </div> <</if>> <div style="text-align: center; margin-top: 25px; display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9c27b0 0%, #e1bee7 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; box-shadow: 0 0 20px rgba(156,39,176,0.5), 0 0 40px rgba(225,190,231,0.3); font-size: 16px;'>✨ Stand in the Light</div>">> <<goto "MysteriousBeamStand">> <</link>> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #D2691E; text-align: center;">🏕️ Jungle Camp</h1> <div style="padding: 20px; background: linear-gradient(135deg, #5D4037 0%, #8B4513 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #D2691E;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> Your makeshift camp sits in a small clearing you carved out of the jungle. A lean-to shelter of sticks and broad leaves keeps the worst of the rain off, and a ring of stones marks a fire pit. It's not much, but it's yours — a small island of order in the wild chaos of the jungle. </p> </div> <h2 style="color: #D2691E;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Rest at Camp --> <div style="border: 3px solid #8B4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #D2691E; margin: 0 0 10px 0;">💤 Rest</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take a break and recover your energy in your shelter.</p> <<link "<div style='background: #8B4513; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Rest (60 min)</div>">> <<advancetime 60>> <<run setup.removeDebuff("dive_injury")>> <<goto "JungleCamp">> <</link>> </div> <!-- Sleep at Camp --> <div style="border: 3px solid #8B4513; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #D2691E; margin: 0 0 10px 0;">😴 Sleep</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Bed down in your lean-to for a real sleep. Any amount of sleep clears exhaustion. Sleep 8+ hours for the Well Rested buff.</p> <<link "<div style='background: #8B4513; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Sleep</div>">> <<popover "camp-sleep-popover">> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; max-width: 350px;"> <h3 style="color: #D2691E; margin: 0 0 15px 0; text-align: center;">How long do you want to sleep?</h3> <div style="text-align: center; margin-bottom: 15px;"> <input type="number" id="camp-sleep-input" min="1" max="12" value="8" style="width: 80px; padding: 10px; font-size: 18px; text-align: center; border-radius: 5px; border: 2px solid #8B4513; background: #1a1a1a; color: white;"> <span style="color: #ccc; margin-left: 10px;">hours</span> </div> <<if $witchFormActive && $clairFirstMeetingDone>> <<if $dreamwalkEnabled>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check" checked> 💤 Dreamwalk tonight</label></p> <<else>> <p style="margin: 8px 0 0 0;"><label style="color: #a78bfa; font-size: 13px; cursor: pointer;"><input type="checkbox" id="dreamwalk-check"> 💤 Dreamwalk tonight</label></p> <</if>> <</if>> <p style="color: #888; font-size: 12px; text-align: center; margin-bottom: 15px;">Any amount of sleep removes exhaustion. Sleep 8+ hours for the Well Rested buff.</p> <div style="margin-top: 20px; text-align: center;"> <<link "<div style='display: inline-block; background: #8B4513; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; margin-right: 10px;'>Confirm</div>">> <<set _campSleepHours = Number(jQuery("#camp-sleep-input").val())>> <<if _campSleepHours < 1 || _campSleepHours > 12 || Number.isNaN(_campSleepHours)>> <<set _campSleepHours = 8>> <</if>> <<if _campSleepHours >= 8>> <<run setup.achievements.unlock("full_rest")>> <</if>> <<if !$lucidRestActive>><<run advanceTime(_campSleepHours * 60)>><</if>> <<run setup.setHairMessy()>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.removeDebuff("exhaustion")>> <<if $witchFormActive && $clairFirstMeetingDone>><<set $dreamwalkEnabled = jQuery("#dreamwalk-check").prop("checked")>><</if>> <<set _dreamRoute = setup.witchSpells.onSleep(_campSleepHours, "JungleCamp")>> <<if _campSleepHours >= 8 && setup.canEarnWellRestedBySleeping()>> <<run setup.addBuff("well_rested", 480)>><<run setup.mining && setup.mining.refillEnergy && setup.mining.refillEnergy()>> <</if>> <<run Dialog.close()>> <<if _dreamRoute>><<goto _dreamRoute>><<else>><<goto "JungleCamp">><</if>> <</link>> <<link "<div style='display: inline-block; background: #dc3545; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</popover>> <</link>> </div> <<if $labSecurityDisabled>> <div style="border: 3px solid #8cff66; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 12px rgba(140,255,102,0.2); display: flex; flex-direction: column;"> <h3 style="color: #8cff66; margin: 0 0 10px 0;">🧪 Overgrown Lab</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The lab door answered your hand once. You know the way now, and the apparatus is yours to use whenever you like.</p> <<link "<div style='background: linear-gradient(135deg, #5a9e3a 0%, #8cff66 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to the Lab (15 min)</div>">> <<advancetime 15>> <<goto "OvergrownLab">> <</link>> </div> <</if>> <!-- Future placeholder --> <div style="border: 3px solid #555; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.5;"> <h3 style="color: #888; margin: 0 0 10px 0;">🔧 Upgrade Camp</h3> <p style="font-size: 14px; color: #666; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Further improvements to your camp might be possible...</p> <div style="background: #333; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;">Coming Soon</div> </div> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } @keyframes blessedGlow { 0% { box-shadow: 0 0 20px rgba(255,215,0,0.3); } 50% { box-shadow: 0 0 60px rgba(255,215,0,0.7), 0 0 100px rgba(225,190,231,0.4); } 100% { box-shadow: 0 0 20px rgba(255,215,0,0.3); } } </style> <div style="background: #0a0a1a; min-height: 100vh; padding: 20px; text-align: center;"> <<set _beamHour = Math.floor($timeInMinutes / 60) % 24>> <<if $currentWeather === "Stormy" && (_beamHour >= 21 || _beamHour < 3) && !$mentalTraits.includes("Blessed")>> <!-- BLESSED EVENT: Stormy night (9pm-3am), no existing Blessed trait --> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #e1bee7; font-size: 24px; font-weight: bold; text-shadow: 0 0 20px rgba(225,190,231,0.5);">You step into the beam...</p> </div> <<timed 2.5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px; line-height: 1.6;">The light surrounds you instantly. It's warm — warmer than it should be. The storm rages overhead but you can't feel the rain anymore. The beam flickers, once, twice, and then <strong style="color: #e1bee7;">blazes</strong> with an intensity that forces your eyes shut.</p> </div> <</timed>> <<timed 6s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px; line-height: 1.6;">A warmth flushes through your entire body — not hot, not burning, but <em>deep</em>. It seeps into your bones, your muscles, your mind. Every part of you tingles with an energy you've never felt before. Lightning strikes somewhere close and the beam <strong style="color: #ffd700;">pulses</strong> in rhythm with the thunder.</p> </div> <</timed>> <<timed 10s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px; line-height: 1.6;">Your knees buckle. The world tilts. The light is everything now — above, below, inside you. You feel yourself falling, but there's no ground, no sky, just an endless warmth carrying you somewhere far away...</p> </div> <</timed>> <<timed 14s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #444; font-size: 18px;">...</p> </div> <</timed>> <<timed 16s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #888; font-size: 18px; line-height: 1.6;">You wake up on the ground. The storm has passed. The beam is calm again, its usual silent shimmer. Morning light filters through the canopy.</p> <p style="color: #ccc; font-size: 18px; margin-top: 15px; line-height: 1.6;">You sit up slowly. Something is <strong style="color: #ffd700;">different</strong>. Your body feels lighter, stronger. Your thoughts are clearer. The world around you seems sharper, more vivid. You feel... <em>changed</em>.</p> </div> <<run $mentalTraits.push("Blessed")>> <</timed>> <<timed 20s>> <div class="fade-in" style="padding: 30px; margin: 20px auto; max-width: 500px; background: linear-gradient(135deg, #1a0a2e 0%, #2a1a3e 100%); border-radius: 12px; border: 3px solid #ffd700; animation: blessedGlow 3s ease-in-out infinite;"> <p style="color: #ffd700; font-size: 22px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 15px rgba(255,215,0,0.5);">✨ New Trait Acquired ✨</p> <p style="color: #e1bee7; font-size: 20px; font-weight: bold; margin: 0 0 10px 0;">Blessed</p> <p style="color: #aaa; font-size: 14px; margin: 0;">+10 Strength • +10 Intelligence • +10 Charisma • +10 Dexterity</p> </div> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9c27b0 0%, #e1bee7 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px;'>Step Out of the Clearing</div>">> <<goto "MysteriousBeam">> <</link>> </div> <</timed>> <<else>> <!-- NON-EVENT: Standing in the light normally --> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #e1bee7; font-size: 24px; font-weight: bold; text-shadow: 0 0 20px rgba(225,190,231,0.5);">You step into the beam...</p> </div> <<timed 2s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ccc; font-size: 18px; line-height: 1.6;">The light passes through you — or maybe around you. It's hard to tell. You feel a faint tingling on your skin, a whisper of warmth that fades almost as quickly as it appears. Standing here is peaceful, but nothing happens. Whatever this beam is, it doesn't seem to respond to you right now.</p> </div> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #e1bee7; color: #1a1a1a; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Step Back Out</div>">> <<goto "MysteriousBeam">> <</link>> </div> <</timed>> <</if>> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a0a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff9800; text-align: center;">🔨 Building Camp</h1> <!-- Trait check for building --> <<set _canBuild = true>> <<set _buildBlockReason = "">> <<if $physicalTraits && ($physicalTraits.includes("Weak") || $physicalTraits.includes("Clumsy"))>> <<set _canBuild = false>> <<if $physicalTraits.includes("Weak")>> <<set _buildBlockReason = "You try to lash the main support beams together, but you can barely lift them. The materials scatter across the ground. You're just not strong enough for this kind of work.">> <<else>> <<set _buildBlockReason = "Every time you try to tie vines together or balance a support beam, something goes wrong. You drop things, trip over the materials, and accidentally kick apart what you've already assembled. Building is definitely not your strong suit.">> <</if>> <</if>> <<if _canBuild && $mentalTraits>> <<if $mentalTraits.includes("Lazy")>> <<set _canBuild = false>> <<set _buildBlockReason = "You look at the pile of materials, then at the ground, then back at the materials. Nah. This seems like a lot of work. Maybe tomorrow.">> <<elseif $mentalTraits.includes("Bimbo")>> <<set _canBuild = false>> <<set _buildBlockReason = "You try to start building, but get confused about which end of the stick goes up. After accidentally constructing what can only be described as abstract art, you give up.">> <<elseif $mentalTraits.includes("Cowardly")>> <<set _canBuild = false>> <<set _buildBlockReason = "What if it collapses on you? What if building attracts predators? What if the jungle itself is angry at you for trying to build here? The fears pile up faster than the materials, and you can't bring yourself to start.">> <<elseif $mentalTraits.includes("Impatient")>> <<set _canBuild = false>> <<set _buildBlockReason = "You rush through the first few steps, slapping materials together haphazardly. The whole thing collapses immediately. Building something properly requires patience you simply don't have.">> <</if>> <</if>> <<if !_canBuild>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ff6b6b; margin: 0 0 15px 0;">Construction Failed</h3> <p style="color: #ccc; margin: 0; line-height: 1.6;"><<print _buildBlockReason>></p> <p style="color: #aaa; margin: 15px 0 0 0; font-style: italic; font-size: 14px;">Your materials are still intact. You can try again another time.</p> </div> <<else>> <<set $jungleCampBuilt = true>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ff9800; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(255,152,0,0.3);"> <h3 style="color: #ff9800; margin: 0 0 15px 0;">🏕️ Camp Built!</h3> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> You work steadily, lashing sticks together with vines, layering broad jungle leaves for waterproofing, and stacking stones into a fire ring. It takes effort, sweat, and more than a few splinters, but slowly a shelter takes shape. </p> <p style="color: #ccc; margin: 0 0 15px 0; line-height: 1.6;"> When you're finally done, you step back and admire your work. It's rough, it's primitive, but it's solid. A lean-to shelter with enough room to lie down, a cleared area for a fire, and even a crude rack for drying things. Not bad at all. </p> <p style="color: #ff9800; margin: 0; font-weight: bold; text-align: center; font-size: 18px;"> You've built a Jungle Camp! You can now rest here during your explorations. </p> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes eerieFlicker { 0%, 100% { text-shadow: 0 0 10px rgba(74,103,65,0.3); } 25% { text-shadow: 0 0 20px rgba(74,103,65,0.6), 0 0 40px rgba(143,188,106,0.2); } 50% { text-shadow: 0 0 5px rgba(74,103,65,0.1); } 75% { text-shadow: 0 0 25px rgba(74,103,65,0.5), 0 0 50px rgba(143,188,106,0.3); } } @keyframes breathingGlow { 0%, 100% { box-shadow: 0 0 10px rgba(74,103,65,0.2); } 50% { box-shadow: 0 0 25px rgba(74,103,65,0.5), 0 0 50px rgba(143,188,106,0.15); } } @keyframes fogDrift { 0% { background-position: 0% 50%; opacity: 0.03; } 50% { background-position: 100% 50%; opacity: 0.06; } 100% { background-position: 0% 50%; opacity: 0.03; } } .ruins-fog { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; background: radial-gradient(ellipse at center, rgba(143,188,106,0.08) 0%, transparent 70%); animation: fogDrift 8s ease-in-out infinite; } .ruins-title { animation: eerieFlicker 4s ease-in-out infinite; } .ruins-card { animation: breathingGlow 3s ease-in-out infinite; } </style> <div class="ruins-fog"></div> <div style="background: #0a0f0a; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 class="ruins-title" style="color: #4a6741; text-align: center;">🏚️ The Overgrown Ruins</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a1f1a 0%, #2d3a28 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4a6741;"> <p style="color: #bbb; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); line-height: 1.6;"> Crumbling walls of grey-green stone rise around you, draped in curtains of moss and vine. The air is thick and still, carrying the faint smell of wet earth and something older — mineral, ancient, dead. Carved symbols cover every surface: spiraling patterns, animal shapes, geometric forms worn nearly smooth by centuries of rain. Three dark openings lead deeper into the ruins. </p> </div> <!-- Hint carving --> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #333; text-align: center;"> <p style="color: #555; margin: 0; font-style: italic; font-size: 14px; line-height: 1.6;"> On the stone floor near the entrance, partially hidden beneath dead leaves, you notice three symbols carved in a row: a twisting vine... a cracked archway... a descending staircase. Beneath them, barely visible, are scratched numerals: <span style="color: #4a6741;">I • II • III</span> </p> </div> <<if $ruinsPuzzleSolved>> <!-- Already solved - direct access to statue room --> <div class="ruins-card" style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #8fbc6a;"> <p style="color: #8fbc6a; margin: 0 0 15px 0; text-align: center; font-weight: bold;">The path to the inner sanctum is clear. You remember the way.</p> <<link "<div style='background: linear-gradient(135deg, #4a6741 0%, #8fbc6a 100%); color: white; padding: 12px 25px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Enter the Statue Room</div>">> <<advancetime 10>> <<goto "RuinsStatueRoom">> <</link>> </div> <<else>> <!-- Three paths to choose from --> <h2 style="color: #4a6741;">Dark Passages</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Left: The Vine Tunnel --> <<if !$ruinsPathOrder.includes("left")>> <div class="ruins-card" style="border: 3px solid #3a5a35; border-radius: 10px; padding: 15px; background: #1a1f1a; display: flex; flex-direction: column;"> <h3 style="color: #4a6741; margin: 0 0 10px 0;">🪴 The Vine Tunnel</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A narrow passage choked with hanging vines. The walls are carved with spiraling plant motifs.</p> <<link "<div style='background: #3a5a35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter</div>">> <<run $ruinsPathOrder.push("left")>> <<goto "RuinsPathChoice">> <</link>> </div> <</if>> <!-- Center: The Carved Stairway --> <<if !$ruinsPathOrder.includes("center")>> <div class="ruins-card" style="border: 3px solid #3a5a35; border-radius: 10px; padding: 15px; background: #1a1f1a; display: flex; flex-direction: column;"> <h3 style="color: #4a6741; margin: 0 0 10px 0;">🪜 The Carved Stairway</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Stone steps descend into darkness. The walls are etched with geometric patterns.</p> <<link "<div style='background: #3a5a35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend</div>">> <<run $ruinsPathOrder.push("center")>> <<goto "RuinsPathChoice">> <</link>> </div> <</if>> <!-- Right: The Broken Archway --> <<if !$ruinsPathOrder.includes("right")>> <div class="ruins-card" style="border: 3px solid #3a5a35; border-radius: 10px; padding: 15px; background: #1a1f1a; display: flex; flex-direction: column;"> <h3 style="color: #4a6741; margin: 0 0 10px 0;">🏛️ The Broken Archway</h3> <p style="font-size: 14px; color: #888; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A grand archway, cracked down the middle. Animal carvings frame both sides.</p> <<link "<div style='background: #3a5a35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Pass Through</div>">> <<run $ruinsPathOrder.push("right")>> <<goto "RuinsPathChoice">> <</link>> </div> <</if>> </div> <<if $ruinsPathOrder.length > 0>> <div style="text-align: center; margin-bottom: 15px;"> <p style="color: #555; font-style: italic;">Paths explored: <<print $ruinsPathOrder.length>> / 3</p> </div> <</if>> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #2ecc71; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes eerieFlicker { 0%, 100% { text-shadow: 0 0 10px rgba(74,103,65,0.3); } 50% { text-shadow: 0 0 5px rgba(74,103,65,0.1); } } .ruins-fog { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; background: radial-gradient(ellipse at center, rgba(143,188,106,0.08) 0%, transparent 70%); } </style> <div class="ruins-fog"></div> <div style="background: #0a0f0a; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <<set _lastPath = $ruinsPathOrder[$ruinsPathOrder.length - 1]>> <<set _pathCount = $ruinsPathOrder.length>> <!-- Flavor text for the path just entered --> <div style="background: #1a1f1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a6741;"> <<if _lastPath === "left">> <h3 style="color: #4a6741; margin: 0 0 15px 0;">🪴 The Vine Tunnel</h3> <p style="color: #bbb; margin: 0; line-height: 1.6;">You push through the curtain of hanging vines. They brush against your skin like cold fingers. The tunnel is narrow and winding, the walls alive with carved vines that mirror the real ones growing over them. Water drips from somewhere above. The passage opens into a small chamber before continuing onward.</p> <<elseif _lastPath === "center">> <h3 style="color: #4a6741; margin: 0 0 15px 0;">🪜 The Carved Stairway</h3> <p style="color: #bbb; margin: 0; line-height: 1.6;">The stone steps are slick with moisture and age. You descend carefully, one hand on the cold wall. Geometric patterns flow down the walls alongside you — circles within circles, triangles nested like teeth. The air grows cooler. At the bottom, a chamber opens before you, the ceiling lost in shadow above.</p> <<else>> <h3 style="color: #4a6741; margin: 0 0 15px 0;">🏛️ The Broken Archway</h3> <p style="color: #bbb; margin: 0; line-height: 1.6;">You pass beneath the cracked archway. Stone animals stare down from both sides — jaguars, birds, serpents, things you cannot name. The passage beyond is wide but low, forcing you to duck. The carvings here are deeper, more deliberate. Someone wanted these to last. The passage leads to a junction room.</p> <</if>> </div> <<if _pathCount < 3>> <!-- Not all paths explored yet - return to choose another --> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #555; text-align: center;"> <p style="color: #888; margin: 0; font-style: italic;">The passage connects back to the main chamber. You sense there is more to explore. (<<print _pathCount>>/3 paths explored)</p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #4a6741; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Continue Exploring</div>">> <<goto "OvergrownRuins">> <</link>> </div> <<else>> <!-- All 3 paths explored - check if correct order --> <<if $ruinsPathOrder[0] === "left" && $ruinsPathOrder[1] === "right" && $ruinsPathOrder[2] === "center">> <!-- CORRECT ORDER: Vine Tunnel -> Broken Archway -> Carved Stairway --> <div style="background: #1a2a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #8fbc6a; box-shadow: 0 0 30px rgba(143,188,106,0.3);"> <p style="color: #8fbc6a; margin: 0 0 15px 0; font-weight: bold; font-size: 18px; text-align: center;">Something shifts deep within the ruins...</p> <p style="color: #bbb; margin: 0; line-height: 1.6;"> As you complete the final passage, a deep rumbling shakes the stone beneath your feet. Dust falls from the ceiling. The wall at the far end of this chamber — solid stone moments ago — slides open with a grinding roar, revealing a hidden passage beyond. A faint green light pulses from within. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4a6741 0%, #8fbc6a 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 20px rgba(143,188,106,0.4);'>Enter the Hidden Chamber</div>">> <<advancetime 10>> <<goto "RuinsStatueRoom">> <</link>> </div> <<else>> <!-- WRONG ORDER: Dead end --> <div style="background: #2a2020; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #663333;"> <p style="color: #aa6666; margin: 0 0 15px 0; font-weight: bold; font-size: 16px;">Dead End</p> <p style="color: #bbb; margin: 0; line-height: 1.6;"> The final passage leads to a solid stone wall. No hidden doors, no secret switches — just cold, unyielding rock. You trace your fingers over the carvings, but nothing responds. Whatever secret these ruins hold, you have not found the right way. Perhaps the order matters. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #4a6741; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to the Entrance</div>">> <<goto "OvergrownRuins">> <</link>> </div> <</if>> <</if>> </div> <</nobr>>
<<nobr>> <style> @keyframes statueGlow { 0%, 100% { box-shadow: 0 0 15px rgba(143,188,106,0.3); } 50% { box-shadow: 0 0 35px rgba(143,188,106,0.7), 0 0 60px rgba(74,103,65,0.3); } } @keyframes allStatuesGlow { 0%, 100% { box-shadow: 0 0 20px rgba(255,215,0,0.3); } 50% { box-shadow: 0 0 50px rgba(255,215,0,0.7), 0 0 80px rgba(255,215,0,0.3); } } @keyframes eerieFlicker { 0%, 100% { text-shadow: 0 0 10px rgba(74,103,65,0.3); } 50% { text-shadow: 0 0 5px rgba(74,103,65,0.1); } } @keyframes traitGlow { 0%, 100% { box-shadow: 0 0 20px rgba(255,215,0,0.3); } 50% { box-shadow: 0 0 60px rgba(255,215,0,0.7), 0 0 100px rgba(143,188,106,0.4); } } .statue-base { border: 3px solid #555; border-radius: 10px; padding: 15px; background: #1a1f1a; cursor: pointer; text-align: center; transition: all 0.3s ease; user-select: none; } .statue-base:hover { border-color: #4a6741; } .statue-active { border-color: #8fbc6a !important; background: #1a2a1a !important; animation: statueGlow 2s ease-in-out infinite; } .statue-all-lit { border-color: #ffd700 !important; background: linear-gradient(135deg, #1a2a1a 0%, #2a3a1a 100%) !important; animation: allStatuesGlow 2s ease-in-out infinite; } .ruins-fog { position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 0; background: radial-gradient(ellipse at center, rgba(143,188,106,0.08) 0%, transparent 70%); } </style> <div class="ruins-fog"></div> <div style="background: #0a0f0a; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #4a6741; text-align: center; animation: eerieFlicker 4s ease-in-out infinite;">The Inner Sanctum</h1> <<if $ruinsPuzzleSolved>> <!-- Already solved - show lit-up room --> <div style="background: #1a2a1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #ffd700; box-shadow: 0 0 30px rgba(255,215,0,0.3);"> <p style="color: #ffd700; margin: 0 0 15px 0; font-weight: bold; text-align: center; font-size: 18px;">The statues still glow with golden light.</p> <p style="color: #bbb; margin: 0; line-height: 1.6;"> The eight stone animals radiate a warm golden glow that fills the entire chamber. The eyes of the Macaque, the Ocelot, and the Tiger burn brightest of all. The room hums with a quiet energy — ancient, satisfied, at peace. You have already proven yourself here. </p> </div> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 25px;"> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🐒</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Macaque</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🐆</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Ocelot</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🐅</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Tiger</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🐪</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Camel</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🐄</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Cow</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🦃</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Turkey</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🦙</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Alpaca</p></div> <div class="statue-base statue-all-lit"><p style="font-size: 24px; margin: 0;">🐦</p><p style="color: #ffd700; margin: 5px 0 0 0; font-size: 12px;">Finch</p></div> </div> <<if $mentalTraits.includes("Wild")>> <div style="padding: 30px; margin: 20px auto; max-width: 500px; background: linear-gradient(135deg, #1a2a1a 0%, #2a3a1a 100%); border-radius: 12px; border: 3px solid #ffd700; animation: traitGlow 3s ease-in-out infinite;"> <p style="color: #ffd700; font-size: 22px; font-weight: bold; margin: 0 0 10px 0; text-shadow: 0 0 15px rgba(255,215,0,0.5);">✨ Trait Acquired ✨</p> <p style="color: #8fbc6a; font-size: 20px; font-weight: bold; margin: 0 0 10px 0;">Wild</p> <p style="color: #aaa; font-size: 14px; margin: 0;">+5 Strength • +5 Dexterity</p> </div> <<else>> <div id="wildTraitArea" style="text-align: center; margin: 20px auto; max-width: 500px;"> <div style="padding: 25px; background: linear-gradient(135deg, #1a2a1a 0%, #2a3a1a 100%); border-radius: 12px; border: 3px solid #4a6741; animation: traitGlow 3s ease-in-out infinite;"> <p style="color: #8fbc6a; font-size: 18px; margin: 0 0 15px 0;">The three wild statues pulse with golden energy. You feel their power calling to you.</p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4a6741 0%, #8fbc6a 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 20px rgba(143,188,106,0.6);'>✋ Commune with the Statues</div>">> <<replace "#wildTraitArea">> <div style="padding: 30px; background: linear-gradient(135deg, #1a2a1a 0%, #2a3a1a 100%); border-radius: 12px; border: 3px solid #ffd700; animation: traitGlow 3s ease-in-out infinite;"> <p style="color: #ffd700; font-size: 18px; line-height: 1.6; margin: 0 0 15px 0;">You press your palms against the glowing stone. Wild energy surges through you once more — the ferocity of the tiger, the cunning of the ocelot, the agility of the macaque. Your senses sharpen. Your muscles coil with primal strength.</p> <div style="background: #0d0804; padding: 15px; border-radius: 10px; border: 1px solid #ffd700; text-align: center;"> <p style="color: #ffd700; font-size: 22px; font-weight: bold; margin: 0; text-shadow: 0 0 15px rgba(255,215,0,0.8);">✨ You gained the Wild trait! ✨</p> <p style="color: #8fbc6a; font-size: 14px; margin: 5px 0 0 0;">+5 Strength • +5 Dexterity</p> </div> </div> <<run $mentalTraits.push("Wild")>> <</replace>> <</link>> </div> </div> <</if>> <<elseif $ruinsPuzzleAttemptedToday>> <!-- Already attempted today --> <div style="background: #1a1f1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a6741;"> <p style="color: #bbb; margin: 0 0 15px 0; line-height: 1.6;"> The vast circular chamber stretches before you. Eight stone pedestals line the walls, each bearing an animal statue carved from dark stone. </p> </div> <div style="background: #2a2020; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #663333;"> <p style="color: #aa6666; margin: 0; line-height: 1.6;"> The statues stand cold and silent. Whatever energy charged them before has faded. You press your hands against the stone animals, but nothing responds. Perhaps you need to wait and return another day. </p> </div> <<else>> <!-- Active puzzle --> <div style="background: #1a1f1a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #4a6741;"> <p style="color: #bbb; margin: 0; line-height: 1.6;"> The hidden passage opens into a vast circular chamber. Eight stone pedestals line the walls, each bearing an animal statue carved from dark stone. Their eyes are hollow, waiting. The air here feels charged, expectant — as if the room itself is holding its breath. A stone altar in the center bears a worn inscription: <em style="color: #4a6741;">"Awaken only the wild ones. The tame shall not answer."</em> </p> </div> <p style="color: #888; text-align: center; font-style: italic; margin-bottom: 15px;">Click the statues you wish to activate. Choose carefully — you only get one attempt per day.</p> <div id="statueGrid" style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 25px;"> </div> <<run setTimeout(function() { var animals = [ {name: "Macaque", emoji: "🐒"}, {name: "Ocelot", emoji: "🐆"}, {name: "Tiger", emoji: "🐅"}, {name: "Camel", emoji: "🐪"}, {name: "Cow", emoji: "🐄"}, {name: "Turkey", emoji: "🦃"}, {name: "Alpaca", emoji: "🦙"}, {name: "Finch", emoji: "🐦"} ]; for (var i = animals.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = animals[i]; animals[i] = animals[j]; animals[j] = temp; } window._ruinsSelected = new Set(); var grid = document.getElementById("statueGrid"); if (grid) { animals.forEach(function(a) { var div = document.createElement("div"); div.className = "statue-base"; div.id = "statue-" + a.name; div.innerHTML = '<p style="font-size: 28px; margin: 0;">' + a.emoji + '</p><p style="color: #888; margin: 5px 0 0 0; font-size: 13px; font-weight: bold;">' + a.name + '</p>'; div.addEventListener("click", function() { if (window._ruinsSelected.has(a.name)) { window._ruinsSelected.delete(a.name); div.classList.remove("statue-active"); } else { window._ruinsSelected.add(a.name); div.classList.add("statue-active"); } }); grid.appendChild(div); }); } }, 0)>> <!-- Confirm button --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #4a6741 0%, #8fbc6a 100%); color: white; padding: 15px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 16px;'>Activate Selected Statues</div>">> <<set _selected = Array.from(window._ruinsSelected).sort()>> <<if _selected.length === 3 && _selected[0] === "Macaque" && _selected[1] === "Ocelot" && _selected[2] === "Tiger">> <<set $ruinsPuzzleSolved = true>> <<if !$mentalTraits.includes("Wild")>> <<run $mentalTraits.push("Wild")>> <</if>> <<goto "RuinsStatueRoom">> <<else>> <<set $ruinsPuzzleAttemptedToday = true>> <<goto "RuinsStatueRoom">> <</if>> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #4a6741; color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Ruins Entrance</div>">> <<goto "OvergrownRuins">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <<set _hour = Math.floor($timeInMinutes / 60) % 24>> <<set _wasHeat = _hour >= 12 && _hour < 18>> <!-- Apply debuffs immediately --> <<run setup.addDebuff("exhaustion")>> <<if $appearance.hairStyle !== "messy">> <<run setup.setHairMessy()>> <</if>> <div style="background: #000; min-height: 100vh; padding: 40px 20px; text-align: center;"> <div class="fade-in" style="padding: 60px 20px;"> <<if _wasHeat>> <p style="color: #333; font-size: 18px;">The scorching heat overwhelms you... your vision blurs...</p> <<else>> <p style="color: #333; font-size: 18px;">The freezing cold seeps into your bones... your limbs go numb...</p> <</if>> </div> <<timed 2s>> <div class="fade-in" style="padding: 20px;"> <<if _wasHeat>> <p style="color: #444; font-size: 16px;">The desert sand burns beneath you as you collapse. The world fades to white...</p> <<else>> <p style="color: #444; font-size: 16px;">You curl up against the biting wind, shivering uncontrollably. Darkness closes in...</p> <</if>> </div> <</timed>> <<timed 5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #555; font-size: 16px;">Time passes... you drift in and out of consciousness...</p> </div> <</timed>> <<timed 8s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #aaa; font-size: 18px;">You wake up back at <strong style="color: #D2691E;">The Nest</strong>, disoriented and exhausted. Someone — or something — must have dragged you back from the desert.</p> <p style="color: #666; font-size: 14px; font-style: italic; margin-top: 10px;">You gained the <strong style="color: #ff5722;">Exhaustion</strong> debuff.</p> </div> <div style="margin-top: 30px;"> <<link "<div style='background: #D2691E; color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up at The Nest</div>">> <<goto "The Nest">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DesertExplore">> <!-- Post-exploration time check --> <<set _hour = Math.floor($timeInMinutes / 60) % 24>> <<set _isDay = _hour >= 12 && _hour < 18>> <<set _isNight = _hour >= 22 || _hour < 6>> <<if _isDay && !($physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Salamander") || $mentalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Automaton"))>> <<goto "DesertPassout">> <<elseif _isNight && !($physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow"))>> <<goto "DesertPassout">> <</if>> <div style="background: #1a1508; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #c2953a; text-align: center;">🏜️ Desert Exploration</h2> <!-- Resource gathering placeholder for future pickaxe --> <<if $hasPickaxe>> <<set _desertMaterials = 1>> <<if $skills.includes("Heavy Lifting")>><<set _desertMaterials += 1>><</if>> <<if $physicalTraits.includes("Strong") || $physicalTraits.includes("Muscular")>><<set _desertMaterials += 1>><</if>> <<set $desertMaterials = ($desertMaterials || 0) + _desertMaterials>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 2px solid #c2953a; text-align: center;"> <p style="color: #c2953a; margin: 0; font-size: 16px;">⛏️ Gathered <strong><<print _desertMaterials>></strong> desert stone</p> </div> <</if>> <!-- Event roll --> <<set _eventRoll = random(1, 100)>> <div style="padding: 25px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B6914;"> <<if _eventRoll <= 15 && !$discoveredDesertRuins>> <<set $discoveredDesertRuins = true>> <p style="color: #d4a76a; font-size: 16px; line-height: 1.6;"> The wind drops for a moment, and the dunes ahead resolve into something that is not a dune at all: a broken line of stone pillars, and beyond them the buried shoulders of a great ruined structure. The desert has been hiding it in plain sight, and only now does it let you see. </p> <div style="background: #2a2010; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #8B6914; text-align: center;"> <p style="color: #c2953a; font-size: 18px; font-weight: bold; margin: 0;">🏛️ You discovered the Sunken Ruins!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Ruins from the Desert.</p> </div> <<elseif _eventRoll <= 25 && !$foundStoneTablet>> <!-- Discover Stone Tablet --> <<set $foundStoneTablet = true>> <p style="color: #d4a76a; font-size: 16px; line-height: 1.6;"> Cresting a tall dune, you spot something unusual — a flat slab of dark stone jutting from the sand at an angle, its surface covered in deeply carved symbols. The inscriptions are weathered but deliberate, untouched by the erosion that has consumed everything else around it. The tablet radiates an ancient stillness, as though the desert itself has been keeping it hidden. </p> <div style="background: #3a2a1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #c2953a; text-align: center;"> <p style="color: #ffd700; font-size: 18px; font-weight: bold; margin: 0;">📜 You discovered the Stone Tablet!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Stone Tablet from the Desert.</p> </div> <<elseif _eventRoll <= 45 && !$discoveredOasis>> <!-- Discover Oasis --> <<set $discoveredOasis = true>> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> You spot a shimmer on the horizon — another mirage, you think. But as you trudge closer, the image doesn't fade. Palm trees rise from a depression between the dunes, their fronds swaying gently. And then you see it: water. Real, actual water — a spring-fed pool nestled in a sheltered hollow, its surface glittering under the sky. Reeds grow along the edges, and you can see the shadows of fish darting beneath the surface. </p> <div style="background: #1a2a2a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #1abc9c; text-align: center;"> <p style="color: #ffd700; font-size: 18px; font-weight: bold; margin: 0;">🏝️ You discovered the Desert Oasis!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Oasis from the Desert.</p> </div> <<elseif _eventRoll <= 55>> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> You trudge across an endless field of rolling dunes. The sand shifts underfoot, making every step feel twice as heavy. At the crest of the highest dune, you pause to catch your breath and take in the vast, empty expanse around you. Nothing but sand in every direction. </p> <<elseif _eventRoll <= 65>> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> You come across a cluster of jagged rock formations rising from the sand like broken teeth. Wind has carved them into strange, twisted shapes over countless centuries. The shadows they cast provide brief relief from the elements. </p> <<elseif _eventRoll <= 75>> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> A dried riverbed cuts through the sand, its cracked surface telling the story of water that flowed here long ago. Smooth stones line the channel, bleached white by the relentless sun. You follow it for a while, but it leads nowhere. </p> <<elseif _eventRoll <= 82>> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> A small desert lizard darts across the sand in front of you, disappearing behind a rock before you can get a closer look. In the distance, you spot what might be a bird of prey circling high above. Life persists here, even in this desolation. </p> <<elseif _eventRoll <= 90 && Math.floor($dayNumber / 7) !== $lastObeliskWeek_desert>> <!-- 8% CHANCE: Desert Obelisk hint (once per week) --> <<set $lastObeliskWeek_desert = Math.floor($dayNumber / 7)>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-bottom: 15px; border: 2px solid #c0c0c0;"> <h3 style="color: #e0e0e0; margin: 0 0 10px 0;">△ A Strange Obelisk</h3> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> Rising from behind a sand dune like a bone from a grave, you find a sleek white obelisk half-buried in the desert. Its surface is unblemished — no sand erosion, no sun damage. The geometric etchings on its face seem to glow faintly in the harsh light. Four gear symbols are arranged near the top, and beneath them a sequence of numbers: <strong style="color: #ffd700; font-size: 20px; font-family: monospace; letter-spacing: 4px;"><<print $obeliskCodes[2][0]>> <<print $obeliskCodes[2][1]>> <<print $obeliskCodes[2][2]>> <<print $obeliskCodes[2][3]>></strong>. The rest of the obelisk is scoured by something that isn’t wind. </p> <div style="background: #1a1508; padding: 12px; border-radius: 8px; border: 1px solid #888; text-align: center;"> <p style="color: #aaa; font-size: 14px; font-style: italic; margin: 0;">The sand shifts and the obelisk sinks slightly, as if it doesn’t want to be found. You commit the number to memory.</p> </div> </div> <<else>> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> For a moment, you swear you see water shimmering on the horizon — a lake surrounded by palm trees. You walk toward it, but with each step it recedes further, until you realize it was never there at all. Just another mirage in this merciless wasteland. </p> <</if>> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Desert</div>">> <<goto "Desert">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DesertRuins">> <<set _hour = Math.floor($timeInMinutes / 60) % 24>> <<set _isDay = _hour >= 12 && _hour < 18>> <<set _isNight = _hour >= 22 || _hour < 6>> <<if _isDay && !($physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Salamander") || $mentalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Automaton"))>> <<goto "DesertPassout">> <<elseif _isNight && !($physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow"))>> <<goto "DesertPassout">> <</if>> <style> .dr-scene { background: radial-gradient(120% 80% at 50% 8%, #241a0c 0%, #17110a 48%, #0c0906 100%); min-height:100vh; padding:24px 16px 42px; position:relative; overflow:hidden; isolation:isolate; } .dr-h1 { text-align:center; color:#d9b055; font-size:28px; font-family:inherit; font-weight:700; text-shadow:0 0 10px rgba(200,150,50,.3); margin:6px 0 0; letter-spacing:.5px; } .dr-h2 { text-align:center; color:#d9b055; font-size:24px; font-family:inherit; font-weight:700; margin:6px 0 0; } .dr-div { width:120px; height:3px; margin:9px auto 16px; border-radius:3px; background:linear-gradient(90deg,transparent,#b8923c,transparent); } .dr-intro { color:#b7a079; font-family:inherit; text-align:center; max-width:560px; margin:0 auto 22px; line-height:1.6; font-size:15px; } .dr-actions { max-width:560px; margin:0 auto; text-align:center; } .dr-card { padding:16px 18px; border-radius:12px; text-align:center; cursor:pointer; color:#eaddc0; font-weight:bold; font-family:inherit; font-size:17px; border:1px solid #7a5f22; background:linear-gradient(135deg,#241a0b,#191207); box-shadow:0 4px 14px rgba(0,0,0,.45); transition:transform .12s, border-color .12s; } .dr-card:hover { transform:translateY(-2px); border-color:#d9b055; box-shadow:0 6px 20px rgba(0,0,0,.5), 0 0 16px rgba(184,146,60,.22); } .dr-find { max-width:560px; margin:0 auto; padding:20px 22px; border-radius:14px; border:1px solid #6a5320; background:linear-gradient(180deg,#221a0b,#181206); box-shadow:0 6px 22px rgba(0,0,0,.4); } .dr-narr { color:#c7b48c; font-family:inherit; line-height:1.7; margin:0; font-size:15.5px; } .dr-decipher { color:#e6cf8f; font-family:inherit; line-height:1.7; margin:12px 0 0; padding:10px 12px; border-left:3px solid #b8923c; background:rgba(184,146,60,.08); border-radius:0 6px 6px 0; } .dr-found { margin-top:14px; text-align:center; color:#ffd27f; font-weight:bold; font-family:inherit; background:linear-gradient(135deg,#3a2a12,#2a1d10); border:1px solid #d98a3d; border-radius:8px; padding:11px; } .dr-relic { margin-top:14px; text-align:center; color:#7ddf9a; font-weight:bold; font-family:inherit; background:rgba(60,80,40,.25); border:1px solid #6a8a4a; border-radius:8px; padding:11px; } .dr-actions2 { display:flex; gap:12px; justify-content:center; margin-top:20px; flex-wrap:wrap; } .dr-btn { display:inline-block; padding:12px 28px; border-radius:8px; cursor:pointer; font-weight:bold; font-family:inherit; } .dr-btn-gold { background:linear-gradient(135deg,#8B6914,#c2953a); color:#fff; box-shadow:0 3px 10px rgba(0,0,0,.4); } .dr-btn-ghost { background:#241a0b; color:#c8b48a; border:1px solid #4a3a1a; } .dr-btn-ghost:hover { background:#33260f; } .dr-back { text-align:center; margin-top:22px; } .dr-sand { position:absolute; inset:0; pointer-events:none; z-index:-1; } </style> <div class="dr-scene"> <div class="dr-sand"></div> <h1 class="dr-h1">🏺 The Sunken Ruins</h1> <div class="dr-div"></div> <p class="dr-intro">Half swallowed by the dunes, a ring of toppled pillars and buried doorways marks a place older than any story the island still tells. The sand hisses as it shifts between the stones. Whatever stood here was grand once, and it did not fall gently.</p> <div class="dr-actions"> <<link "<div class='dr-card'>Search deeper among the stones</div>">><<goto "DesertRuinsExplore">><</link>> </div> <div class="dr-back"> <<link "<div class='dr-btn dr-btn-ghost'>Back to the Desert</div>">><<goto "Desert">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DesertRuinsExplore">> <<set _hour = Math.floor($timeInMinutes / 60) % 24>> <<set _isDay = _hour >= 12 && _hour < 18>> <<set _isNight = _hour >= 22 || _hour < 6>> <<if _isDay && !($physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Salamander") || $mentalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Automaton"))>> <<goto "DesertPassout">> <<elseif _isNight && !($physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow"))>> <<goto "DesertPassout">> <</if>> <<advancetime 20>> <style> .dr-scene { background: radial-gradient(120% 80% at 50% 8%, #241a0c 0%, #17110a 48%, #0c0906 100%); min-height:100vh; padding:24px 16px 42px; position:relative; overflow:hidden; isolation:isolate; } .dr-h1 { text-align:center; color:#d9b055; font-size:28px; font-family:inherit; font-weight:700; text-shadow:0 0 10px rgba(200,150,50,.3); margin:6px 0 0; letter-spacing:.5px; } .dr-h2 { text-align:center; color:#d9b055; font-size:24px; font-family:inherit; font-weight:700; margin:6px 0 0; } .dr-div { width:120px; height:3px; margin:9px auto 16px; border-radius:3px; background:linear-gradient(90deg,transparent,#b8923c,transparent); } .dr-intro { color:#b7a079; font-family:inherit; text-align:center; max-width:560px; margin:0 auto 22px; line-height:1.6; font-size:15px; } .dr-actions { max-width:560px; margin:0 auto; text-align:center; } .dr-card { padding:16px 18px; border-radius:12px; text-align:center; cursor:pointer; color:#eaddc0; font-weight:bold; font-family:inherit; font-size:17px; border:1px solid #7a5f22; background:linear-gradient(135deg,#241a0b,#191207); box-shadow:0 4px 14px rgba(0,0,0,.45); transition:transform .12s, border-color .12s; } .dr-card:hover { transform:translateY(-2px); border-color:#d9b055; box-shadow:0 6px 20px rgba(0,0,0,.5), 0 0 16px rgba(184,146,60,.22); } .dr-find { max-width:560px; margin:0 auto; padding:20px 22px; border-radius:14px; border:1px solid #6a5320; background:linear-gradient(180deg,#221a0b,#181206); box-shadow:0 6px 22px rgba(0,0,0,.4); } .dr-narr { color:#c7b48c; font-family:inherit; line-height:1.7; margin:0; font-size:15.5px; } .dr-decipher { color:#e6cf8f; font-family:inherit; line-height:1.7; margin:12px 0 0; padding:10px 12px; border-left:3px solid #b8923c; background:rgba(184,146,60,.08); border-radius:0 6px 6px 0; } .dr-found { margin-top:14px; text-align:center; color:#ffd27f; font-weight:bold; font-family:inherit; background:linear-gradient(135deg,#3a2a12,#2a1d10); border:1px solid #d98a3d; border-radius:8px; padding:11px; } .dr-relic { margin-top:14px; text-align:center; color:#7ddf9a; font-weight:bold; font-family:inherit; background:rgba(60,80,40,.25); border:1px solid #6a8a4a; border-radius:8px; padding:11px; } .dr-actions2 { display:flex; gap:12px; justify-content:center; margin-top:20px; flex-wrap:wrap; } .dr-btn { display:inline-block; padding:12px 28px; border-radius:8px; cursor:pointer; font-weight:bold; font-family:inherit; } .dr-btn-gold { background:linear-gradient(135deg,#8B6914,#c2953a); color:#fff; box-shadow:0 3px 10px rgba(0,0,0,.4); } .dr-btn-ghost { background:#241a0b; color:#c8b48a; border:1px solid #4a3a1a; } .dr-btn-ghost:hover { background:#33260f; } .dr-back { text-align:center; margin-top:22px; } .dr-sand { position:absolute; inset:0; pointer-events:none; z-index:-1; } </style> <div class="dr-scene"> <div class="dr-sand"></div> <h2 class="dr-h2">Searching the Ruins</h2> <div class="dr-div"></div> <div class="dr-find"> <<if !$relicInventory>><<set $relicInventory = []>><</if>> <<if $relicFindsDay !== $dayNumber>><<set $relicFindsDay = $dayNumber>><<set $relicFindsToday = 0>><</if>> <<set _heirloomChance = $veradinMet ? 25 : 1>> <<set _hRoll = random(1,100)>> <<set _rRoll = random(1,100)>> <<if !$foundVeradinHeirloom and _hRoll <= _heirloomChance>> <<set $foundVeradinHeirloom = true>> <p class="dr-narr">Your fingers close on something buried at the base of a fallen pillar: a slender clay vase, its glaze long since flaked away but its shape whole, a line of ancient script pressed in a band around its neck. It is old, and it is precious, and it does not belong to the desert. This must be what the smith lost.</p> <<if $skills && $skills.includes("Languages")>> <<set $heirloomDeciphered = true>> <p class="dr-decipher">The letters are worn almost smooth, but the languages you have studied let you pick them apart. The inscription reads: <em>Lloyd is water, water is Lloyd.</em></p> <</if>> <div class="dr-found">🏺 You found Veradin's Heirloom, an inscribed vase. Return it to him at the forge.</div> <<elseif _rRoll <= 5 and $relicFindsToday < 3>> <<set _relicVal = random(50,1500)>> <<set $relicFindsToday = $relicFindsToday + 1>> <<set _relicNames = ["a tarnished bronze idol", "a cracked jade seal", "a string of glass trade beads", "a corroded ceremonial dagger", "a carved bone talisman", "a dust filled scent bottle", "a fragment of a gold mask"]>> <<set _relicName = _relicNames.random()>> <<set $relicInventory.push({ name: _relicName, value: _relicVal })>> <p class="dr-narr">Half buried in the drifted sand you uncover <<print _relicName>>. It is worth something to the right buyer.</p> <div class="dr-relic">Relic recovered, worth about $<<print _relicVal>>.</div> <<else>> <p class="dr-narr">You pick through fallen masonry and drifted sand, but this stretch gives up nothing today.</p> <</if>> </div> <div class="dr-actions2"> <<link "<div class='dr-btn dr-btn-gold'>Search again</div>">><<goto "DesertRuinsExplore">><</link>> <<link "<div class='dr-btn dr-btn-ghost'>Leave the ruins</div>">><<goto "DesertRuins">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "StoneTablet">> <div style="background: #1a1508; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #d4a76a; text-align: center;">📜 The Stone Tablet</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3a2a1a 0%, #2a1a0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B7355;"> <p style="color: #c2953a; font-size: 16px; line-height: 1.6;"> A massive slab of obsidian-dark stone rises from the sand, covered in rows of meticulously carved symbols. The inscriptions seem to glow faintly in certain light, as though the stone itself remembers the hands that shaped it. An altar-like depression sits at its base, smooth and concave, as if designed to receive offerings. </p> </div> <<if $physicalTraits.includes("Guardian") && $mentalTraits.includes("Chosen")>> <!-- Already have both Guardian and Chosen --> <div style="padding: 20px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700; text-align: center;"> <p style="color: #ffd700; font-size: 18px; font-weight: bold;">The tablet's power has already been bestowed upon you.</p> <p style="color: #aaa; font-size: 14px;">The inscriptions have faded to silence. The altar sits empty and cold.</p> </div> <<elseif $mentalTraits.includes("Chosen") && !$physicalTraits.includes("Guardian")>> <!-- Has Chosen but not Guardian - show Guardian path if they have Loyal --> <div style="padding: 20px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700; text-align: center;"> <p style="color: #ffd700; font-size: 18px; font-weight: bold;">The tablet's primary power has already been bestowed upon you.</p> <p style="color: #aaa; font-size: 14px;">Yet... you sense the altar still stirs faintly. There may be another way.</p> </div> <<if $mentalTraits.includes("Loyal")>> <!-- Guardian path available --> <div style="padding: 20px; background: linear-gradient(135deg, #1a2a1a 0%, #0a1a0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: #888; font-size: 13px; font-style: italic; margin-bottom: 10px; text-align: center;">A second inscription glows faintly below the first:</p> <div style="background: #0a0a00; padding: 20px; border-radius: 10px; border: 1px solid #2ecc71;"> <p style="color: #2ecc71; font-size: 16px; line-height: 1.8; font-style: italic; text-align: center;"> “The faithful who would guard this place,<br> Must lay their loyalty upon the stone<br> And pour their fortune without trace—<br> A hundred thousand suns, at least, to atone.” </p> </div> <div id="guardian-offer-area" style="margin-top: 20px; text-align: center;"> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Your loyalty calls to the altar. You feel drawn to place your devotion upon the stone.</p> <p style="color: #ffd700; font-size: 13px; margin-bottom: 15px;">Your gold on hand: $<<print $money.toLocaleString()>></p> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #1a8a4a 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Offer Your Loyalty and All Your Gold</div>">> <<replace "#guardian-offer-area">> <<if $money >= 100000>> <<set _sacrifice = $money>> <<set $money = 0>> <<run $physicalTraits.push("Guardian")>> <div style="padding: 20px; text-align: center;"> <p style="color: #2ecc71; font-size: 18px; font-weight: bold; margin-bottom: 10px;">✨ The altar blazes with emerald light! ✨</p> <p style="color: #d4a76a; font-size: 15px; margin-bottom: 15px;">Your loyalty resonates through the stone as $<<print _sacrifice.toLocaleString()>> in gold dissolves into the altar. The tablet recognizes your devotion and sacrifice. A protective warmth settles over you like ancient armor.</p> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid #2ecc71; display: inline-block;"> <p style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 5px;">🛡️ Guardian Trait Gained!</p> <p style="color: #ccc; font-size: 14px; margin-bottom: 3px;">+10 Strength, +10 Intelligence, +10 Charisma, +10 Dexterity</p> <p style="color: #888; font-size: 12px;">60 Trait Points</p> </div> </div> <<else>> <<set $money = 0>> <div style="padding: 20px; text-align: center;"> <p style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin-bottom: 10px;">The altar flickers... and goes dark.</p> <p style="color: #888; font-size: 15px;">Your gold dissolves into the stone, but the offering was not enough. The altar demanded at least a hundred thousand suns. Your fortune is gone, consumed by the uncaring stone.</p> </div> <</if>> <</replace>> <</link>> </div> </div> <</if>> <<elseif $physicalTraits.includes("Guardian") && !$mentalTraits.includes("Chosen") && ($skills.includes("Foreign Language") || $skills.includes("Languages"))>> <!-- Has Guardian but not Chosen - show guardian message then Chosen path --> <div style="padding: 20px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71; text-align: center;"> <p style="color: #2ecc71; font-size: 18px; font-weight: bold;">The guardian's blessing already protects you.</p> <p style="color: #aaa; font-size: 14px;">Yet the tablet's deeper power still awaits a grander offering...</p> </div> <div style="padding: 20px; background: #1a1a0a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #d4a76a;"> <p style="color: #888; font-size: 14px; font-style: italic; margin-bottom: 10px;">Your knowledge of ancient languages allows you to decipher the inscription...</p> <div style="background: #0a0a00; padding: 20px; border-radius: 10px; border: 1px solid #4a3a2a;"> <p style="color: #d4a76a; font-size: 16px; line-height: 1.8; font-style: italic; text-align: center;"> “Where sun meets sand and fortune smiles,<br> The worthy bear their ocean trials.<br> Bring the rarest from the deep—<br> Every crown the waters keep,<br> Every legend the tides conceal.<br> Ten million suns of golden zeal,<br> And fortune's mark upon your soul.<br> Only the divine and lucky may pay the toll.<br> Place all upon this altar stone,<br> And power beyond measure shall be known.” </p> </div> </div> <!-- Hidden requirements check --> <<run setTimeout(function() { var v = State.variables; var inv = v.fishInventory || []; var mythicalNames = ["Queen Sunfish", "Sally Sunfish", "Sunfish Jones", "Sunfish", "Pinko the Sunfish", "Sunny Sunfish", "King Sunfish", "Empress Sunfish"]; var legendaryNames = ["Noafish", "Trisbane", "Noafish2", "Binah", "Spooner wooner", "Ling the King", "Umafish", "Pegafish", "Roland", "Ultimata Fish", "Middle of Evolution Fish", "FishFish", "Shizufish", "Ayin", "Bronze Seahorse???", "Angela", "Pegafish 2 electric boogaloo", "Yesod", "Cirina"]; var fishInInv = {}; for (var i = 0; i < inv.length; i++) { if (inv[i] && inv[i].name) { fishInInv[inv[i].name] = true; } } var hasMoney = (v.money || 0) >= 10000000; var hasBlessed = v.mentalTraits && v.mentalTraits.includes("Blessed"); var hasLucky = (v.mentalTraits && v.mentalTraits.includes("Lucky")) || (v.physicalTraits && v.physicalTraits.includes("Cupid")) || (v.physicalTraits && v.physicalTraits.includes("Cheshire Cat")); var hasSoul = (v.mentalTraits && v.mentalTraits.includes("Soul")) || (v.physicalTraits && v.physicalTraits.includes("Soul")) || (v.skills && v.skills.includes("Soul")); var hasWild = v.mentalTraits && v.mentalTraits.includes("Wild"); var isOriginalBody = !v.lifeSwapOriginalBodyNPC; var hasDisturbed = v.physicalTraits && v.physicalTraits.includes("Disturbed"); var hasDarkness = v.physicalTraits && v.physicalTraits.includes("Darkness"); var hasHeart = v.physicalTraits && v.physicalTraits.includes("Heart"); var allMythical = true; var allLegendary = true; for (var m = 0; m < mythicalNames.length; m++) { if (!fishInInv[mythicalNames[m]]) allMythical = false; } for (var l = 0; l < legendaryNames.length; l++) { if (!fishInInv[legendaryNames[l]]) allLegendary = false; } /* Store for deposit check */ window._tabletAllMet = hasBlessed && hasLucky && hasSoul && hasWild && hasDisturbed && hasDarkness && hasHeart && isOriginalBody && hasMoney && allMythical && allLegendary; /* Deposit button */ var btn = document.getElementById("tabletDeposit"); if (btn) { if (window._tabletAllMet) { btn.style.opacity = "1"; btn.style.cursor = "pointer"; btn.style.background = "linear-gradient(135deg, #ffd700 0%, #ff6b9d 100%)"; btn.innerHTML = "<strong>Make the Offering</strong>"; } else { btn.style.opacity = "0.4"; btn.style.cursor = "not-allowed"; btn.style.background = "#333"; btn.innerHTML = "<strong>Requirements Not Met</strong>"; } } }, 0)>> <!-- Deposit button --> <div style="text-align: center; margin-bottom: 25px;"> <<if $mentalTraits.includes("Blessed") && $mentalTraits.includes("Lucky") && ($mentalTraits.includes("Soul") || $physicalTraits.includes("Soul") || $skills.includes("Soul")) && $mentalTraits.includes("Wild") && $physicalTraits.includes("Disturbed") && $physicalTraits.includes("Darkness") && $physicalTraits.includes("Heart") && !$lifeSwapOriginalBodyNPC>> <<link "<div id='tabletDeposit' style='padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; color: #1a1a1a; opacity: 0.4; background: #333;'><strong>Checking...</strong></div>">> <<if window._tabletAllMet>> <!-- Remove money --> <<set $money -= 10000000>> <!-- Remove fish from inventory --> <<run (function() { var v = State.variables; var mythicalNames = ["Queen Sunfish", "Sally Sunfish", "Sunfish Jones", "Sunfish", "Pinko the Sunfish", "Sunny Sunfish", "King Sunfish", "Empress Sunfish"]; var legendaryNames = ["Noafish", "Trisbane", "Noafish2", "Binah", "Spooner wooner", "Ling the King", "Umafish", "Pegafish", "Roland", "Ultimata Fish", "Middle of Evolution Fish", "FishFish", "Shizufish", "Ayin", "Bronze Seahorse???", "Angela", "Pegafish 2 electric boogaloo", "Yesod", "Cirina"]; var allNames = mythicalNames.concat(legendaryNames); for (var n = 0; n < allNames.length; n++) { for (var i = 0; i < v.fishInventory.length; i++) { if (v.fishInventory[i].name === allNames[n]) { v.fishInventory.splice(i, 1); break; } } } })()>> <!-- Remove offering traits --> <<run (function() { var v = State.variables; var mentalRemove = ["Blessed", "Lucky", "Soul", "Wild"]; var physicalRemove = ["Disturbed", "Darkness", "Heart"]; for (var i = 0; i < mentalRemove.length; i++) { var idx = v.mentalTraits.indexOf(mentalRemove[i]); if (idx !== -1) v.mentalTraits.splice(idx, 1); } for (var i = 0; i < physicalRemove.length; i++) { var idx = v.physicalTraits.indexOf(physicalRemove[i]); if (idx !== -1) v.physicalTraits.splice(idx, 1); } })()>> <!-- Grant Chosen trait --> <<run $mentalTraits.push("Chosen")>> <<goto "StoneTabletSuccess">> <</if>> <</link>> <<else>> <div style="padding: 15px 40px; border-radius: 10px; display: inline-block; font-size: 16px; color: #888; background: #333; opacity: 0.4;"> <<if !$mentalTraits.includes("Blessed")>> <strong>Only the divine may deposit here</strong> <<elseif !$mentalTraits.includes("Lucky")>> <strong>Only the fortunate may deposit here</strong> <<elseif !($mentalTraits.includes("Soul") || $physicalTraits.includes("Soul") || $skills.includes("Soul"))>> <strong>Only those with a Soul may deposit here</strong> <<elseif !$mentalTraits.includes("Wild")>> <strong>Only the untamed may deposit here</strong> <<elseif $lifeSwapOriginalBodyNPC>> <strong>You must be in your original body to deposit here</strong> <<else>> <strong>Requirements not met</strong> <</if>> </div> <</if>> </div> <<elseif $mentalTraits.includes("Chosen") && !$physicalTraits.includes("Guardian")>> <!-- Has Chosen but not Guardian - show Chosen done + Guardian path --> <div style="padding: 20px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700; text-align: center;"> <p style="color: #ffd700; font-size: 18px; font-weight: bold;">The tablet's primary power has already been bestowed upon you.</p> <p style="color: #aaa; font-size: 14px;">Yet... you sense the altar still stirs faintly. There may be another way.</p> </div> <<if $mentalTraits.includes("Loyal")>> <!-- Guardian path available --> <div style="padding: 20px; background: linear-gradient(135deg, #1a2a1a 0%, #0a1a0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: #888; font-size: 13px; font-style: italic; margin-bottom: 10px; text-align: center;">A second inscription glows faintly below the first:</p> <div style="background: #0a0a00; padding: 20px; border-radius: 10px; border: 1px solid #2ecc71;"> <p style="color: #2ecc71; font-size: 16px; line-height: 1.8; font-style: italic; text-align: center;"> “The faithful who would guard this place,<br> Must lay their loyalty upon the stone<br> And pour their fortune without trace—<br> A hundred thousand suns, at least, to atone.” </p> </div> <div id="guardian-offer-area" style="margin-top: 20px; text-align: center;"> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Your loyalty calls to the altar. You feel drawn to place your devotion upon the stone.</p> <p style="color: #ffd700; font-size: 13px; margin-bottom: 15px;">Your gold on hand: $<<print $money.toLocaleString()>></p> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #1a8a4a 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Offer Your Loyalty and All Your Gold</div>">> <<replace "#guardian-offer-area">> <<if $money >= 100000>> <<set _sacrifice = $money>> <<set $money = 0>> <<run $physicalTraits.push("Guardian")>> <div style="padding: 20px; text-align: center;"> <p style="color: #2ecc71; font-size: 18px; font-weight: bold; margin-bottom: 10px;">✨ The altar blazes with emerald light! ✨</p> <p style="color: #d4a76a; font-size: 15px; margin-bottom: 15px;">Your loyalty resonates through the stone as $<<print _sacrifice.toLocaleString()>> in gold dissolves into the altar. The tablet recognizes your devotion and sacrifice. A protective warmth settles over you like ancient armor.</p> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid #2ecc71; display: inline-block;"> <p style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 5px;">🛡️ Guardian Trait Gained!</p> <p style="color: #ccc; font-size: 14px; margin-bottom: 3px;">+10 Strength, +10 Intelligence, +10 Charisma, +10 Dexterity</p> <p style="color: #888; font-size: 12px;">60 Trait Points</p> </div> </div> <<else>> <<set $money = 0>> <div style="padding: 20px; text-align: center;"> <p style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin-bottom: 10px;">The altar flickers... and goes dark.</p> <p style="color: #888; font-size: 15px;">Your gold dissolves into the stone, but the offering was not enough. The altar demanded at least a hundred thousand suns. Your fortune is gone, consumed by the uncaring stone.</p> </div> <</if>> <</replace>> <</link>> </div> </div> <</if>> <<elseif $mentalTraits.includes("Chosen")>> <!-- Already have Chosen trait (and Guardian) --> <div style="padding: 20px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffd700; text-align: center;"> <p style="color: #ffd700; font-size: 18px; font-weight: bold;">The tablet's power has already been bestowed upon you.</p> <p style="color: #aaa; font-size: 14px;">The inscriptions have faded to silence. The altar sits empty and cold.</p> </div> <<elseif $skills.includes("Foreign Language") || $skills.includes("Languages")>> <!-- Can read the inscription --> <div style="padding: 20px; background: #1a1a0a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #d4a76a;"> <p style="color: #888; font-size: 14px; font-style: italic; margin-bottom: 10px;">Your knowledge of ancient languages allows you to decipher the inscription...</p> <div style="background: #0a0a00; padding: 20px; border-radius: 10px; border: 1px solid #4a3a2a;"> <p style="color: #d4a76a; font-size: 16px; line-height: 1.8; font-style: italic; text-align: center;"> “Where sun meets sand and fortune smiles,<br> The worthy bear their ocean trials.<br> Bring the rarest from the deep—<br> Every crown the waters keep,<br> Every legend the tides conceal.<br> Ten million suns of golden zeal,<br> And fortune's mark upon your soul.<br> Only the divine and lucky may pay the toll.<br> Place all upon this altar stone,<br> And power beyond measure shall be known.” </p> </div> </div> <!-- Hidden requirements check --> <<run setTimeout(function() { var v = State.variables; var inv = v.fishInventory || []; var mythicalNames = ["Queen Sunfish", "Sally Sunfish", "Sunfish Jones", "Sunfish", "Pinko the Sunfish", "Sunny Sunfish", "King Sunfish", "Empress Sunfish"]; var legendaryNames = ["Noafish", "Trisbane", "Noafish2", "Binah", "Spooner wooner", "Ling the King", "Umafish", "Pegafish", "Roland", "Ultimata Fish", "Middle of Evolution Fish", "FishFish", "Shizufish", "Ayin", "Bronze Seahorse???", "Angela", "Pegafish 2 electric boogaloo", "Yesod", "Cirina"]; var fishInInv = {}; for (var i = 0; i < inv.length; i++) { if (inv[i] && inv[i].name) { fishInInv[inv[i].name] = true; } } var hasMoney = (v.money || 0) >= 10000000; var hasBlessed = v.mentalTraits && v.mentalTraits.includes("Blessed"); var hasLucky = (v.mentalTraits && v.mentalTraits.includes("Lucky")) || (v.physicalTraits && v.physicalTraits.includes("Cupid")) || (v.physicalTraits && v.physicalTraits.includes("Cheshire Cat")); var hasSoul = (v.mentalTraits && v.mentalTraits.includes("Soul")) || (v.physicalTraits && v.physicalTraits.includes("Soul")) || (v.skills && v.skills.includes("Soul")); var hasWild = v.mentalTraits && v.mentalTraits.includes("Wild"); var isOriginalBody = !v.lifeSwapOriginalBodyNPC; var hasDisturbed = v.physicalTraits && v.physicalTraits.includes("Disturbed"); var hasDarkness = v.physicalTraits && v.physicalTraits.includes("Darkness"); var hasHeart = v.physicalTraits && v.physicalTraits.includes("Heart"); var allMythical = true; var allLegendary = true; for (var m = 0; m < mythicalNames.length; m++) { if (!fishInInv[mythicalNames[m]]) allMythical = false; } for (var l = 0; l < legendaryNames.length; l++) { if (!fishInInv[legendaryNames[l]]) allLegendary = false; } /* Store for deposit check */ window._tabletAllMet = hasBlessed && hasLucky && hasSoul && hasWild && hasDisturbed && hasDarkness && hasHeart && isOriginalBody && hasMoney && allMythical && allLegendary; /* Deposit button */ var btn = document.getElementById("tabletDeposit"); if (btn) { if (window._tabletAllMet) { btn.style.opacity = "1"; btn.style.cursor = "pointer"; btn.style.background = "linear-gradient(135deg, #ffd700 0%, #ff6b9d 100%)"; btn.innerHTML = "<strong>Make the Offering</strong>"; } else { btn.style.opacity = "0.4"; btn.style.cursor = "not-allowed"; btn.style.background = "#333"; btn.innerHTML = "<strong>Requirements Not Met</strong>"; } } }, 0)>> <!-- Deposit button --> <div style="text-align: center; margin-bottom: 25px;"> <<if $mentalTraits.includes("Blessed") && $mentalTraits.includes("Lucky") && ($mentalTraits.includes("Soul") || $physicalTraits.includes("Soul") || $skills.includes("Soul")) && $mentalTraits.includes("Wild") && $physicalTraits.includes("Disturbed") && $physicalTraits.includes("Darkness") && $physicalTraits.includes("Heart") && !$lifeSwapOriginalBodyNPC>> <<link "<div id='tabletDeposit' style='padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; color: #1a1a1a; opacity: 0.4; background: #333;'><strong>Checking...</strong></div>">> <<if window._tabletAllMet>> <!-- Remove money --> <<set $money -= 10000000>> <!-- Remove fish from inventory --> <<run (function() { var v = State.variables; var mythicalNames = ["Queen Sunfish", "Sally Sunfish", "Sunfish Jones", "Sunfish", "Pinko the Sunfish", "Sunny Sunfish", "King Sunfish", "Empress Sunfish"]; var legendaryNames = ["Noafish", "Trisbane", "Noafish2", "Binah", "Spooner wooner", "Ling the King", "Umafish", "Pegafish", "Roland", "Ultimata Fish", "Middle of Evolution Fish", "FishFish", "Shizufish", "Ayin", "Bronze Seahorse???", "Angela", "Pegafish 2 electric boogaloo", "Yesod", "Cirina"]; var allNames = mythicalNames.concat(legendaryNames); for (var n = 0; n < allNames.length; n++) { for (var i = 0; i < v.fishInventory.length; i++) { if (v.fishInventory[i].name === allNames[n]) { v.fishInventory.splice(i, 1); break; } } } })()>> <!-- Remove offering traits --> <<run (function() { var v = State.variables; var mentalRemove = ["Blessed", "Lucky", "Soul", "Wild"]; var physicalRemove = ["Disturbed", "Darkness", "Heart"]; for (var i = 0; i < mentalRemove.length; i++) { var idx = v.mentalTraits.indexOf(mentalRemove[i]); if (idx !== -1) v.mentalTraits.splice(idx, 1); } for (var i = 0; i < physicalRemove.length; i++) { var idx = v.physicalTraits.indexOf(physicalRemove[i]); if (idx !== -1) v.physicalTraits.splice(idx, 1); } })()>> <!-- Grant Chosen trait --> <<run $mentalTraits.push("Chosen")>> <<goto "StoneTabletSuccess">> <</if>> <</link>> <<else>> <div style="padding: 15px 40px; border-radius: 10px; display: inline-block; font-size: 16px; color: #888; background: #333; opacity: 0.4;"> <<if !$mentalTraits.includes("Blessed")>> <strong>Only the divine may deposit here</strong> <<elseif !$mentalTraits.includes("Lucky")>> <strong>Only the fortunate may deposit here</strong> <<elseif !($mentalTraits.includes("Soul") || $physicalTraits.includes("Soul") || $skills.includes("Soul"))>> <strong>Only those with a Soul may deposit here</strong> <<elseif !$mentalTraits.includes("Wild")>> <strong>Only the untamed may deposit here</strong> <<elseif $lifeSwapOriginalBodyNPC>> <strong>You must be in your original body to deposit here</strong> <<else>> <strong>Requirements not met</strong> <</if>> </div> <</if>> </div> <!-- Guardian Alternative Path --> <<if $mentalTraits.includes("Loyal") && !$physicalTraits.includes("Guardian")>> <div style="padding: 20px; background: linear-gradient(135deg, #1a2a1a 0%, #0a1a0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #2ecc71;"> <p style="color: #888; font-size: 13px; font-style: italic; margin-bottom: 10px; text-align: center;">A second inscription glows faintly below the first:</p> <div style="background: #0a0a00; padding: 20px; border-radius: 10px; border: 1px solid #2ecc71;"> <p style="color: #2ecc71; font-size: 16px; line-height: 1.8; font-style: italic; text-align: center;"> “The faithful who would guard this place,<br> Must lay their loyalty upon the stone<br> And pour their fortune without trace—<br> A hundred thousand suns, at least, to atone.” </p> </div> <div id="guardian-offer-area" style="margin-top: 20px; text-align: center;"> <p style="color: #ccc; font-size: 14px; margin-bottom: 10px;">Your loyalty calls to the altar. You feel drawn to place your devotion upon the stone first—before any other offering.</p> <p style="color: #ffd700; font-size: 13px; margin-bottom: 15px;">Your gold on hand: $<<print $money.toLocaleString()>></p> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #1a8a4a 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Offer Your Loyalty and All Your Gold</div>">> <<replace "#guardian-offer-area">> <<if $money >= 100000>> <<set _sacrifice = $money>> <<set $money = 0>> <<run $physicalTraits.push("Guardian")>> <div style="padding: 20px; text-align: center;"> <p style="color: #2ecc71; font-size: 18px; font-weight: bold; margin-bottom: 10px;">✨ The altar blazes with emerald light! ✨</p> <p style="color: #d4a76a; font-size: 15px; margin-bottom: 15px;">Your loyalty resonates through the stone as $<<print _sacrifice.toLocaleString()>> in gold dissolves into the altar. The tablet recognizes your devotion and sacrifice. A protective warmth settles over you like ancient armor.</p> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid #2ecc71; display: inline-block;"> <p style="color: #2ecc71; font-size: 20px; font-weight: bold; margin-bottom: 5px;">🛡️ Guardian Trait Gained!</p> <p style="color: #ccc; font-size: 14px; margin-bottom: 3px;">+10 Strength, +10 Intelligence, +10 Charisma, +10 Dexterity</p> <p style="color: #888; font-size: 12px;">60 Trait Points</p> </div> </div> <<else>> <<set $money = 0>> <div style="padding: 20px; text-align: center;"> <p style="color: #ff6b6b; font-size: 18px; font-weight: bold; margin-bottom: 10px;">The altar flickers... and goes dark.</p> <p style="color: #888; font-size: 15px;">Your gold dissolves into the stone, but the offering was not enough. The altar demanded at least a hundred thousand suns. Your fortune is gone, consumed by the uncaring stone.</p> </div> <</if>> <</replace>> <</link>> </div> </div> <</if>> <<else>> <!-- Cannot read the inscription --> <div style="padding: 20px; background: #2a2a1a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #555;"> <p style="color: #888; font-size: 16px; line-height: 1.6; text-align: center;"> Strange symbols are carved deep into the stone surface. The writing is in an ancient language you cannot read. Perhaps someone with knowledge of <strong style="color: #d4a76a;">foreign languages</strong> could make sense of it. </p> </div> <</if>> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Desert</div>">> <<goto "Desert">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes goldenPulse { 0%, 100% { box-shadow: 0 0 20px rgba(255,215,0,0.3); } 50% { box-shadow: 0 0 60px rgba(255,215,0,0.8), 0 0 100px rgba(255,107,157,0.3); } } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <div style="background: #000; min-height: 100vh; padding: 40px 20px; text-align: center;"> <div class="fade-in" style="padding: 40px 20px;"> <p style="color: #d4a76a; font-size: 18px;">You place the fish upon the altar one by one... the mythical sunfish gleaming in the desert light... the legendary creatures of the deep...</p> </div> <<timed 3s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ffd700; font-size: 18px;">The gold coins pile high — ten million dollars worth of fortune, glinting as they cascade into the altar's basin.</p> </div> <</timed>> <<timed 6s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ff6b9d; font-size: 20px; font-weight: bold;">The tablet erupts with golden light. Ancient symbols blaze to life across its surface, each one igniting the next in a chain that spirals outward.</p> </div> <</timed>> <<timed 9s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #ffd700; font-size: 18px;">The light envelops you completely. Every cell in your body resonates with an ancient power. You feel yourself changing — not physically, but fundamentally. Something deep within you has been unlocked.</p> </div> <</timed>> <<timed 12s>> <div class="fade-in" style="padding: 30px 20px;"> <div style="background: linear-gradient(135deg, #2a1a0a 0%, #1a0a00 100%); padding: 30px; border-radius: 15px; border: 3px solid #ffd700; animation: goldenPulse 3s ease-in-out infinite; display: inline-block;"> <p style="color: #ffd700; font-size: 24px; font-weight: bold; margin: 0 0 10px 0;">✨ CHOSEN ✨</p> <p style="color: #d4a76a; font-size: 16px; margin: 0 0 5px 0;">Anointed by the ancient desert altar</p> <p style="color: #ff6b9d; font-size: 14px; margin: 0;">+100 Strength | +100 Intelligence | +100 Charisma | +100 Dexterity</p> <p style="color: #888; font-size: 12px; margin: 5px 0 0 0;">2347 Trait Points</p> </div> </div> <div style="margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #ff6b9d 100%); color: #1a1a1a; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to the Desert</div>">> <<goto "Desert">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Mountains")>> <<run $visitedLocations.push("Mountains")>> <</if>> <<set $lastLocation = "Mountains">> <style> @keyframes snowDrift { 0%, 100% { opacity: 0.3; transform: translateX(0px); } 50% { opacity: 0.5; transform: translateX(3px); } } .mountain-snow-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 0%, rgba(200,210,230,0.06) 0%, transparent 70%); pointer-events: none; z-index: 0; animation: snowDrift 6s ease-in-out infinite; } </style> <div class="mountain-snow-overlay"></div> <div style="background: #0a0f1a; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #8B9DAF; text-align: center;">⛰️ The Mountains</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Mountains.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #8B9DAF; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Mountains"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #3a4a5c 0%, #2a3a4c 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B9DAF;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> A rugged mountain trail winds through alpine terrain, switchbacking between grey stone outcrops and patches of hardy scrub. The air is noticeably thinner up here, each breath coming a little harder. Above you, the peaks are crowned with snow, their jagged silhouettes cutting against the sky. The distant sound of wind through rocky passes carries an almost musical quality. </p> </div> <h2 style="color: #8B9DAF;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Explore the Mountains --> <div style="border: 3px solid #6B7B8F; border-radius: 10px; padding: 15px; background: #1a2030; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8B9DAF; margin: 0 0 10px 0;">⛰️ Explore the Mountains</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Trek deeper into the mountain trails. There could be anything hidden among the peaks and valleys.</p> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Explore (30 min)</div>">> <<advancetime 30>> <<goto "MountainExplore">> <</link>> </div> <!-- Hot Spring (only if discovered) --> <<if $discoveredHotSpring>> <div style="border: 3px solid #1abc9c; border-radius: 10px; padding: 15px; background: #1a2030; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(26,188,156,0.15); display: flex; flex-direction: column;"> <h3 style="color: #1abc9c; margin: 0 0 10px 0;">♨️ Abandoned Hot Spring</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Steam rises from a natural pool near a crumbling old building, high up in the snowy peaks.</p> <<link "<div style='background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Hot Spring</div>">> <<goto "MountainHotSpring">> <</link>> </div> <</if>> <!-- Veradin's Forge (only if discovered) --> <<if $discoveredForge>> <div style="border: 3px solid #d98a3d; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a1d10 0%, #1a1008 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(217,138,61,0.15); display: flex; flex-direction: column;"> <h3 style="color: #d98a3d; margin: 0 0 10px 0;">⚒️ Veradin's Forge</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A squat stone forge wedged into the mountain flank, its chimney breathing embers into the cold air.</p> <<link "<div style='background:linear-gradient(135deg,#7a4a1e 0%,#d98a3d 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit the Forge</div>">> <<goto "VeradinForge">> <</link>> </div> <</if>> <!-- Fox Shrine (only if discovered) --> <<if $discoveredShrine>> <div style="border: 3px solid #e67e22; border-radius: 10px; padding: 15px; background: #1a2030; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(230,126,34,0.15); display: flex; flex-direction: column;"> <h3 style="color: #e67e22; margin: 0 0 10px 0;">⛩️ Fox Shrine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Ancient stone stairs lead up through snow and ice to a mysterious shrine with a nine-tailed fox statue.</p> <<link "<div style='background: linear-gradient(135deg, #e67e22 0%, #d35400 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Climb to the Shrine</div>">> <<goto "MountainShrine">> <</link>> </div> <</if>> <!-- Mysterious Clean Room (only if discovered) --> <<if $discoveredCleanRoom>> <div style="border: 3px solid #cd7f32; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #2a1a0a 0%, #1a1008 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(205,127,50,0.2); display: flex; flex-direction: column;"> <h3 style="color: #cd7f32; margin: 0 0 10px 0;">⚙️ Mysterious Room</h3> <<if $cleanRoomSolved>> <p style="font-size: 14px; color: #c9a06c; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A chamber of brass and copper hidden within the mountain. The gear lock stands open. Ancient clockwork hums within.</p> <<else>> <p style="font-size: 14px; color: #c9a06c; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A chamber of brass pipes and copper gears hidden impossibly between the mountain boulders. A massive gear lock bars the inner door.</p> <</if>> <<link "<div style='background: linear-gradient(135deg, #cd7f32 0%, #8B6914 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Investigate</div>">> <<goto "MountainCleanRoom">> <</link>> </div> <</if>> <!-- The Manor (mysteriously appears at night) --> <<if getTimeOfDay() === "evening" || getTimeOfDay() === "night">> <style> @keyframes manorPulse { 0%, 100% { box-shadow: 0 0 10px rgba(0,0,0,0.4), 0 0 20px rgba(0,0,0,0.3); } 50% { box-shadow: 0 0 20px rgba(0,0,0,0.9), 0 0 30px rgba(0,0,0,0.6); } } .manor-glow { animation: manorPulse 3s ease-in-out infinite; } </style> <div class="manor-glow" style="border: 3px solid #222; border-radius: 10px; padding: 15px; background: #0a0a0a; display: flex; flex-direction: column;"> <h3 style="color: #888; margin: 0 0 10px 0;">🏚️ The Manor</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A decaying manor house looms in a dark hollow below the mountain trail. It wasn’t there during the day. You’re certain of it.</p> <<link "<div style='background: linear-gradient(135deg, #222 0%, #111 100%); color: #999; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Approach the Manor</div>">> <<goto "Manor">> <</link>> </div> <</if>> <!-- The Cliff (only if discovered) --> <<if $discoveredCliff>> <div style="border: 3px solid #8B0000; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #1a0a0a 0%, #0a0505 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(139,0,0,0.2); display: flex; flex-direction: column;"> <h3 style="color: #8B0000; margin: 0 0 10px 0;">🧗 The Cliff</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A sheer drop into a dizzying abyss. The wind howls up from the void below. Something dark waits at the bottom.</p> <<link "<div style='background: linear-gradient(135deg, #8B0000 0%, #4a0000 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Approach the Edge</div>">> <<goto "MountainCliff">> <</link>> </div> <</if>> <!-- Climb to the Peak (always visible) --> <div style="border: 3px solid #f1c40f; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #1a1a2a 0%, #0a0a1a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(241,196,15,0.15); display: flex; flex-direction: column;"> <h3 style="color: #f1c40f; margin: 0 0 10px 0;">⚡ Climb to the Peak</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Scale the treacherous path to the mountain’s highest point. The summit pierces the clouds above.</p> <<link "<div style='background: linear-gradient(135deg, #f1c40f 0%, #d4ac0d 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Begin the Climb (4 hours)</div>">> <<advancetime 240>> <<goto "MountainPeak">> <</link>> </div> <!-- Cragside Quarry (only if discovered) --> <<if $discoveredCragside>> <div style="border: 3px solid #8B9DAF; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #1a2030 0%, #0a1020 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #a8b8c8; margin: 0 0 10px 0;">⛰ Cragside Quarry</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A vertical shaft cut into mountain granite, eight floors deep. Silver and emerald veins lace the cold stone. Loose rock falls without warning.</p> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend the Quarry (30 min)</div>">> <<advancetime 30>> <<goto "CragsideQuarryEntrance">> <</link>> </div> <</if>> <!-- Frostspire (only if discovered) --> <<if $discoveredFrostspire>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(126,200,227,0.15); display: flex; flex-direction: column;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">❄ Frostspire</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">An ice-bound shaft in the highest peak, ten floors deep. Mithril, aquamarine, and diamond hide in the frozen rock. Cold-tolerant body or gear required to even step inside.</p> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Climb to the Frostspire (1 hr)</div>">> <<advancetime 60>> <<goto "FrostspireEntrance">> <</link>> </div> <</if>> <!-- Tundra of Aeternus (only if discovered) --> <<if $discoveredTundra>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(126,200,227,0.15); display: flex; flex-direction: column;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">❄️ Tundra of Aeternus</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The frozen country beyond the summit. An endless white tundra on the far side of the mountain, silent and bitterly cold. The crossing takes hours over the peak.</p> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Cross to the Tundra (3 hours)</div>">> <<advancetime 180>> <<goto "TundraOfAeternus">> <</link>> </div> <</if>> </div> <h2 style="color: #8B9DAF;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Return to The Nest --> <div style="border: 3px solid #D2691E; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #D2691E; margin: 0 0 10px 0;">🫹 The Nest</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Head back down the mountain trail to the giant nest.</p> <<link "<div style='background: linear-gradient(135deg, #D2691E 0%, #8B4513 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend to The Nest (4 hrs)</div>">> <<advancetime 240>> <<goto "The Nest">> <</link>> </div> <!-- Head to the Volcano --> <div style="border: 3px solid #ff5722; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff5722; margin: 0 0 10px 0;">🌋 The Volcano</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A trail of black basalt leads toward the smoldering volcano. Heat rises from its direction.</p> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Head to the Volcano (4 hrs)</div>">> <<advancetime 240>> <<goto "Volcano">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MountainExplore">> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #8B9DAF; text-align: center;">⛰️ Mountain Exploration</h2> <<set _eventRoll = random(1, 100)>> <!-- Manor night exploration priority check --> <<set _isNightTime = (getTimeOfDay() === "evening" || getTimeOfDay() === "night")>> <<set _forceManor = false>> <<if _isNightTime && !$discoveredManor && $discoveredHotSpring && $discoveredShrine && $discoveredCleanRoom && $discoveredCliff>> <<set _forceManor = true>> <</if>> <div style="padding: 25px; background: #1a2030; border-radius: 15px; margin-bottom: 25px; border: 2px solid #5C6B7A;"> <<if _forceManor>> <!-- Manor Discovery (priority check) --> <<set $discoveredManor = true>> <p style="color: #9b59b6; font-size: 16px; line-height: 1.6;"> The moonlight catches something you've never noticed before — a narrow path branching off the main trail, half-hidden by dense pine branches. You push through, and the trees close in around you, blocking out most of the pale light. The path winds downward through a dark hollow before opening into a small clearing. </p> <p style="color: #9b59b6; font-size: 16px; line-height: 1.6;"> A wrought-iron gate stands before you, its bars twisted with age and draped in dead ivy. Beyond it looms a manor house — grand and imposing, but clearly abandoned. The windows stare out like empty eye sockets. Overgrown hedges claw at the stone walls. The front door bears a massive ornate lock, rusted but unyielding. You try it, but it won't budge. The silence here is oppressive, broken only by the occasional creak of old wood settling. Something about this place feels deeply, fundamentally wrong. </p> <div style="background: #1a0a2a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #6a0dad; text-align: center;"> <p style="color: #9b59b6; font-size: 18px; font-weight: bold; margin: 0;">🏚️ You discovered the Manor!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">The Manor appears in the Mountains at night.</p> </div> <<elseif !$discoveredForge and ($mentalTraits.includes("Perceptive") || $physicalTraits.includes("Perceptive")) and _eventRoll <= 30>> <<set $discoveredForge = true>> <p style="color:#d98a3d; font-size:16px; line-height:1.6;"> Something your sharper eye catches that others would miss: a thread of orange smoke rising from a fold in the rock where no smoke should be. You follow it to a narrow cleft, and heat rolls out to meet you. Wedged into the mountain flank is a squat stone forge, its chimney breathing embers into the cold air. A broad shouldered dwarf works an anvil inside, orange hair matted with sweat, and he has not yet noticed you. </p> <div style="background:#2a1d10; padding:15px; border-radius:10px; margin-top:15px; border:1px solid #d98a3d; text-align:center;"> <p style="color:#d98a3d; font-size:18px; font-weight:bold; margin:0;">⚒️ You discovered Veradin's Forge!</p> <p style="color:#aaa; font-size:14px; margin:5px 0 0 0;">You can now visit the Forge from the Mountains.</p> </div> <<elseif _eventRoll <= 20 && !$discoveredHotSpring>> <!-- Hot Spring Discovery --> <<set $discoveredHotSpring = true>> <p style="color: #1abc9c; font-size: 16px; line-height: 1.6;"> As you climb higher along a narrow ridge, the air grows biting cold — but then you catch the scent of sulfur and warmth. Rounding a snow-covered outcrop, you discover something extraordinary: a natural hot spring, its turquoise water steaming against the frozen landscape. Beside it sits a decrepit wooden building, its walls dark with age, its windows like hollow eyes staring out at the mountain. The spring and the building feel like they've been waiting here, forgotten, for a very long time. </p> <div style="background: #0a1a2a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #1abc9c; text-align: center;"> <p style="color: #1abc9c; font-size: 18px; font-weight: bold; margin: 0;">♨️ You discovered the Abandoned Hot Spring!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Hot Spring from the Mountains.</p> </div> <<elseif _eventRoll <= 35 && !$discoveredShrine>> <!-- Fox Shrine Discovery --> <<set $discoveredShrine = true>> <p style="color: #e67e22; font-size: 16px; line-height: 1.6;"> Pushing through a curtain of snow-laden branches, you stumble upon something unexpected — a stone staircase, ancient and weather-worn, carved directly into the mountainside. Each step is etched with faded symbols. You climb carefully through swirling snow until you reach a small plateau. There, sheltered by a ring of frost-covered pines, stands a shrine. At its center sits a beautifully carved fox statue, its nine flowing tails each tipped with a different colored gemstone that catches the pale mountain light. The air here feels different — still, reverent, as if the mountain itself is holding its breath. </p> <div style="background: #1a1500; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #e67e22; text-align: center;"> <p style="color: #e67e22; font-size: 18px; font-weight: bold; margin: 0;">⛩️ You discovered the Fox Shrine!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Fox Shrine from the Mountains.</p> </div> <<elseif _eventRoll <= 45 && !$discoveredCleanRoom>> <!-- Clean Room Discovery --> <<set $discoveredCleanRoom = true>> <p style="color: #cd7f32; font-size: 16px; line-height: 1.6;"> Squeezing between two massive boulders, you find something that makes no sense. Nestled in a natural alcove in the rock face is a room — but not a natural one. Copper pipes run along the ceiling. The floor is riveted steel, dark with age and oil. A gas lamp flickers overhead, casting amber light across surfaces of brass and iron. The air smells metallic, like old machinery. On the far wall stands a massive steel door adorned with interlocking gears of varying sizes. Some turn slowly; most are still. Whatever civilization built this place, they understood things about mechanics that the modern world has forgotten. </p> <div style="background: #1a1008; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #cd7f32; text-align: center;"> <p style="color: #cd7f32; font-size: 18px; font-weight: bold; margin: 0;">⚙️ You discovered a Mysterious Room!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now investigate the Mysterious Room from the Mountains.</p> </div> <<elseif _eventRoll <= 52 && !$discoveredCragside>> <!-- Cragside Quarry Discovery --> <<set $discoveredCragside = true>> <p style="color: #a8b8c8; font-size: 16px; line-height: 1.6;"> A switchback path drops down between two granite shoulders and ends at a wide gash in the mountain face. Old pulleys hang from hooks eaten through with rust. Carts lie on their sides at the entrance, half buried in scree. Somewhere deep in the dark, water drips on stone. The shaft is open. The shaft is waiting. </p> <div style="background: #0a1018; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #8B9DAF; text-align: center;"> <p style="color: #a8b8c8; font-size: 18px; font-weight: bold; margin: 0;">⛰ You discovered Cragside Quarry!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now mine at Cragside Quarry from the Mountains.</p> </div> <<elseif _eventRoll <= 58 && !$discoveredFrostspire>> <!-- Frostspire Discovery --> <<set $discoveredFrostspire = true>> <p style="color: #aee0f5; font-size: 16px; line-height: 1.6;"> The air thins as you climb. Ice crusts every rock. Around a bend you find a steel door set into a tower of ice, the whole face of it a single shaft driven straight up the spire. Pickaxe marks are still fresh in the rime around the entrance. Whoever was here last left in a hurry. </p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄ You discovered Frostspire!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now mine at Frostspire from the Mountains.</p> </div> <<elseif _eventRoll <= 75>> <!-- Mountain wildlife --> <p style="color: #8B9DAF; font-size: 16px; line-height: 1.6;"> A family of mountain goats picks its way across a sheer rock face with impossible grace, their hooves finding purchase on ledges you can barely see. High above, a golden eagle circles in wide, patient arcs, riding thermals that sweep up the mountainside. Life thrives here in ways you wouldn't expect — small, tough, and perfectly adapted to the harsh terrain. </p> <<elseif _eventRoll <= 85>> <!-- Rocky overlook --> <p style="color: #8B9DAF; font-size: 16px; line-height: 1.6;"> You haul yourself up a steep scramble and emerge onto a rocky outcrop with a breathtaking view. The entire island stretches out below you — the dark canopy of the jungle, the golden smear of the desert beyond it, the glittering coastline, and the distant rooftops of Sunfish City catching the light. From up here, it all looks impossibly small. The wind tugs at you, and for a moment you feel completely untethered from the world below. </p> <<elseif _eventRoll <= 91>> <!-- Alpine meadow --> <p style="color: #8B9DAF; font-size: 16px; line-height: 1.6;"> Tucked between two ridges, you discover a small alpine meadow — an unlikely patch of green among the grey stone. Tiny wildflowers in pale purple and white grow between the rocks, bending in the mountain breeze. A thin stream of snowmelt trickles through the center, cold and crystal clear. It's a quiet, beautiful place that feels hidden from the rest of the world. </p> <<elseif _eventRoll <= 95 && Math.floor($dayNumber / 7) !== $lastObeliskWeek_mountain>> <!-- Mountain Obelisk hint (once per week) --> <<set $lastObeliskWeek_mountain = Math.floor($dayNumber / 7)>> <div style="background: #1a2030; padding: 15px; border-radius: 10px; margin-bottom: 15px; border: 2px solid #c0c0c0;"> <h3 style="color: #e0e0e0; margin: 0 0 10px 0;">△ A Strange Obelisk</h3> <p style="color: #8B9DAF; font-size: 16px; line-height: 1.6;"> Wedged into a crevice between two boulders, catching the light at just the right angle, you spot a sleek white obelisk. Its polished surface is startling against the rough mountain stone. Geometric patterns trace across it like a circuit board. Near the base, four gear symbols sit in a row with a sequence of numbers etched below: <strong style="color: #ffd700; font-size: 20px; font-family: monospace; letter-spacing: 4px;"><<print $obeliskCodes[4][0]>> <<print $obeliskCodes[4][1]>> <<print $obeliskCodes[4][2]>> <<print $obeliskCodes[4][3]>></strong>. The rest of the surface is blank — or perhaps just hidden. </p> <div style="background: #0a0f1a; padding: 12px; border-radius: 8px; border: 1px solid #888; text-align: center;"> <p style="color: #aaa; font-size: 14px; font-style: italic; margin: 0;">A deep vibration pulses through the rock for just a moment, then stops. You note the number and continue your climb.</p> </div> </div> <<elseif _eventRoll <= 99 && !$discoveredCliff>> <!-- Cliff Discovery --> <<set $discoveredCliff = true>> <p style="color: #8B0000; font-size: 16px; line-height: 1.6;"> The trail narrows to almost nothing as you push higher along a knife-edge ridge. Loose scree shifts under your boots. Then, abruptly, the ground just... ends. You stumble to a halt, heart slamming against your ribs. Before you yawns a sheer cliff face, dropping away into a dizzying void. Far, far below — at least a thousand feet, maybe three hundred meters — you can just make out the rocky ground at the bottom, shrouded in a faint, unnatural haze. The wind screams up the cliff face, tugging at your clothes. Something about this place feels wrong. Ancient. Hungry. </p> <div style="background: #1a0a0a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #8B0000; text-align: center;"> <p style="color: #8B0000; font-size: 18px; font-weight: bold; margin: 0;">🧗 You discovered the Cliff!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Cliff from the Mountains.</p> </div> <<else>> <!-- Rockslide near-miss --> <p style="color: #8B9DAF; font-size: 16px; line-height: 1.6;"> A sharp crack echoes across the mountainside. You freeze, and a moment later a cascade of loose rocks tumbles down a slope just ahead of you, clattering and bouncing off the trail in a cloud of dust. If you'd been ten seconds faster, you'd have been right in the middle of it. Your heart hammers as the last few pebbles settle. The mountains don't care if you're paying attention or not. </p> <</if>> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MountainHotSpring">> <<set _hasColdTolerance = ($physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow"))>> <<if !_hasColdTolerance>> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #1abc9c; text-align: center;">♨️ Abandoned Hot Spring</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a2a3a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ba3c9;"> <p style="color: #7ba3c9; font-size: 16px; line-height: 1.6;"> You begin the climb toward the hot spring, but the biting cold quickly becomes unbearable. The wind cuts through your clothing like a knife, and your fingers go numb within minutes. Ice coats every surface, making each step treacherous. You can see the steam rising from the spring above, tantalizingly close, but your body simply cannot endure the cold long enough to reach it. You need some kind of physical toughness or cold tolerance to make this journey. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <<else>> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #1abc9c; text-align: center;">♨️ Abandoned Hot Spring</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a3a 0%, #0a2a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1abc9c;"> <p style="color: #b0d0c0; font-size: 16px; line-height: 1.6;"> Steam curls lazily from the surface of the hot spring, the turquoise water impossibly inviting against the frozen landscape. The warmth radiating from the pool creates a pocket of comfort in the bitter mountain air. Snow falls gently around the edges but melts before it touches the water. </p> <p style="color: #b0d0c0; font-size: 16px; line-height: 1.6; margin-top: 10px;"> Beside the spring, a weathered wooden building looms. Its dark timber walls are streaked with age, and the windows are black and empty. The door hangs slightly ajar, creaking faintly in the wind. Something about it feels... off. </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Rest in Hot Spring --> <div style="border: 3px solid #1abc9c; border-radius: 10px; padding: 15px; background: #1a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #1abc9c; margin: 0 0 10px 0;">♨️ Rest in the Hot Spring</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Soak in the warm, mineral-rich water. It looks like it could wash away all your worries — and then some.</p> <<link "<div style='background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Soak (60 min)</div>">> <<if !$lucidRestActive>><<advancetime 60>><</if>> <<goto "MountainHotSpringRest">> <</link>> </div> <!-- Explore the Building --> <div style="border: 3px solid #555; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.6); display: flex; flex-direction: column;"> <h3 style="color: #888; margin: 0 0 10px 0;">🏚️ Explore the Building</h3> <p style="font-size: 14px; color: #777; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The abandoned building sits dark and silent. The door is ajar. Something compels you to look inside.</p> <<link "<div style='background: linear-gradient(135deg, #555 0%, #333 100%); color: #ccc; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Building</div>">> <<goto "MountainAbandonedBuilding">> <</link>> </div> </div> <!-- Cup of Demons bowl --> <div style="border: 3px solid #c4a040; border-radius: 10px; padding: 15px; background: #241f10; box-shadow: 0 0 18px rgba(196,160,64,0.20); margin-bottom: 25px;"> <h3 style="color: #c4a040; margin: 0 0 10px 0;">🍶 A Deep Bowl with Fangs</h3> <p style="font-size: 14px; color: #ddd4b8; margin: 0 0 12px 0; line-height: 1.5;">A deep stone bowl set into the rocks beside the spring. Hot mist rises around it. Two fangs are carved into its rim.</p> <<if $drunkCupOfDemons && (!$physicalTraits || $physicalTraits.indexOf("Oni") === -1) && setup.oni && setup.oni.isPlayerInOwnBody && setup.oni.isPlayerInOwnBody()>> <p style="font-size: 14px; color: #e8c878; margin: 0 0 12px 0; line-height: 1.5; font-style: italic;">The bowl is empty but the sake still moves in you. The ritual is unfinished. Step closer.</p> <<link "<div style='background: linear-gradient(135deg, #c4a040 0%, #8a6a20 100%); color: #1a1308; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Finish the ritual</div>">> <<goto "OniTransformationCutscene">> <</link>> <<elseif $giftInventory && ($giftInventory.sake_bottle || 0) > 0>> <<link "<div style='background: linear-gradient(135deg, #c4a040 0%, #8a6a20 100%); color: #1a1308; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Pour sake into the bowl</div>">> <<run setup.oni && setup.oni.tryCupOfDemons && setup.oni.tryCupOfDemons()>> <<if !$drunkCupOfDemons>><<goto "MountainHotSpring">><</if>> <</link>> <<else>> <p style="font-size: 13px; color: #888; font-style: italic; margin: 0;">You have no sake to pour.</p> <</if>> <<if $oniLastBowlMessage>> <p style="font-size: 14px; color: #ddd; font-style: italic; margin: 12px 0 0 0; line-height: 1.5;">$oniLastBowlMessage</p> <</if>> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "MountainHotSpringRest">> <!-- Apply buffs --> <<run setup.removeDebuff("exhaustion")>> <<set _dreamRoute = setup.witchSpells.onSleep(1, "MountainHotSpring")>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.addBuff("shower_fresh", 180)>> <<run setup.addBuff("bath_relaxed", 180)>> <<if _dreamRoute>><<goto _dreamRoute>><</if>> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #1abc9c; text-align: center;">♨️ Mountain Hot Spring</h2> <div style="padding: 25px; background: linear-gradient(135deg, #1a3a3a 0%, #0a2a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1abc9c;"> <p style="color: #b0d0c0; font-size: 16px; line-height: 1.6;"> You ease into the steaming water and the effect is immediate. Warmth floods through your body, unknotting muscles you didn't realize were tense. The mineral-rich water has a silky quality to it, and the faint scent of sulfur mixes with the crisp mountain air. Snow falls softly around you, each flake dissolving the moment it touches the rising steam. </p> <p style="color: #b0d0c0; font-size: 16px; line-height: 1.6; margin-top: 15px;"> For a while, there's nothing but the gentle gurgle of the spring and the vast silence of the mountains. Your thoughts slow. Your breathing deepens. The frozen peaks stretch endlessly above you, and for a brief, perfect moment, everything feels exactly right. </p> </div> <div style="background: #0a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 25px; border: 1px solid #1abc9c; text-align: center;"> <p style="color: #1abc9c; font-size: 16px; margin: 0;">🚿 You feel <strong>Fresh & Clean</strong>! (+15% trading bonus, 3 hours)</p> <p style="color: #1abc9c; font-size: 16px; margin: 5px 0 0 0;">🛁 You feel <strong>Deeply Relaxed</strong>! (+10% steal chance, 3 hours)</p> <<if setup.hasDebuff && setup.hasDebuff("exhaustion")>><<else>> <p style="color: #51cf66; font-size: 16px; margin: 5px 0 0 0;">💤 Your <strong>Exhaustion</strong> has been washed away.</p> <</if>> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MountainAbandonedBuilding">> <style> @keyframes flicker { 0%, 95%, 100% { opacity: 0; } 96%, 99% { opacity: 0.15; } } @keyframes shadowShift { 0%, 100% { transform: translateX(0px); opacity: 0.3; } 30% { transform: translateX(-5px); opacity: 0.5; } 70% { transform: translateX(3px); opacity: 0.2; } } .eerie-flicker { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,200,0.03); pointer-events: none; z-index: 2; animation: flicker 8s ease-in-out infinite; } .shadow-movement { position: fixed; top: 30%; right: 5%; width: 40px; height: 120px; background: rgba(0,0,0,0.15); border-radius: 50%; pointer-events: none; z-index: 1; animation: shadowShift 12s ease-in-out infinite; filter: blur(8px); } </style> <div class="eerie-flicker"></div> <div class="shadow-movement"></div> <div style="background: #0a0a0a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #555; text-align: center; font-style: italic;">🏚️ The Abandoned Building</h1> <div style="padding: 25px; background: #111; border-radius: 15px; margin-bottom: 25px; border: 2px solid #333;"> <p style="color: #666; font-size: 16px; line-height: 1.8;"> The door groans as you push it open, the sound echoing longer than it should. Inside, the air is thick and stale — but cold. Unnervingly cold, despite the hot spring just outside. Dust motes hang motionless in the dim light filtering through the grimy windows, as if frozen in place. </p> <p style="color: #555; font-size: 16px; line-height: 1.8; margin-top: 15px;"> Old furniture sits beneath moth-eaten sheets — a table, chairs, what might have been a bed frame. Everything is covered in a thick layer of dust, except... there are footprints. In the dust on the floor. Footprints that aren't yours. They lead deeper into the building and then simply <em>stop</em>, in the middle of the room, as if whoever made them vanished into thin air. </p> <p style="color: #555; font-size: 16px; line-height: 1.8; margin-top: 15px;"> From somewhere in the walls, you hear a faint <em>tick... tick... tick...</em> A clock, still running after what must be decades of abandonment. You can't see it. A draft of icy air brushes the back of your neck from a direction where there is no window, no opening, nothing that should let air through. You spin around. Nothing. But the shadows in the corner seem to shift when you're not looking directly at them. </p> <p style="color: #444; font-size: 16px; line-height: 1.8; margin-top: 15px;"> Near the back of the room, a narrow hallway disappears into darkness. The air from that direction is even colder. A light — impossibly — flickers once at the far end and then goes out. Old wallpaper peels from the walls in long curling strips, and beneath it the plaster is covered in scratch marks. Not random. Almost like writing. But the hallway is blocked by a collapse of timber and stone. Whatever is back there, you can't reach it. </p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; margin-bottom: 25px; border: 1px dashed #444; text-align: center;"> <p style="color: #666; font-size: 14px; font-style: italic; margin: 0;">The hallway deeper into the building is blocked by debris. There seems to be more to explore here... but the way is blocked for now.</p> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #555 0%, #333 100%); color: #ccc; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Leave the Building</div>">> <<goto "MountainHotSpring">> <</link>> </div> </div> <</nobr>>
<<nobr>><<set $lastLocation = "MountainShrine">> <<set _hasColdTolerance = ($physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow"))>> <<if !_hasColdTolerance>> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #e67e22; text-align: center;">⛩️ The Fox Shrine</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a2a3a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ba3c9;"> <p style="color: #7ba3c9; font-size: 16px; line-height: 1.6;"> You begin climbing the ancient stone staircase, but the higher you go, the more brutal the cold becomes. The steps are coated in a thick layer of ice, and the wind howls through the frozen pines with enough force to knock you off balance. Your hands are shaking too badly to grip the stone railing. You can just barely make out the shrine at the top through the swirling snow, but your body refuses to go further. You need some kind of physical toughness or cold tolerance to make this climb. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <<else>> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #e67e22; text-align: center;">⛩️ The Fox Shrine</h1> <div style="padding: 25px; background: linear-gradient(135deg, #2a1a0a 0%, #1a0a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e67e22;"> <p style="color: #d4a76a; font-size: 16px; line-height: 1.6;"> The ancient stone staircase climbs steeply through the snow, each step worn smooth by centuries of passage. Ice crystals cling to the carved symbols along the railing, and the wind dies to nothing as you reach the top. </p> <p style="color: #d4a76a; font-size: 16px; line-height: 1.6; margin-top: 15px;"> A small plateau opens before you, sheltered by a ring of ancient frost-covered pines. At the center stands a weathered stone shrine, its architecture unlike anything else on the island — elegant, deliberate, sacred. And within it sits the statue: a fox, carved from a single piece of pale stone, with nine flowing tails fanning out behind it. Each tail ends in a gemstone of a different color — ruby, sapphire, emerald, topaz, amethyst, diamond, opal, obsidian, and one that seems to shift between all colors at once. The fox's eyes are closed, its expression serene, as though caught in an eternal moment of meditation. </p> <p style="color: #d4a76a; font-size: 16px; line-height: 1.6; margin-top: 15px;"> The air here is perfectly still. No wind, no sound, not even the crunch of snow underfoot. You get the distinct feeling that something is aware of your presence. </p> </div> <!-- Riddle inscription --> <div style="background: #0a0a00; padding: 20px; border-radius: 10px; margin-bottom: 25px; border: 1px solid #4a3a2a;"> <p style="color: #888; font-size: 13px; font-style: italic; margin-bottom: 10px; text-align: center;">Carved into the base of the shrine in ancient script:</p> <p style="color: #e67e22; font-size: 16px; line-height: 1.8; font-style: italic; text-align: center;"> “Nine tails burn bright, nine offerings deep,<br> One gift each week, a promise to keep.<br> Only the rarest may grace this stone—<br> Fish touched by myth, by starlight sewn.<br> But heed this well, should you offer less,<br> The tails go dark, and you start afresh.<br> Nine treasures laid, however long it takes,<br> And when the last light wakes, the debt is paid.” </p> </div> <<if $shrineMysticAwarded>> <!-- POST-MYSTIC STATE: Deposit shrine --> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a2e 0%, #0a0a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: #bb86fc; font-size: 18px; font-weight: bold; text-align: center; margin-bottom: 10px;">✨ The Mystic Shrine</p> <p style="color: #aaa; font-size: 14px; text-align: center; margin-bottom: 15px;">The fox spirit's blessing flows through you. You may offer fish at this sacred place — the shrine's power will double their worth.</p> <p style="color: #888; font-size: 13px; text-align: center; margin-bottom: 15px;">Total deposited at shrine: $<<print $shrineTotalDeposited>></p> <!-- List fish that can be deposited (common through legendary only) --> <<set _depositableFish = []>> <<for _i = 0; _i < $fishInventory.length; _i++>> <<if $fishInventory[_i].rarity !== "mythical">> <<run _depositableFish.push(_i)>> <</if>> <</for>> <<if _depositableFish.length === 0>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; text-align: center; border: 1px solid #444;"> <p style="color: #888; font-size: 14px;">You have no fish to deposit. Only common through legendary fish may be offered here.</p> </div> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px;" id="shrine-deposit-list"> <<for _j = 0; _j < _depositableFish.length; _j++>> <<set _idx = _depositableFish[_j]>> <<set _fish = $fishInventory[_idx]>> <<set _level = setup.fishing.getLevel()>> <<set _priceBonus = 1 + (_level * 0.05)>> <<set _baseVal = Math.floor(_fish.basePrice * _priceBonus)>> <<set _shrineVal = _baseVal * 2>> <<capture _idx, _fish, _shrineVal>> <div style="background: #1a1a2e; padding: 12px; border-radius: 8px; border: 1px solid #9b59b6;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div> <<if _fish.icon && _fish.icon.indexOf("Images/") === 0>><img @src="_fish.icon" style="width: 32px; height: 32px; image-rendering: pixelated; vertical-align: middle;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 20px;">🐟</span><<else>><span style="font-size: 20px;"><<print _fish.icon || "🐟">></span><</if>> <span style="color: #ddd; font-weight: bold; margin-left: 5px;"><<print _fish.name>></span> <span style="color: #888; font-size: 12px; margin-left: 5px;">(<<print _fish.rarity>>)</span> </div> <div style="text-align: right;"> <span style="color: #ffd700; font-weight: bold;">$<<print _shrineVal>></span> <span style="color: #51cf66; font-size: 11px;"> (2x)</span> </div> </div> <div style="margin-top: 8px; text-align: right;"> <<link "<span style='background: #9b59b6; color: white; padding: 5px 15px; border-radius: 5px; font-size: 13px; cursor: pointer;'>Deposit</span>">> <<set $money += _shrineVal>> <<set $shrineTotalDeposited += _shrineVal>> <<run setup.fishing.removeFromInventory(_idx)>> <<goto "MountainShrine">> <</link>> </div> </div> <</capture>> <</for>> </div> <!-- Deposit All button --> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #6c3483 100%); color: white; padding: 12px 30px; border-radius: 8px; display: inline-block; font-weight: bold; font-size: 14px; cursor: pointer;'>Deposit All Fish</div>">> <<set _totalEarned = 0>> <<for _k = $fishInventory.length - 1; _k >= 0; _k-->> <<if $fishInventory[_k].rarity !== "mythical">> <<set _level = setup.fishing.getLevel()>> <<set _priceBonus = 1 + (_level * 0.05)>> <<set _val = Math.floor($fishInventory[_k].basePrice * _priceBonus) * 2>> <<set _totalEarned += _val>> <<run $fishInventory.splice(_k, 1)>> <</if>> <</for>> <<set $money += _totalEarned>> <<set $shrineTotalDeposited += _totalEarned>> <<goto "MountainShrine">> <</link>> </div> <</if>> </div> <<elseif $physicalTraits.includes("Mystic")>> <!-- Somehow have Mystic but shrineMysticAwarded is false? Fix it --> <<set $shrineMysticAwarded = true>> <<goto "MountainShrine">> <<else>> <!-- PRE-MYSTIC STATE: Offering sequence --> <!-- Status display --> <div style="padding: 15px; background: #1a1500; border-radius: 10px; margin-bottom: 25px; border: 1px dashed #e67e22;"> <<if $shrineOfferCount === 0>> <p style="color: #e67e22; font-size: 15px; text-align: center; margin: 0;"> The fox statue watches in silence. Its nine tails shimmer faintly, each gemstone dark and waiting. </p> <<elseif $shrineOfferCount >= 1 && $shrineOfferCount <= 8>> <p style="color: #e67e22; font-size: 15px; text-align: center; margin: 0;"> <<print $shrineOfferCount>> of the nine gemstone tails glow softly with an inner light. <<print 9 - $shrineOfferCount>> remain dark. </p> <<if $shrineLastOfferDay >= 0 && ($dayNumber - $shrineLastOfferDay) < 7>> <p style="color: #888; font-size: 13px; text-align: center; margin-top: 8px;">You have already made this week's offering. Return in <<print 7 - ($dayNumber - $shrineLastOfferDay)>> day<<if (7 - ($dayNumber - $shrineLastOfferDay)) !== 1>>s<</if>>.</p> <</if>> <</if>> </div> <!-- 9 offerings complete - AWARD MYSTIC --> <<if $shrineOfferCount >= 9>> <div style="padding: 30px; background: linear-gradient(135deg, #ffffff10 0%, #ffffff05 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #fff; box-shadow: 0 0 30px rgba(255,255,255,0.3), 0 0 60px rgba(255,255,255,0.1);"> <p style="color: #fff; font-size: 18px; text-align: center; line-height: 1.8; margin-bottom: 20px;"> All nine gemstones burn with radiant light. The statue's pale stone seems almost translucent now, and the fox's eyes — for the first time — are open. They glow with a warm, ancient intelligence. </p> <p style="color: #ddd; font-size: 16px; text-align: center; line-height: 1.7; margin-bottom: 20px;"> The air hums with power. A warmth that has nothing to do with temperature spreads through your body, starting from your chest and flowing to your fingertips, your toes, the crown of your head. Your vision goes white for a moment — not painful, but overwhelming, like staring into the heart of a star. </p> <p style="color: #ddd; font-size: 16px; text-align: center; line-height: 1.7; margin-bottom: 20px;"> When it clears, the fox statue's eyes have closed again. But something has changed. You can feel it in your bones, in the way the air moves around you, in the sharpness of your thoughts and the steadiness of your hands. The mountain itself seems to acknowledge you differently. </p> <div style="background: #0a0a0a; padding: 20px; border-radius: 10px; border: 2px solid #ffd700; text-align: center; margin-bottom: 20px;"> <p style="color: #ffd700; font-size: 20px; font-weight: bold; margin-bottom: 10px;">✨ Mystic Trait Gained! ✨</p> <p style="color: #ccc; font-size: 14px; margin-bottom: 5px;">+7 Strength, +7 Intelligence, +7 Charisma, +7 Dexterity</p> <p style="color: #9b59b6; font-size: 13px;">The shrine now serves as a sacred deposit — offer fish here for double their value.</p> </div> <div style="text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #e67e22 100%); color: #000; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; text-align: center;'>Accept the Fox Spirit's Blessing</div>">> <<run $physicalTraits.push("Mystic")>> <<set $shrineMysticAwarded = true>> <<goto "MountainShrine">> <</link>> </div> </div> <<else>> <!-- OFFERING INTERFACE --> <<if $shrineLastOfferDay >= 0 && ($dayNumber - $shrineLastOfferDay) < 7>> <!-- Already offered this week --> <div style="background: #1a1a0a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 1px solid #4a4a2a; text-align: center;"> <p style="color: #d4a76a; font-size: 15px; margin: 0;">You have already placed your offering this week. The shrine rests. Return in <<print 7 - ($dayNumber - $shrineLastOfferDay)>> day<<if (7 - ($dayNumber - $shrineLastOfferDay)) !== 1>>s<</if>>.</p> </div> <<else>> <<set _offerableFish = []>> <<for _i = 0; _i < $fishInventory.length; _i++>> <<run _offerableFish.push(_i)>> <</for>> <<if _offerableFish.length === 0>> <div style="background: #1a1a0a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 1px solid #4a4a2a; text-align: center;"> <p style="color: #d4a76a; font-size: 15px; margin: 0;">You carry no fish to offer. Return when you have something to place upon the shrine.</p> </div> <<else>> <div style="background: linear-gradient(135deg, #2a1a0a 0%, #1a0a00 100%); padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #e67e22;"> <p style="color: #e67e22; font-size: 16px; font-weight: bold; margin-bottom: 15px; text-align: center;">Choose an Offering</p> <div id="shrine-offer-area"> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 10px;"> <<for _j = 0; _j < _offerableFish.length; _j++>> <<set _idx = _offerableFish[_j]>> <<set _fish = $fishInventory[_idx]>> <<capture _idx, _fish>> <div style="background: #0a0a1a; padding: 12px; border-radius: 8px; border: 1px solid #e67e22;"> <div style="display: flex; justify-content: space-between; align-items: center;"> <div> <<if _fish.icon && _fish.icon.indexOf("Images/") === 0>><img @src="_fish.icon" style="width: 32px; height: 32px; image-rendering: pixelated; vertical-align: middle;" onerror="this.style.display='none'; this.nextElementSibling.style.display='inline';"><span style="display: none; font-size: 20px;">🐟</span><<else>><span style="font-size: 20px;"><<print _fish.icon || "🐟">></span><</if>> <span style="color: #ffd700; font-weight: bold; margin-left: 5px;"><<print _fish.name>></span> </div> <<link "<span style='background: #e67e22; color: white; padding: 5px 15px; border-radius: 5px; font-size: 13px; cursor: pointer;'>Offer</span>">> <<if _fish.rarity === "mythical">> /* Mythical fish - advances progress */ <<set $shrineOfferCount += 1>> <<set $shrineLastOfferDay = $dayNumber>> <<run setup.fishing.removeFromInventory(_idx)>> <<if $shrineOfferCount >= 9>> <<goto "MountainShrine">> <<else>> <<replace "#shrine-offer-area">> <div style="text-align: center; padding: 20px;"> <p style="color: #ffd700; font-size: 18px; margin-bottom: 10px;">✨ The shrine accepts your offering.</p> <p style="color: #d4a76a; font-size: 15px;">You place the <<print _fish.name>> at the base of the statue. The fish dissolves into golden light that flows into one of the gemstone tails, which begins to glow softly.</p> <p style="color: #888; font-size: 14px; margin-top: 15px;"><<print $shrineOfferCount>> of 9 tails glow. Return next week with another mythical offering.</p> </div> <</replace>> <</if>> <<else>> /* Non-mythical fish - consumed but resets all progress */ <<set $shrineOfferCount = 0>> <<set $shrineLastOfferDay = $dayNumber>> <<run setup.fishing.removeFromInventory(_idx)>> <<replace "#shrine-offer-area">> <div style="text-align: center; padding: 20px;"> <p style="color: #ff4444; font-size: 18px; margin-bottom: 10px;">The shrine rejects your offering.</p> <p style="color: #d4a76a; font-size: 15px;">You place the <<print _fish.name>> at the base of the statue. It dissolves into dark smoke. The gemstone tails that were glowing flicker and go dark, one by one.</p> <p style="color: #888; font-size: 14px; margin-top: 15px;">The shrine has consumed your offering and forgotten your devotion. You must begin anew.</p> </div> <</replace>> <</if>> <</link>> </div> </div> <</capture>> <</for>> </div> </div> </div> <</if>> <</if>> <</if>> <</if>> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #e67e22 0%, #d35400 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Descend the Stairs</div>">> <<goto "Mountains">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "MountainCleanRoom">> <style> @keyframes gearSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes steamPuff { 0% { opacity: 0.8; transform: translateY(0) scale(1); } 100% { opacity: 0; transform: translateY(-40px) scale(1.5); } } @keyframes pipePulse { 0%, 100% { box-shadow: 0 0 5px rgba(205,127,50,0.3); } 50% { box-shadow: 0 0 15px rgba(205,127,50,0.6); } } .gear-container { display: flex; justify-content: center; gap: 20px; margin: 30px 0; flex-wrap: wrap; } .gear-dial { width: 100px; height: 190px; display: flex; flex-direction: column; align-items: center; justify-content: space-between; background: linear-gradient(180deg, #3a2a1a 0%, #2a1a0a 100%); border: 3px solid #cd7f32; border-radius: 12px; padding: 12px 10px; position: relative; box-shadow: 0 4px 8px rgba(0,0,0,0.6), inset 0 1px 0 rgba(205,127,50,0.3); animation: pipePulse 3s ease-in-out infinite; user-select: none; -webkit-user-select: none; touch-action: none; } .gear-dial-label { color: #cd7f32; font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: 2px; margin-bottom: 5px; text-shadow: 0 0 5px rgba(205,127,50,0.5); } .gear-number { font-size: 42px; font-weight: bold; color: #ffd700; text-shadow: 0 0 10px rgba(255,215,0,0.6), 0 0 20px rgba(255,215,0,0.3); line-height: 1; margin: 5px 0; font-family: "Courier New", monospace; } .gear-btn { width: 36px; height: 28px; border: 2px solid #cd7f32; background: linear-gradient(180deg, #4a3a2a 0%, #2a1a0a 100%); color: #cd7f32; font-size: 18px; font-weight: bold; border-radius: 6px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s; touch-action: manipulation; -webkit-tap-highlight-color: transparent; } .gear-btn:hover, .gear-btn:active { background: linear-gradient(180deg, #5a4a3a 0%, #3a2a1a 100%); border-color: #ffd700; color: #ffd700; box-shadow: 0 0 10px rgba(255,215,0,0.4); } .gear-icon { font-size: 24px; margin-bottom: 3px; animation: gearSpin 8s linear infinite; display: inline-block; } .steam-puff { position: absolute; top: -10px; font-size: 16px; opacity: 0; animation: steamPuff 2s ease-out forwards; pointer-events: none; } .submit-gear-btn { background: linear-gradient(180deg, #5a3a1a 0%, #3a2a0a 100%); border: 3px solid #cd7f32; color: #ffd700; padding: 15px 40px; border-radius: 10px; font-size: 18px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 8px rgba(0,0,0,0.6), 0 0 20px rgba(205,127,50,0.3); transition: all 0.2s; text-shadow: 0 0 8px rgba(255,215,0,0.5); touch-action: manipulation; -webkit-tap-highlight-color: transparent; } .submit-gear-btn:hover { background: linear-gradient(180deg, #6a4a2a 0%, #4a3a1a 100%); border-color: #ffd700; box-shadow: 0 4px 8px rgba(0,0,0,0.6), 0 0 30px rgba(255,215,0,0.5); } </style> <div style="background: linear-gradient(180deg, #1a1008 0%, #0d0804 100%); min-height: 100vh; padding: 40px 20px; position: relative; z-index: 1;"> <h1 style="color: #cd7f32; text-align: center; text-shadow: 0 0 15px rgba(205,127,50,0.5);">⚙️ The Mysterious Room</h1> <div style="padding: 25px; background: linear-gradient(135deg, #2a1a0a 0%, #1a1008 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B6914;"> <p style="color: #c9a06c; font-size: 16px; line-height: 1.6;"> You step inside and the mountain vanishes. The air here is different — warm, dry, faintly metallic. Copper pipes run along the ceiling in neat parallel lines, disappearing into the walls. The floor is riveted steel, darkened with age and oil. A single gas lamp flickers overhead, its amber light dancing across surfaces of brass and iron. Somewhere behind the walls, you hear the rhythmic ticking of clockwork — steady, patient, ancient. </p> <p style="color: #c9a06c; font-size: 16px; line-height: 1.6; margin-top: 15px;"> On the far wall stands a massive steel door, its surface adorned with interlocking gears of varying sizes — some still, some slowly turning. In the center of the door, four large dials are mounted in a row, each displaying a single digit. Above them, an inscription in angular brass lettering reads: <em style="color: #ffd700;">“Turn the gears. Speak the number. The machine remembers.”</em> </p> </div> <<if $cleanRoomSolved>> <!-- Already solved - door is open --> <div style="padding: 20px; background: #1a2a10; border-radius: 12px; margin-bottom: 25px; border: 2px solid #51cf66; text-align: center;"> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0 0 15px 0;">⚙️ The gears have already aligned. The door stands open.</p> <<link "<div style='background: linear-gradient(135deg, #cd7f32 0%, #8B6914 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 20px rgba(205,127,50,0.4);'>Enter the Inner Chamber</div>">> <<goto "CleanRoomInner">> <</link>> </div> <<else>> <!-- Gear Puzzle - 7 Sequential Locks --> <<if typeof $cleanRoomProgress === "undefined">><<set $cleanRoomProgress = 0>><</if>> <div style="padding: 25px; background: linear-gradient(135deg, #2a1a0a 0%, #1a1008 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #cd7f32; text-align: center;"> <!-- Progress indicator --> <h3 style="color: #cd7f32; margin: 0 0 5px 0;">⚙️ The Gear Lock</h3> <p style="color: #888; font-size: 13px; margin: 0 0 10px 0; font-style: italic;">Turn each gear to set a digit. Click the arrows or swipe up/down.</p> <!-- Lock progress display --> <div id="lockProgress" style="margin-bottom: 15px;"> <div style="display: flex; justify-content: center; gap: 8px; margin-bottom: 8px;"> <<for _lk = 0; _lk < 7; _lk++>> <<if _lk < $cleanRoomProgress>> <div style="width: 28px; height: 28px; border-radius: 50%; background: #cd7f32; border: 2px solid #ffd700; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #fff; font-weight: bold; box-shadow: 0 0 10px rgba(255,215,0,0.5);"><<print _lk + 1>></div> <<elseif _lk === $cleanRoomProgress>> <div style="width: 28px; height: 28px; border-radius: 50%; background: #cd7f32; border: 2px solid #ffd700; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #fff; font-weight: bold; box-shadow: 0 0 10px rgba(255,215,0,0.5);"><<print _lk + 1>></div> <<else>> <div style="width: 28px; height: 28px; border-radius: 50%; background: #1a1008; border: 2px solid #555; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #555; font-weight: bold;"><<print _lk + 1>></div> <</if>> <</for>> </div> <p style="color: #cd7f32; font-size: 14px; margin: 0; font-weight: bold;">Lock <<print $cleanRoomProgress + 1>> of 7</p> </div> <div id="gearPuzzle" class="gear-container"> <div class="gear-dial" data-gear="0"> <div class="gear-dial-label">I</div> <div class="gear-btn" data-dir="up">▲</div> <div class="gear-icon">⚙️</div> <div class="gear-number" data-digit="0">0</div> <div class="gear-btn" data-dir="down">▼</div> </div> <div class="gear-dial" data-gear="1"> <div class="gear-dial-label">II</div> <div class="gear-btn" data-dir="up">▲</div> <div class="gear-icon">⚙️</div> <div class="gear-number" data-digit="0">0</div> <div class="gear-btn" data-dir="down">▼</div> </div> <div class="gear-dial" data-gear="2"> <div class="gear-dial-label">III</div> <div class="gear-btn" data-dir="up">▲</div> <div class="gear-icon">⚙️</div> <div class="gear-number" data-digit="0">0</div> <div class="gear-btn" data-dir="down">▼</div> </div> <div class="gear-dial" data-gear="3"> <div class="gear-dial-label">IV</div> <div class="gear-btn" data-dir="up">▲</div> <div class="gear-icon">⚙️</div> <div class="gear-number" data-digit="0">0</div> <div class="gear-btn" data-dir="down">▼</div> </div> </div> <div id="gearResult" style="margin-top: 15px; min-height: 30px;"></div> <div style="margin-top: 15px;"> <span id="gearSubmitBtn" class="submit-gear-btn">⚙️ Engage the Lock</span> </div> </div> <script> (function() { /* 7 codes pulled from randomized $obeliskCodes - deep copy to plain JS arrays */ var rawCodes = SugarCube.State.variables.obeliskCodes; var CODES; if (rawCodes && rawCodes.length >= 7) { CODES = []; for (var c = 0; c < rawCodes.length; c++) { CODES.push([Number(rawCodes[c][0]), Number(rawCodes[c][1]), Number(rawCodes[c][2]), Number(rawCodes[c][3])]); } } else { CODES = [ [0, 0, 0, 1], [0, 0, 0, 2], [0, 0, 0, 3], [0, 0, 0, 4], [0, 0, 0, 5], [0, 0, 0, 6], [0, 0, 0, 7] ]; } var progress = Number(SugarCube.State.variables.cleanRoomProgress) || 0; var currentCode = CODES[progress]; var digits = [0, 0, 0, 0]; var container = document.getElementById("gearPuzzle"); if (!container) return; function updateDisplay(index) { var dials = container.querySelectorAll(".gear-dial"); var numEl = dials[index].querySelector(".gear-number"); numEl.textContent = digits[index]; numEl.setAttribute("data-digit", digits[index]); /* Add steam puff effect */ var puff = document.createElement("span"); puff.className = "steam-puff"; puff.textContent = "\u2601"; puff.style.left = (Math.random() * 60 + 20) + "px"; dials[index].appendChild(puff); setTimeout(function() { if (puff.parentNode) puff.parentNode.removeChild(puff); }, 2000); } function changeDigit(index, direction) { if (direction === "up") { digits[index] = (digits[index] + 1) % 10; } else { digits[index] = (digits[index] + 9) % 10; } updateDisplay(index); } /* Button clicks */ container.addEventListener("click", function(e) { var btn = e.target.closest(".gear-btn"); if (!btn) return; var dial = btn.closest(".gear-dial"); var index = parseInt(dial.getAttribute("data-gear")); var dir = btn.getAttribute("data-dir"); changeDigit(index, dir); }); /* Touch/swipe support */ var touchStartY = {}; container.addEventListener("touchstart", function(e) { var dial = e.target.closest(".gear-dial"); if (!dial) return; var touch = e.touches[0]; var index = dial.getAttribute("data-gear"); touchStartY[index] = touch.clientY; }, {passive: true}); container.addEventListener("touchend", function(e) { var dial = e.target.closest(".gear-dial"); if (!dial) return; var touch = e.changedTouches[0]; var index = dial.getAttribute("data-gear"); if (touchStartY[index] !== undefined) { var diff = touchStartY[index] - touch.clientY; if (Math.abs(diff) > 20) { changeDigit(parseInt(index), diff > 0 ? "up" : "down"); } delete touchStartY[index]; } }, {passive: true}); /* Mouse wheel support */ container.addEventListener("wheel", function(e) { var dial = e.target.closest(".gear-dial"); if (!dial) return; e.preventDefault(); var index = parseInt(dial.getAttribute("data-gear")); changeDigit(index, e.deltaY < 0 ? "up" : "down"); }, {passive: false}); /* Submit button */ var submitBtn = document.getElementById("gearSubmitBtn"); var resultDiv = document.getElementById("gearResult"); var submitting = false; if (submitBtn) { function handleSubmit() { if (submitting) return; submitting = true; var correct = true; for (var i = 0; i < 4; i++) { if (digits[i] !== currentCode[i]) { correct = false; break; } } if (correct) { progress++; SugarCube.State.variables.cleanRoomProgress = progress; if (progress >= 7) { /* All 7 locks solved! */ resultDiv.innerHTML = '<p style="color: #ffd700; font-size: 20px; font-weight: bold; text-shadow: 0 0 15px rgba(255,215,0,0.8);">\u2699\uFE0F All seven locks engage in unison. The entire wall shudders. Ancient gears, dormant for centuries, grind to life. The door slides open with a sound like thunder...</p>'; submitBtn.style.display = "none"; SugarCube.State.variables.cleanRoomSolved = true; setTimeout(function() { SugarCube.Engine.play("CleanRoomInner"); }, 3000); } else { /* Lock accepted, advance to next - silent reload */ setTimeout(function() { SugarCube.Engine.play("MountainCleanRoom"); }, 500); } } else { /* Wrong code resets ALL progress back to lock 1 */ SugarCube.State.variables.cleanRoomProgress = 0; /* Reset dials */ for (var j = 0; j < 4; j++) { digits[j] = 0; updateDisplay(j); } /* Reload passage to show reset progress */ setTimeout(function() { SugarCube.Engine.play("MountainCleanRoom"); }, 1500); } } submitBtn.addEventListener("click", handleSubmit); submitBtn.addEventListener("touchend", function(e) { e.preventDefault(); handleSubmit(); }); } })(); </script> <</if>> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Leave</div>">> <<goto "Mountains">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <!-- Apply debuffs immediately --> <<run setup.addDebuff("exhaustion")>> <<if $appearance.hairStyle !== "messy">> <<run setup.setHairMessy()>> <</if>> <div style="background: #000; min-height: 100vh; padding: 40px 20px; text-align: center;"> <div class="fade-in" style="padding: 60px 20px;"> <p style="color: #333; font-size: 18px;">The volcanic heat overwhelms you... your vision blurs...</p> </div> <<timed 2s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #444; font-size: 16px;">The scorching air burns your lungs as you collapse. Ash swirls around you as the world fades to orange...</p> </div> <</timed>> <<timed 5s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #555; font-size: 16px;">Time passes... you drift in and out of consciousness...</p> </div> <</timed>> <<timed 8s>> <div class="fade-in" style="padding: 20px;"> <p style="color: #aaa; font-size: 18px;">You wake up back at <strong style="color: #D2691E;">The Nest</strong>, disoriented and exhausted. Someone — or something — must have dragged you away from the volcano.</p> <p style="color: #666; font-size: 14px; font-style: italic; margin-top: 10px;">You gained the <strong style="color: #ff5722;">Exhaustion</strong> debuff.</p> </div> <div style="margin-top: 30px;"> <<link "<div style='background: #D2691E; color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up at The Nest</div>">> <<goto "The Nest">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoExplore">> <!-- Post-exploration heat check with grace period --> <<set _hasHeatImmunity = setup.skillTree.getEffect("heatImmunity") || $physicalTraits.includes("Tan Skin") || $physicalTraits.includes("Dark Skin") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Salamander") || $mentalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Automaton")>> <<if _hasHeatImmunity>> <<set $volcanoHeatSteps = 0>> <<else>> <<set $volcanoHeatSteps += 1>> <<if $volcanoHeatSteps >= 3>> <<set $volcanoHeatSteps = 0>> <<goto "VolcanoPassout">> <</if>> <</if>> <!-- Explore heat warning --> <<if !_hasHeatImmunity && $volcanoHeatSteps === 1>> <div style="background: #4a1a00; padding: 12px; border-radius: 8px; border: 2px solid #ff5722; margin-bottom: 15px; text-align: center;"> <p style="color: #ff8a65; font-size: 15px; font-weight: bold; margin: 0;">🌡️ The searing heat presses against your skin. Sweat drips from every pore. You need to leave soon or the volcano will claim you.</p> </div> <<elseif !_hasHeatImmunity && $volcanoHeatSteps === 2>> <div style="background: #5a0a00; padding: 12px; border-radius: 8px; border: 2px solid #ff0000; margin-bottom: 15px; text-align: center;"> <p style="color: #ff4444; font-size: 16px; font-weight: bold; margin: 0;">🔥 Your vision swims. The air scorches your lungs with every breath. One more step and you won’t be walking out of here.</p> </div> <</if>> <div style="background: #1a0a00; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #ff5722; text-align: center;">🌋 Volcano Exploration</h2> <!-- Event roll --> <<set _eventRoll = random(1, 100)>> <div style="padding: 25px; background: #2a1a0a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #bf360c;"> <<if _eventRoll <= 18 && !$discoveredWolfStatue>> <<set $discoveredWolfStatue = true>> <h3 style="color: #c77dff; margin-top: 0;">🐺 A Broken Statue</h3> <p>Half buried in cooling basalt, where the heat is so fierce it bends the air, you find a statue of a great wolf. Its lower body is intact, but its chest, shoulders, and head are gone, sheared away long ago. A ring of cold dark runes circles its base. It can be reached again from the volcano whenever you can bear the heat.</p> <div style="background: #1a0a28; padding: 12px; border-radius: 8px; margin-top: 12px; border: 1px solid #c77dff; text-align: center;"><span style="color: #c77dff; font-weight: bold;">🐺 You discovered the Broken Wolf Statue.</span></div> <<elseif _eventRoll <= 20 && !$discoveredLavaPool>> <!-- Lava Pool Discovery (one-time) --> <<set $discoveredLavaPool = true>> <h3 style="color: #ff3d00; margin-top: 0;">🔥 Bubbling Lava Pool</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> Rounding a jagged outcrop of black basalt, you hear it before you see it — a deep, rhythmic bubbling like the earth itself is breathing. Below the ridge, nestled at the base of a sheer cliff face, a wide pool of molten rock churns and hisses. The surface glows in shifting shades of orange and crimson, occasionally splitting apart to reveal the white-hot magma beneath. Even from several meters away, the heat is staggering. The air above the pool ripples and distorts, and mineral deposits around its edges have crystallized into formations of brilliant yellow and deep red. </p> <div style="background: #0a0500; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #ff3d00; text-align: center;"> <p style="color: #ff3d00; font-size: 18px; font-weight: bold; margin: 0;">🔥 You discovered the Bubbling Lava Pool!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">You can now visit the Lava Pool from the Volcano.</p> </div> <<elseif _eventRoll <= 30 && !$discoveredIronBowl>> <!-- Iron Bowl Discovery --> <<set $discoveredIronBowl = true>> <h3 style="color: #b85c5c; margin-top: 0;">🍶 An Iron Bowl</h3> <p style="color: #ddc4c4; font-size: 16px; line-height: 1.6;"> You crest a basalt ridge and find a flat shelf of black stone slick with old soot. At its center sits a heavy iron rimmed bowl, set so deep into the rock it could only have been put there before the rock cooled around it. The bowl is empty. The bowl has been waiting a long time. </p> <div style="background: #1a0a0a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #b85c5c; text-align: center;"> <p style="color: #b85c5c; font-size: 18px; font-weight: bold; margin: 0;">🍶 You discovered an Iron Bowl!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">The bowl will appear at the Volcano now.</p> </div> <<elseif _eventRoll <= 35>> <!-- Find Volcanic Fruit (repeatable) --> <h3 style="color: #ff6e40; margin-top: 0;">🍅 Strange Volcanic Fruit</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> Pushing through a curtain of sulfurous haze, you spot something extraordinary — a peculiar plant growing from a crack beside a lava flow. Its fruit glows faintly orange, with veins of light pulsing through its skin like embers. The air around it smells of cinnamon and smoke, and the fruit itself is warm to the touch. </p> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #ff6e40 0%, #e64a19 100%); color: white; padding: 12px 30px; border-radius: 8px; display: inline-block; font-weight: bold; font-size: 15px; cursor: pointer;'>Examine the Fruit</div>">> <<goto "VolcanoFruit">> <</link>> </div> <<elseif _eventRoll <= 48>> <!-- Lava Flow --> <h3 style="color: #ff5722; margin-top: 0;">🔥 Lava Flow</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> You round a bend in the trail and stop dead. A river of molten rock cascades down a narrow channel carved into the mountainside, close enough to feel the searing heat on your face. The lava glows a vivid orange, its surface crusting over in dark patches before cracking apart to reveal the liquid fire beneath. The air above it ripples and distorts, making the far side of the flow seem to dance and shimmer. </p> <<elseif _eventRoll <= 61>> <!-- Obsidian Field --> <h3 style="color: #ff5722; margin-top: 0;">💎 Obsidian Field</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> The terrain opens into a vast field of black volcanic glass. Obsidian shards jut from the ground at jagged angles, their surfaces so smooth and dark they reflect the sky like a thousand broken mirrors. You tread carefully — the edges are razor-sharp. Here and there, patches of glass catch the light just right, revealing swirling patterns frozen in the stone from the moment it cooled millennia ago. </p> <<elseif _eventRoll <= 73>> <!-- Volcanic Vents --> <h3 style="color: #ff5722; margin-top: 0;">💨 Volcanic Vents</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> A cluster of geothermal vents punctures the rocky ground, each one hissing and sputtering jets of superheated steam and sulfurous gas into the air. The stench of rotten eggs is nearly overwhelming. Mineral deposits have painted the rocks around each vent in vivid yellows and greens, creating an alien landscape that feels like it belongs on another world entirely. The ground trembles slightly beneath your feet. </p> <<elseif _eventRoll <= 83>> <!-- Ash Fields --> <h3 style="color: #ff5722; margin-top: 0;">🌫️ Ash Fields</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> Grey ash stretches in every direction like a desolate moonscape. Your footsteps leave deep impressions that the hot wind slowly fills back in. Strange shapes protrude from the ash — the petrified remains of trees caught in some ancient eruption, their branches frozen mid-reach toward a sky that betrayed them. An eerie silence hangs over everything, broken only by the crunch of your steps. </p> <<elseif _eventRoll <= 92>> <!-- Crater Overlook --> <h3 style="color: #ff5722; margin-top: 0;">🌋 Crater Overlook</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> You crest a ridge and find yourself staring down into the massive volcanic crater. Far below, a lake of churning lava pulses with a deep, rhythmic glow — like the heartbeat of the mountain itself. Plumes of smoke and gas rise in lazy spirals, lit from beneath in shades of orange and red. The scale is breathtaking. The entire crater could swallow a city, and the heat rising from it creates a constant updraft that tugs at your clothes. </p> <<else>> <!-- Strange Warmth --> <h3 style="color: #ff5722; margin-top: 0;">🌺 Strange Warmth</h3> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> You stumble upon an unexpected pocket of life in this hostile terrain. Where the geothermal heat meets a thin trickle of mineral-rich water, a tiny garden has taken root. Strange, heat-adapted plants with thick waxy leaves grow in impossible shades of deep crimson and bright amber. Tiny flowers with translucent petals seem to glow faintly from within. It feels almost sacred — a stubborn declaration that life persists even in the harshest places. </p> <</if>> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Volcano</div>">> <<goto "Volcano">> <</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Oasis")>> <<run $visitedLocations.push("Oasis")>> <</if>> <<set $lastLocation = "Oasis">> <style> @keyframes waterShimmer { 0%, 100% { opacity: 0.3; } 50% { opacity: 0.5; } } .oasis-water-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 80%, rgba(26,188,156,0.06) 0%, transparent 60%); pointer-events: none; z-index: 0; animation: waterShimmer 5s ease-in-out infinite; } </style> <div class="oasis-water-overlay"></div> <div style="background: #1a1a0a; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #1abc9c; text-align: center;">🏝️ The Desert Oasis</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Oasis.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #1abc9c; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Desert Oasis"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1a3a2a 0%, #0a2a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1abc9c;"> <p style="color: white; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> A hidden paradise in the heart of the desert. A spring-fed pool of crystal-clear water sits sheltered in a depression between tall dunes, surrounded by swaying palm trees and thick reeds. The air here is cooler and carries the faint scent of green growing things. Colorful fish dart beneath the surface, their scales catching the light as they weave through aquatic plants. It feels like a secret the desert has been keeping for a very long time. </p> </div> <h2 style="color: #1abc9c;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Go Fishing --> <div style="border: 3px solid #1abc9c; border-radius: 10px; padding: 15px; background: #1a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(26,188,156,0.15); display: flex; flex-direction: column;"> <h3 style="color: #1abc9c; margin: 0 0 10px 0;">🎣 Go Fishing</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Cast your line into the oasis spring. Mysterious fish are said to dwell in these hidden waters.</p> <<link "<div style='background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go Fishing</div>">> <<goto "FishingOasis">> <</link>> </div> <!-- Siren Water Dance (Night + Siren + 300 base DEX) --> <<if (getTimeOfDay() === "evening" || getTimeOfDay() === "night") && $physicalTraits.includes("Siren") && $stats && $stats.dexterity >= 300>> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #1a1a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(155,89,182,0.15); display: flex; flex-direction: column;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🎵 Sing to the Waters</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The moonlit waters call to you. Your siren voice could awaken something beneath the surface.</p> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Begin Singing</div>">> <<goto "OasisSirenDance">> <</link>> </div> <</if>> </div> <h2 style="color: #1abc9c;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Return to Desert --> <div style="border: 3px solid #c2953a; border-radius: 10px; padding: 15px; background: #2a2a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #c2953a; margin: 0 0 10px 0;">🏜️ The Desert</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Head back out into the desert sands.</p> <<link "<div style='background: linear-gradient(135deg, #c2953a 0%, #8B6914 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Return to Desert (15 min)</div>">> <<advancetime 15>> <<goto "Desert">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<if !$fishingSkill>><<set $fishingSkill = {xp: 0}>><</if>> <<if !$fishCollection>><<set $fishCollection = []>><</if>> <<if !$fishingStats>><<set $fishingStats = {totalCatches: 0, moneyEarned: 0}>><</if>> <<set _hasRod = $fishingPole && $fishingPole > 0>> <<if !$fishInventory>><<set $fishInventory = []>><</if>> <<if !$tackle>><<set $tackle = {hook: null, line: null}>><</if>> <<set _level = setup.fishing.getLevel()>> <<set _xpProgress = setup.fishing.getXpProgress()>> <<set _stats = setup.fishing.getCollectionStats()>> <<set _pole = setup.fishing.getCurrentPole()>> <<set _poleTier = $fishingPole || 0>> <<set _invCount = setup.fishing.getInventoryCount()>> <<set _maxInv = setup.fishing.getMaxInventory()>> <<set _invFull = setup.fishing.isInventoryFull()>> <<set _themeColor = "#1abc9c">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button (Top) --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #1abc9c; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #1abc9c44; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "Oasis">><</link>> </div> <!-- Header Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid <<print _themeColor>>; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px <<print _themeColor>>44; margin-bottom: 20px;"> <h2 style="color: <<print _themeColor>>; margin: 0 0 10px 0; text-align: center;">🏝️ Oasis Fishing</h2> <p style="color: #aaa; margin: 0; font-size: 14px; text-align: center;">A hidden desert spring teeming with mysterious fish.</p> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333; margin-top: 15px;"> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; text-align: center;"> <div> <div style="color: #3498db; font-size: 20px; font-weight: bold;">Lv <<print _level>></div> <div style="color: #888; font-size: 11px;">Skill</div> <div style="background: #333; border-radius: 4px; height: 6px; margin-top: 4px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #3498db, #1abc9c); height: 100%; width: <<print _xpProgress.percent>>%;"></div> </div> </div> <div> <div style="color: #2ecc71; font-size: 20px; font-weight: bold;">$<<print $money || 0>></div> <div style="color: #888; font-size: 11px;">Money</div> </div> <div> <div style="color: #f39c12; font-size: 20px; font-weight: bold;"><<print _invCount>>/<<print _maxInv>></div> <div style="color: #888; font-size: 11px;">Storage</div> </div> <div> <div style="color: #9b59b6; font-size: 20px; font-weight: bold;"><<print _stats.caught>>/<<print _stats.total>></div> <div style="color: #888; font-size: 11px;">Collection</div> </div> </div> </div> </div> <!-- Equipment Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 1px solid #333; text-align: center;"> <div style="color: <<if _poleTier === 4>>#e040fb<<elseif _poleTier === 3>>#ffd700<<elseif _poleTier === 2>>#3498db<<elseif _poleTier === 1>>#aaa<<else>>#e74c3c<</if>>; font-size: 16px; font-weight: bold;">🎣 <<if _hasRod>><<print _pole.name>><<else>>No Rod<</if>></div> <<if _hasRod>> <<set _maxRarity = setup.fishing.getMaxRarity(_pole)>> <div style="color: #888; font-size: 11px;">Max: <span style="color: <<print setup.fishing.rarityColors[_maxRarity]>>;"><<print _maxRarity.toUpperCase()>></span></div> <<if _poleTier === 4>><div style="color: #51cf66; font-size: 10px; margin-top: 3px;">No Trash • Treasure Bonus</div><</if>> <<else>> <div style="color: #e74c3c; font-size: 11px;">Buy at dealership</div> <</if>> </div> </div> <!-- Cast Line Button --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 25px; border-radius: 12px; border: 3px solid #1abc9c; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px #1abc9c44; margin-bottom: 20px; text-align: center;"> <<if setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #ff6b6b;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #ff6b6b; font-size: 20px; font-weight: bold;">Too Exhausted to Fish</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">You need to sleep before you can fish</div> </div> <<elseif !_hasRod>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🎣</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">No Fishing Rod!</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Buy one at the dealership</div> </div> <<elseif _invFull>> <div style="background: linear-gradient(135deg, #555 0%, #333 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; border: 3px solid #e74c3c;"> <div style="font-size: 40px; margin-bottom: 8px;">🐟</div> <div style="color: #e74c3c; font-size: 20px; font-weight: bold;">Inventory Full</div> <div style="color: #888; font-size: 13px; margin-top: 5px;">Sell fish at the dealership</div> </div> <<else>> <<link "<div style='background: linear-gradient(135deg, #16a085 0%, #1abc9c 100%); padding: 25px 50px; border-radius: 12px; display: inline-block; cursor: pointer; border: 3px solid #16a085; box-shadow: 0 4px 15px rgba(22, 160, 133, 0.5);'><div style='font-size: 40px; margin-bottom: 8px;'>🎣</div><div style='color: white; font-size: 20px; font-weight: bold;'>Cast Line</div></div>">> <<set $fishingLocation = "oasis">> <<goto "FishingQTE">> <</link>> <</if>> </div> <!-- Navigation --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 12px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <div style="display: flex; flex-wrap: wrap; gap: 10px; justify-content: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #9b59b6; color: #9b59b6; padding: 12px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>📖 Collection</div>">><<goto "FishEncyclopedia">><</link>> </div> </div> <!-- Back Button (Bottom) --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #1abc9c; color: white; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px #1abc9c44; display: inline-block;'>← Leave Fishing</div>">><<set $fishingLocation = null>><<goto "Oasis">><</link>> </div> </div> <</nobr>>
<<nobr>> <!-- Track location visit --> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("Manor")>> <<run $visitedLocations.push("Manor")>> <</if>> <<set $lastLocation = "Manor">> <!-- Day check: if it becomes day while inside the manor, pass out (bypassed by certain traits) --> <<set _canStayInManor = $physicalTraits.includes("Vampire") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>> <<if $manorUnlocked && !_canStayInManor && (getTimeOfDay() !== "evening" && getTimeOfDay() !== "night")>> <<goto "ManorPassout">> <</if>> <style> @keyframes manorFlicker { 0%, 92%, 100% { opacity: 0; } 93%, 97% { opacity: 0.15; } } @keyframes shadowCreep { 0%, 100% { transform: translateX(0px) scaleX(1); opacity: 0.3; } 50% { transform: translateX(5px) scaleX(1.1); opacity: 0.5; } } .manor-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 30% 20%, rgba(106,13,173,0.04) 0%, transparent 50%); pointer-events: none; z-index: 0; animation: manorFlicker 8s ease-in-out infinite; } </style> <div class="manor-overlay"></div> <div style="background: #0a0008; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #9b59b6; text-align: center;">🏚️ The Manor</h1> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/Manor.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #6a0dad; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="The Manor"> </div> <</if>> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2a 0%, #0d0018 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #6a0dad;"> <p style="color: #c9a0dc; font-size: 18px; margin: 0; text-shadow: 1px 1px 2px rgba(0,0,0,0.5);"> The manor looms before you in the moonlight, a grand but decaying edifice of dark stone and rotting timber. Dead ivy clings to the walls like grasping fingers. The windows are dark — some cracked, some missing entirely — and the overgrown grounds are choked with thorny brambles. An oppressive silence hangs over everything, as though even the wind refuses to come here. </p> </div> <!-- MANOR STATE: Locked vs Unlocked --> <<if !$manorUnlocked>> <<if $hasManorKey>> <div style="padding: 25px; background: #1a0a2a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6; text-align: center;"> <div style="font-size: 48px; margin-bottom: 15px;">🗝️</div> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">The Strange Key Resonates</h3> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6; margin: 0 0 15px 0;"> As you approach the door, the strange key in your pocket grows ice-cold. You pull it out and hold it before the massive ornate lock. The thorned handle seems to writhe in the moonlight. With trembling hands, you slide the key into the lock. It fits perfectly. A deep, resonant click echoes through the silence, and the door swings inward on its own, revealing nothing but darkness beyond. </p> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 15px rgba(106,13,173,0.4);'>🗝️ Enter the Manor</div>">> <<set $manorUnlocked = true>> <<goto "ManorInterior">> <</link>> </div> <<else>> <div style="padding: 25px; background: #1a0a2a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #4a0080; text-align: center;"> <div style="font-size: 48px; margin-bottom: 15px;">🔒</div> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">The Door is Locked</h3> <p style="color: #8e7a9e; font-size: 16px; line-height: 1.6; margin: 0 0 15px 0;"> The front door bears a massive ornate lock — wrought iron, intricately decorated with symbols you don't recognize. Despite its age, the mechanism is solid. You pull at it, push against the door, even try the windows, but nothing gives. Whatever secrets this manor holds, they're sealed behind this lock. You'd need to find the key somewhere. </p> <div style="background: #0d0018; padding: 12px; border-radius: 8px; border: 1px solid #4a0080;"> <p style="color: #6a0dad; font-size: 14px; font-style: italic; margin: 0;">You need a key to enter the Manor...</p> </div> </div> <</if>> <<else>> <div style="padding: 25px; background: #1a0a2a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6; text-align: center;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6; margin: 0 0 15px 0;"> The front door hangs open, the lock shattered from when you used the key. Darkness spills out from within like a living thing. The manor awaits. </p> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 15px rgba(106,13,173,0.4);'>Enter the Manor</div>">> <<goto "ManorInterior">> <</link>> </div> <</if>> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _isLivingDoll = $physicalTraits && $physicalTraits.includes("Living Doll")>> <<set _isAutomaton = $physicalTraits && $physicalTraits.includes("Automaton")>> <<set _isImmune = _isLivingDoll || _isAutomaton>> <<set _isFast = $physicalTraits && ($physicalTraits.includes("Fast") || $physicalTraits.includes("Quick") || $physicalTraits.includes("Quick Reflexes") || $physicalTraits.includes("Athletic Build") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Flexible") || $physicalTraits.includes("Graceful") || $physicalTraits.includes("Lean") || $physicalTraits.includes("Dexterous"))>> <<set _hasHoney = $physicalTraits && $physicalTraits.includes("Honey")>> <<set _hasFire = $physicalTraits && ($physicalTraits.includes("Cerberus") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Salamander"))>> <style> @keyframes beesBuzz { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-2px); } 75% { transform: translateX(2px); } } .bee-hive-glow { animation: beesBuzz 0.3s ease-in-out infinite; } @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } </style> <div style="background: linear-gradient(180deg, #1a1a0a 0%, #0d0d00 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #f0a500; text-align: center; text-shadow: 0 0 20px rgba(240,165,0,0.3);">🐝 Giant Beehive</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a0a 0%, #1a1a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f0a500; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(240,165,0,0.15);"> <p style="color: #ddd; font-size: 16px; line-height: 1.6;"> You push through a curtain of hanging vines and stop dead in your tracks. Suspended from the thick lower branch of an enormous jungle tree is a beehive the size of a small car. Its waxy surface glistens with amber honey that oozes down in slow, golden rivulets. The air thrums with the deep, resonant buzz of thousands of bees, their dark shapes swirling in lazy patterns around the hive's entrance. </p> <p style="color: #ddd; font-size: 16px; line-height: 1.6;"> The honey smells incredible — rich, sweet, and wild, unlike anything you've encountered before. The bees don't seem aggressive yet, but the sheer number of them gives you pause. This is their territory. </p> </div> <div id="beehive-choices"> <!-- Option A: Poke with stick --> <div style="border: 3px solid #c0392b; border-radius: 10px; padding: 15px; background: #2a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🪵 Poke it with a stick</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Find a long branch and give the hive a good whack. What could go wrong?</p> <<link "<div style='background: linear-gradient(135deg, #c0392b 0%, #962d22 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Poke the Hive</div>">> <<replace "#beehive-choices">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 3px solid #c0392b;"> <p style="color: #e74c3c; font-size: 16px; line-height: 1.6; font-weight: bold;">You grab a sturdy branch, wind up, and give the hive a solid whack.</p> <p style="color: #ddd; font-size: 16px; line-height: 1.6;">The reaction is instant and terrifying. The calm buzzing erupts into a furious roar as a black cloud of bees boils out of the hive. You drop the stick and run.</p> <<if _isImmune>> <p style="color: #f0a500; font-size: 16px; line-height: 1.6;"> The swarm descends on you in seconds, covering your arms and face. But their stingers <<if _isLivingDoll>> click uselessly against your porcelain skin. You're a Living Doll — their venom can't penetrate you. <<else>> scrape harmlessly against your metallic exterior. You're an Automaton — they can't hurt you at all. <</if>> After a few confused moments, the bees begin to lose interest. You walk calmly back to the damaged hive and scoop out a generous handful of golden honey. </p> <<if !_hasHoney>> <<run $physicalTraits.push("Honey")>> <div style="background: #3a3a0a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #f0a500; text-align: center;"> <p style="color: #f0a500; font-size: 18px; font-weight: bold; margin: 0;">🍯 You gained the Honey trait!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">Your skin glistens with a permanent golden sheen of wild honey.</p> </div> <<else>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #888; text-align: center;"> <p style="color: #888; font-size: 14px; margin: 0;">You're already coated in honey. The extra honey doesn't seem to change anything.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> <<elseif _isFast>> <p style="color: #3498db; font-size: 16px; line-height: 1.6;"> Your legs pump hard as you tear through the undergrowth. Thanks to your speed and agility, you outpace most of the swarm. A few persistent bees land stings on your arms and neck, but the main cloud falls behind, unable to keep up. You skid to a stop behind a massive tree trunk, breathing hard, welts already rising on your skin. </p> <p style="color: #ddd; font-size: 16px; line-height: 1.6;"> The swarm has mostly dispersed back toward the hive. The damage you did knocked a chunk of honeycomb loose — you can see it glistening on the ground back there. You could go back and grab it before the bees regroup... </p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin-top: 15px;"> <div style="border: 2px solid #f0a500; border-radius: 8px; padding: 12px; background: #2a2a0a;"> <h3 style="color: #f0a500; margin: 0 0 8px 0; font-size: 15px;">🍯 Go back for the honey</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">Risk a few more stings to grab the honeycomb.</p> <<link "<div style='background: linear-gradient(135deg, #f0a500 0%, #c88500 100%); color: #1a1a00; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Grab It</div>">> <<replace "#beehive-choices">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 3px solid #f0a500;"> <p style="color: #ddd; font-size: 16px; line-height: 1.6;"> You sprint back to the hive. A handful of guard bees immediately lock onto you, stinging your hands and arms as you snatch the chunk of dripping honeycomb from the ground. Pain flares across your skin, but you grit your teeth and clutch the prize to your chest as you run. By the time you're clear of their territory, your arms are covered in angry red welts — but your hands are full of the most incredible honey you've ever tasted. </p> <<if !_hasHoney>> <<run $physicalTraits.push("Honey")>> <div style="background: #3a3a0a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #f0a500; text-align: center;"> <p style="color: #f0a500; font-size: 18px; font-weight: bold; margin: 0;">🍯 You gained the Honey trait!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">Your skin glistens with a permanent golden sheen of wild honey.</p> </div> <<else>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #888; text-align: center;"> <p style="color: #888; font-size: 14px; margin: 0;">You're already coated in honey. The extra honey doesn't seem to change anything.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</replace>> <</link>> </div> <div style="border: 2px solid #2ecc71; border-radius: 8px; padding: 12px; background: #1a2a1a;"> <h3 style="color: #2ecc71; margin: 0 0 8px 0; font-size: 15px;">🚶 Get out while you can</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 10px 0;">You've had enough bee encounters for one day.</p> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Leave</div>">> <<replace "#beehive-choices">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 3px solid #2ecc71;"> <p style="color: #ddd; font-size: 16px; line-height: 1.6;"> You decide not to push your luck. The welts on your arms sting enough as it is. You circle wide around the hive's territory and make your way back through the jungle, leaving the honey behind. Smart move. Probably. </p> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</replace>> <</link>> </div> </div> <<else>> <!-- Not immune, not fast: stung badly --> <p style="color: #e74c3c; font-size: 16px; line-height: 1.6;"> You don't make it ten steps. The swarm catches you almost instantly, bees blanketing your arms, your neck, your face. Each sting is a white-hot needle of pain. You flail and stumble, crashing through bushes, but there's no escaping them. The world blurs. Your legs buckle. The last thing you see before everything goes dark is the jungle canopy spinning above you. </p> <<run setup.addDebuff("exhaustion")>> <<if $appearance.hairStyle !== "messy">> <<run setup.setHairMessy()>> <</if>> <<timed 2s>> <div class="fade-in" style="text-align: center; padding: 20px;"> <p style="color: #444; font-size: 16px;">Everything goes dark...</p> </div> <</timed>> <<timed 4s>> <div class="fade-in" style="text-align: center; padding: 20px;"> <p style="color: #555; font-size: 16px;">Time passes... you drift in and out of consciousness...</p> </div> <</timed>> <<timed 7s>> <div class="fade-in" style="text-align: center; padding: 20px;"> <p style="color: #aaa; font-size: 18px;">You wake up back at <strong style="color: #D2691E;">The Nest</strong>, covered in swollen stings and feeling terrible. Someone must have found you and dragged you back.</p> <p style="color: #666; font-size: 14px; font-style: italic; margin-top: 10px;">You gained the <strong style="color: #ff5722;">Exhaustion</strong> debuff. Your hair is a mess.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #D2691E; color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up at The Nest</div>">> <<goto "The Nest">> <</link>> </div> <</timed>> <</if>> </div> <</replace>> <</link>> </div> <!-- Option B: Stick hand in --> <div style="border: 3px solid #f0a500; border-radius: 10px; padding: 15px; background: #2a2a0a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #f0a500; margin: 0 0 10px 0;">✋ Stick your hand in and grab honey</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Go direct. Reach into the hive and take what you want.</p> <<link "<div style='background: linear-gradient(135deg, #f0a500 0%, #c88500 100%); color: #1a1a00; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Reach In</div>">> <<replace "#beehive-choices">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 3px solid #f0a500;"> <<if _isImmune>> <p style="color: #f0a500; font-size: 16px; line-height: 1.6;"> You reach directly into the hive. Bees swarm your arm immediately, covering every inch of exposed skin. Their stingers <<if _isLivingDoll>> click against your porcelain surface without effect. You're a Living Doll — they can't pierce you. <<else>> scrape uselessly against your metallic plating. You're an Automaton — their venom is meaningless to you. <</if>> You dig deep, pulling out a massive chunk of golden honeycomb, honey dripping between your fingers. </p> <<if !_hasHoney>> <<run $physicalTraits.push("Honey")>> <div style="background: #3a3a0a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #f0a500; text-align: center;"> <p style="color: #f0a500; font-size: 18px; font-weight: bold; margin: 0;">🍯 You gained the Honey trait!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">Your skin glistens with a permanent golden sheen of wild honey.</p> </div> <<else>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #888; text-align: center;"> <p style="color: #888; font-size: 14px; margin: 0;">You're already coated in honey. The extra honey doesn't seem to change anything.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> <<else>> <p style="color: #e74c3c; font-size: 16px; line-height: 1.6;"> You shove your hand into the hive. For one glorious moment, you feel warm, sticky honey coat your fingers. Then the pain hits. Dozens of bees sting your hand, your wrist, your arm, all at once. You yank your arm back with a scream, flinging bees everywhere, but the damage is done. Your hand swells immediately. More bees pour out, furious. The stings come faster and faster. Your vision tunnels. The jungle tilts sideways as your knees give out. </p> <<run setup.addDebuff("exhaustion")>> <<if $appearance.hairStyle !== "messy">> <<run setup.setHairMessy()>> <</if>> <<timed 2s>> <div class="fade-in" style="text-align: center; padding: 20px;"> <p style="color: #444; font-size: 16px;">Everything goes dark...</p> </div> <</timed>> <<timed 4s>> <div class="fade-in" style="text-align: center; padding: 20px;"> <p style="color: #555; font-size: 16px;">Time passes... you drift in and out of consciousness...</p> </div> <</timed>> <<timed 7s>> <div class="fade-in" style="text-align: center; padding: 20px;"> <p style="color: #aaa; font-size: 18px;">You wake up back at <strong style="color: #D2691E;">The Nest</strong>, your hand swollen to twice its size and covered in angry welts. At least you're alive.</p> <p style="color: #666; font-size: 14px; font-style: italic; margin-top: 10px;">You gained the <strong style="color: #ff5722;">Exhaustion</strong> debuff. Your hair is a mess. You didn't manage to keep any honey.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #D2691E; color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up at The Nest</div>">> <<goto "The Nest">> <</link>> </div> <</timed>> <</if>> </div> <</replace>> <</link>> </div> <!-- Option C: Leave --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #1a2a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 15px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🚶 Leave it alone</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Not worth the risk. Back away slowly and continue exploring.</p> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Walk Away</div>">> <<goto "Jungle">> <</link>> </div> <!-- Option D: Smoke them out (conditional - fire traits only) --> <<if _hasFire>> <div style="border: 3px solid #e67e22; border-radius: 10px; padding: 15px; background: #2a1a0a; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(230,126,34,0.2); margin-bottom: 15px;"> <h3 style="color: #e67e22; margin: 0 0 10px 0;">🔥 Smoke them out</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Use your fire abilities to produce smoke and calm the bees.</p> <<link "<div style='background: linear-gradient(135deg, #e67e22 0%, #d35400 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Use Fire</div>">> <<replace "#beehive-choices">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 3px solid #e67e22;"> <p style="color: #e67e22; font-size: 16px; line-height: 1.6;"> You summon a controlled burst of heat, directing it beneath the hive. Thick, warm smoke billows upward, enveloping the hive and its inhabitants. The frantic buzzing slows almost immediately as the bees become drowsy and docile, retreating deeper into the hive. Within moments, the entrance is clear. </p> <p style="color: #ddd; font-size: 16px; line-height: 1.6;"> You reach in without resistance, scooping out thick handfuls of golden honeycomb. The bees barely stir. The honey is warm from your fire, rich and sweet, coating your hands and arms in a glistening amber layer. </p> <<if !_hasHoney>> <<run $physicalTraits.push("Honey")>> <div style="background: #3a3a0a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #f0a500; text-align: center;"> <p style="color: #f0a500; font-size: 18px; font-weight: bold; margin: 0;">🍯 You gained the Honey trait!</p> <p style="color: #aaa; font-size: 14px; margin: 5px 0 0 0;">Your skin glistens with a permanent golden sheen of wild honey.</p> </div> <<else>> <div style="background: #2a2a1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #888; text-align: center;"> <p style="color: #888; font-size: 14px; margin: 0;">You're already coated in honey. The extra honey doesn't seem to change anything.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 25px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</replace>> <</link>> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "CleanRoomInner">> <style> @keyframes mechPulse { 0%, 100% { box-shadow: 0 0 20px rgba(205,127,50,0.3), 0 0 40px rgba(205,127,50,0.1); } 50% { box-shadow: 0 0 40px rgba(205,127,50,0.6), 0 0 80px rgba(205,127,50,0.3); } } @keyframes floatRock { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-8px); } } </style> <div style="background: linear-gradient(180deg, #1a1008 0%, #0d0804 100%); min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #cd7f32; text-align: center; text-shadow: 0 0 15px rgba(205,127,50,0.5);">⚙️ The Inner Chamber</h1> <div style="padding: 25px; background: linear-gradient(135deg, #2a1a0a 0%, #1a1008 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B6914;"> <p style="color: #c9a06c; font-size: 16px; line-height: 1.6;"> The door slides open with a sound like exhaling machinery, revealing a chamber that takes your breath away. Brass and copper cover every surface — the walls, the ceiling, even the floor beneath your feet. Pipes of varying widths crisscross overhead, some leaking thin wisps of steam. Gears of every size are mounted on the walls, some spinning lazily, some locked in place by centuries of oxidation. The air smells of oil and ozone and something older — something that predates the island itself. </p> <p style="color: #c9a06c; font-size: 16px; line-height: 1.6; margin-top: 15px;"> In the center of the room, on a pedestal of interlocking brass plates, sits a stone. No — not a stone. A <em>mechanism</em> shaped like a stone. Its surface is covered in impossibly fine gearwork, thousands of tiny cogs and wheels meshed together so precisely they look like natural rock grain. It hovers a fraction of an inch above the pedestal, spinning almost imperceptibly, suspended by forces you cannot begin to understand. It radiates warmth and a low, rhythmic hum that resonates in your chest. </p> </div> <div id="cogTouchArea" style="text-align: center; margin-bottom: 25px;"> <<if $physicalTraits.includes("Cog")>> <div style="padding: 20px; background: #1a2a10; border-radius: 12px; border: 2px solid #51cf66;"> <p style="color: #51cf66; font-size: 18px; font-weight: bold; margin: 0;">The mechanical stone hums in recognition. The gears within you turn in harmony with the ones around you.</p> </div> <<else>> <div style="padding: 25px; background: linear-gradient(135deg, #2a1a0a 0%, #1a1008 100%); border-radius: 15px; border: 2px solid #cd7f32; animation: mechPulse 3s ease-in-out infinite;"> <div style="font-size: 64px; text-align: center; margin-bottom: 15px; animation: floatRock 3s ease-in-out infinite;">⚙️</div> <p style="color: #ffd700; font-size: 18px; text-align: center; margin: 0 0 15px 0;">The mechanical stone pulses with ancient energy. Do you dare to touch it?</p> <<link "<div style='background: linear-gradient(135deg, #cd7f32 0%, #8B6914 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 20px rgba(205,127,50,0.6);'>✋ Touch the Stone</div>">> <<replace "#cogTouchArea">> <div style="padding: 25px; background: linear-gradient(135deg, #2a1a0a 0%, #1a1008 100%); border-radius: 15px; border: 2px solid #ffd700;"> <p style="color: #ffd700; font-size: 18px; line-height: 1.6;"> Your fingers make contact with the surface and the world <em>shifts</em>. Every gear in the room lurches into motion simultaneously. The hum becomes a roar, then a song, then something beyond sound entirely. You feel it in your bones — your very cells rearranging, strengthening, hardening. Ancient mechanical knowledge floods through you like molten brass pouring into a mold. Your muscles tighten, your mind sharpens, and for one blinding moment you understand how everything fits together — every gear, every lever, every mechanism the universe has ever produced. </p> <p style="color: #ffd700; font-size: 18px; line-height: 1.6; margin-top: 15px;"> Then it fades. The gears slow. The stone settles back onto its pedestal, inert. But you’re different now. You can feel it — a clockwork precision in your movements, an iron strength in your limbs, a mechanical clarity in your thoughts. </p> <div style="background: #0d0804; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #ffd700; text-align: center;"> <p style="color: #ffd700; font-size: 22px; font-weight: bold; margin: 0; text-shadow: 0 0 15px rgba(255,215,0,0.8);">⚙️ You gained the Cog trait!</p> <p style="color: #cd7f32; font-size: 14px; margin: 5px 0 0 0;">+70 Strength, +20 Intelligence, -10 Dexterity</p> </div> </div> <<run $physicalTraits.push("Cog")>> <<run setup.achievements.unlock("transform_cog")>> <</replace>> <</link>> </div> <</if>> </div> <!-- Return link --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to the Gear Room</div>">> <<goto "MountainCleanRoom">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MountainCliff">> <div style="background: #0a0505; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #8B0000; text-align: center;">🧗 The Cliff</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a0a 0%, #0a0505 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B0000;"> <p style="color: #c0a0a0; font-size: 16px; line-height: 1.6;"> You stand at the edge of the cliff, wind tearing at your clothes. The drop is staggering — at least a thousand feet, maybe three hundred meters, straight down into a rocky abyss shrouded in a faint, unnatural haze. The air rising from below carries a strange smell, something metallic and ancient. Loose pebbles skitter off the edge and vanish into the void without a sound. Far below, through the haze, you think you can make out... shapes. Objects. But that could just be your imagination playing tricks. </p> </div> <div style="display: flex; flex-direction: column; gap: 15px; align-items: center;"> <!-- PHARAOH CHECK: No jump option at all --> <<if $physicalTraits.includes("Pharaoh")>> <div style="padding: 20px; background: #1a1a0a; border-radius: 10px; border: 2px solid #c9b458; text-align: center; max-width: 500px;"> <p style="color: #c9b458; font-size: 16px; line-height: 1.6;"> Something deep within you recoils from the edge. An ancient, imperious instinct seizes your limbs and refuses to let you step forward. You are a ruler — you do not throw yourself into the abyss. The cliff holds no power over you. You cannot bring yourself to jump, no matter what. </p> </div> <<else>> <!-- JUMP BUTTON --> <<link "<div style='background: linear-gradient(135deg, #8B0000 0%, #4a0000 100%); color: white; padding: 15px 60px; border-radius: 10px; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 15px rgba(139,0,0,0.4);'>Jump</div>">> <<replace "#cliffResult">> <!-- WINGED TRAITS: Dark Angel, Angel, Cupid, Honeybee, Succubus --> <<if $physicalTraits.includes("Dark Angel") || $physicalTraits.includes("Angel") || $physicalTraits.includes("Cupid") || $physicalTraits.includes("Honeybee") || ($physicalTraits.includes("Succubus") || $physicalTraits.includes("Voluptuous Succubus"))>> <div style="padding: 20px; background: #0a1a2a; border-radius: 10px; border: 2px solid #5c9ead; margin-bottom: 15px;"> <p style="color: #5c9ead; font-size: 16px; line-height: 1.6;"> You step off the edge and plunge into the void. The wind screams past you — and then your wings snap open, catching the updraft. The fall becomes a glide, smooth and controlled. You spiral downward through the haze, the rocky ground below growing closer and closer, until your feet touch down softly at the base of the cliff. The landing is gentle, almost graceful. </p> <p style="color: #5c9ead; font-size: 16px; line-height: 1.6;"> Before you, in this desolate hollow at the bottom of the world, two objects sit on a flat stone altar: <strong style="color: #4a0040;">an orb of swirling, absolute darkness</strong> and <strong style="color: #8B4513;">a goblet filled with amber liquid that reeks of alcohol</strong>. </p> <<include "CliffChoice">> </div> <!-- AUTOMATON: Withstand impact --> <<elseif $physicalTraits.includes("Automaton")>> <div style="padding: 20px; background: #0a1a1a; border-radius: 10px; border: 2px solid #cd7f32; margin-bottom: 15px;"> <p style="color: #cd7f32; font-size: 16px; line-height: 1.6;"> You step off the edge without hesitation. The fall is long, the wind deafening. You hit the ground with a thunderous impact that cracks the stone beneath you. Dust and debris erupt outward in a shockwave. But you stand up, perfectly fine. Your mechanical frame absorbed the force without so much as a dent. Internal systems nominal. Structural integrity: 100%. </p> <p style="color: #cd7f32; font-size: 16px; line-height: 1.6;"> Before you, in this desolate hollow at the bottom of the world, two objects sit on a flat stone altar: <strong style="color: #4a0040;">an orb of swirling, absolute darkness</strong> and <strong style="color: #8B4513;">a goblet filled with amber liquid that reeks of alcohol</strong>. </p> <<include "CliffChoice">> </div> <!-- LIVING DOLL: Fall unconscious, wake at Nest --> <<elseif $physicalTraits.includes("Living Doll")>> <div style="padding: 20px; background: #1a0a1a; border-radius: 10px; border: 2px solid #d4a0d4; margin-bottom: 15px;"> <p style="color: #d4a0d4; font-size: 16px; line-height: 1.6;"> You step off the edge. The world becomes a blur of grey stone and screaming wind. You hit the ground, but your porcelain body doesn't shatter — it bounces, cracks, reforms. Consciousness slips away like water through fingers. </p> <p style="color: #d4a0d4; font-size: 16px; line-height: 1.6;"> When you come to, you're lying on familiar ground. Somehow, impossibly, you're back at The Nest. Your body has mended itself, though the memory of the fall lingers like a bad dream. </p> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #d4a0d4 0%, #a070a0 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up at The Nest</div>">> <<goto "The Nest">> <</link>> </div> </div> <!-- BANSHEE: Float down --> <<elseif $physicalTraits.includes("Banshee")>> <div style="padding: 20px; background: #0a0a1a; border-radius: 10px; border: 2px solid #7070c0; margin-bottom: 15px;"> <p style="color: #7070c0; font-size: 16px; line-height: 1.6;"> You step off the edge and... don't fall. Or rather, you fall slowly, impossibly slowly, your spectral form drifting downward like a leaf on still air. The wind passes through you. The haze parts around you. You descend in utter silence, your feet touching the ground at the bottom as gently as a whisper. </p> <p style="color: #7070c0; font-size: 16px; line-height: 1.6;"> Before you, in this desolate hollow at the bottom of the world, two objects sit on a flat stone altar: <strong style="color: #4a0040;">an orb of swirling, absolute darkness</strong> and <strong style="color: #8B4513;">a goblet filled with amber liquid that reeks of alcohol</strong>. </p> <<include "CliffChoice">> </div> <!-- DEFAULT: No special trait, hit ground hard, hospital --> <<else>> <div style="padding: 20px; background: #1a0a0a; border-radius: 10px; border: 2px solid #ff4444; margin-bottom: 15px;"> <p style="color: #ff4444; font-size: 16px; line-height: 1.6;"> You jump. There is no grace in it, no plan. Just the sickening lurch of free fall and the wind tearing tears from your eyes. The ground rushes up to meet you with horrifying speed. The impact is catastrophic. Everything goes white, then black. </p> <p style="color: #ff4444; font-size: 16px; line-height: 1.6;"> ...You don't know how long you were unconscious. When you finally open your eyes, you're staring at a white ceiling. Fluorescent lights. The smell of antiseptic. A nurse is telling you that you're lucky to be alive, that you've been in a coma for an entire year. Three hundred and sixty-five days, gone. </p> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #ff4444 0%, #cc0000 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Discharged from Hospital</div>">> <<if $rouletteSystem && $rouletteSystem.lockoutStartDay > 0>><<set $rouletteSystem.lockoutStartDay += 365>><</if>> <<set $dayNumber += 365>> <<goto "Hospital">> <</link>> </div> </div> <</if>> <</replace>> <</link>> <</if>> <!-- LEAVE BUTTON (always available) --> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 60px; border-radius: 10px; font-weight: bold; font-size: 16px; cursor: pointer;'>Step Back from the Edge</div>">> <<goto "Mountains">> <</link>> </div> <!-- Result area --> <div id="cliffResult"></div> </div> <</nobr>>
<<nobr>> <!-- CLIFF BOTTOM CHOICE --> <!-- Check if player already has BOTH Darkness and Alcoholic --> <<if $physicalTraits.includes("Darkness") && $physicalTraits.includes("Alcoholic")>> <!-- Third object: pitch black goblet --> <<if $physicalTraits.includes("Disturbed")>> <!-- Already have all three traits, just pass out --> <p style="color: #666; font-size: 16px; line-height: 1.6; margin-top: 15px;"> The altar is empty. There is nothing here for you anymore. A wave of exhaustion crashes over you and the world goes dark. </p> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #333 0%, #111 100%); color: #999; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up</div>">> <<goto "Alleyway">> <</link>> </div> <<else>> <p style="color: #1a001a; font-size: 16px; line-height: 1.6; margin-top: 15px;"> The orb and goblet are gone. In their place sits a single object: a goblet carved from obsidian, filled with a liquid so dark it seems to drink the light around it. Black smoke curls from its surface, coiling like living things. There is no other path. No other choice. You must drink if you want to leave this place. </p> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #1a001a 0%, #000 100%); color: #4a004a; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; border: 2px solid #4a004a; box-shadow: 0 0 20px rgba(74,0,74,0.5);'>Drink the Black Elixir</div>">> <<if !$physicalTraits.includes("Disturbed")>><<run $physicalTraits.push("Disturbed")>><</if>> <<goto "Alleyway">> <</link>> </div> <</if>> <<else>> <!-- Normal choice: orb or goblet --> <p style="color: #aaa; font-size: 15px; line-height: 1.6; margin-top: 15px; text-align: center; font-style: italic;">You must choose one before you can leave this place.</p> <div style="display: flex; gap: 20px; justify-content: center; flex-wrap: wrap; margin-top: 15px;"> <!-- ORB OF DARKNESS --> <<if !$physicalTraits.includes("Darkness")>> <<link "<div style='background: linear-gradient(135deg, #1a001a 0%, #000 100%); color: #6a006a; padding: 20px 30px; border-radius: 10px; font-weight: bold; font-size: 15px; cursor: pointer; border: 2px solid #4a004a; box-shadow: 0 0 20px rgba(74,0,74,0.4); text-align: center; min-width: 180px;'>⚫ Touch the Orb of Darkness</div>">> <<if !$physicalTraits.includes("Darkness")>><<run $physicalTraits.push("Darkness")>><</if>> <<goto "The Nest">> <</link>> <<else>> <div style="background: #111; color: #444; padding: 20px 30px; border-radius: 10px; font-size: 15px; border: 2px solid #333; text-align: center; min-width: 180px; font-style: italic;">⚫ Darkness already claimed</div> <</if>> <!-- GOBLET OF ALCOHOL --> <<if !$physicalTraits.includes("Alcoholic")>> <<link "<div style='background: linear-gradient(135deg, #3a2000 0%, #1a1000 100%); color: #c9853a; padding: 20px 30px; border-radius: 10px; font-weight: bold; font-size: 15px; cursor: pointer; border: 2px solid #8B4513; box-shadow: 0 0 20px rgba(139,69,19,0.4); text-align: center; min-width: 180px;'>🍷 Drink from the Goblet</div>">> <<if !$physicalTraits.includes("Alcoholic")>><<run $physicalTraits.push("Alcoholic")>><</if>> <<goto "The Nest">> <</link>> <<else>> <div style="background: #111; color: #444; padding: 20px 30px; border-radius: 10px; font-size: 15px; border: 2px solid #333; text-align: center; min-width: 180px; font-style: italic;">🍷 Already an Alcoholic</div> <</if>> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "ManorInterior">> <!-- Day check --> <<set _canStayInManor = $physicalTraits.includes("Vampire") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>> <<if !_canStayInManor && (getTimeOfDay() !== "evening" && getTimeOfDay() !== "night")>> <<goto "ManorPassout">> <</if>> <style> @keyframes manorFlicker { 0%, 92%, 100% { opacity: 0; } 93%, 97% { opacity: 0.15; } } @keyframes candleGlow { 0%, 100% { opacity: 0.4; text-shadow: 0 0 8px rgba(255,160,50,0.6); } 50% { opacity: 0.8; text-shadow: 0 0 15px rgba(255,160,50,0.9); } } .manor-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 30% 20%, rgba(106,13,173,0.04) 0%, transparent 50%); pointer-events: none; z-index: 0; animation: manorFlicker 8s ease-in-out infinite; } </style> <div class="manor-overlay"></div> <div style="background: #0a0008; min-height: 100vh; padding: 20px; position: relative; z-index: 1;"> <h1 style="color: #9b59b6; text-align: center;">🏚️ Manor Interior</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2a 0%, #0d0018 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #6a0dad;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> The manor's grand foyer is a ruin of faded grandeur. A massive chandelier hangs crooked overhead, its crystal pendants catching the faintest moonlight through cracked windows. Dust covers everything — the checkered marble floor, the sweeping staircase, the rotting velvet curtains. The air is thick with the smell of mildew, old wood, and something faintly sweet and wrong. Corridors branch off into darkness in every direction. A staircase leads up toward the upper floors, and a heavy door beneath the staircase leads down. </p> </div> <h2 style="color: #9b59b6;">Explore</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Creepy Hallways --> <div style="border: 3px solid #4a0080; border-radius: 10px; padding: 15px; background: #1a0a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8e7a9e; margin: 0 0 10px 0;">🚪 Creepy Hallways</h3> <p style="font-size: 14px; color: #7a6a8a; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Long dark corridors stretch out before you, lined with dusty portraits whose eyes seem to follow your every move.</p> <<link "<div style='background: linear-gradient(135deg, #4a0080 0%, #2a0050 100%); color: #c9a0dc; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Wander the Halls</div>">> <<goto "ManorHalls">> <</link>> </div> <!-- Hidden Trapdoor (Werebunny / Gym Bunny only) --> <<if $physicalTraits.includes("Werebunny") || $physicalTraits.includes("Gym Bunny")>> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #1a0f2a; box-shadow: 0 0 12px rgba(201,169,255,0.25); display: flex; flex-direction: column;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🪜 Hidden Trapdoor</h3> <p style="font-size: 14px; color: #b0a0c8; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A section of floorboards beneath the rotting carpet doesn't sit quite right. Something in your bunny instincts is screaming at you to look closer. You crouch and find a hidden trapdoor with an iron ring, and below it, a wooden ladder descending into darkness.</p> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6a4a9a 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Descend the Ladder</div>">> <<goto "ManorSecretHallway">> <</link>> </div> <</if>> </div> <!-- Exit --> <h2 style="color: #9b59b6;">Leave</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<if $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Mirrored") || $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>> <div style="border: 3px solid #8B9DAF; border-radius: 10px; padding: 15px; background: #1a2030; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #8B9DAF; margin: 0 0 10px 0;">⛰️ Return to Mountains</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;"> <<if $physicalTraits.includes("Banshee")>>Your spectral form drifts effortlessly through the manor walls. <<elseif $physicalTraits.includes("Cheshire Cat")>>You fade away with a grin, slipping between the cracks in reality. <<elseif $physicalTraits.includes("Vampire")>>This place bows to your presence. You stride out as its master. <<elseif $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>>The manor recognizes the blood in your veins. The doors part willingly. <<else>>Something about you resonates with this place. The doors open freely for you. <</if>> </p> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Leave the Manor</div>">> <<goto "Mountains">> <</link>> </div> <<else>> <div style="border: 3px solid #444; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; opacity: 0.6;"> <h3 style="color: #666; margin: 0 0 10px 0;">🔒 The Way Out</h3> <p style="font-size: 14px; color: #555; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The front door has sealed shut behind you. Every window is barred from the outside. The walls seem to close in when you aren't looking. You cannot leave this place through normal means.</p> <div style="background: #0d0008; color: #6a0dad; padding: 10px; border-radius: 6px; text-align: center; margin-top: 10px; font-style: italic;">🔒 You are trapped. There must be another way...</div> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ManorHalls">> <<set _canStayInManor = $physicalTraits.includes("Vampire") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>> <<if !_canStayInManor && (getTimeOfDay() !== "evening" && getTimeOfDay() !== "night")>> <<goto "ManorPassout">> <</if>> <div style="background: #0a0008; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #8e7a9e; text-align: center;">🚪 The Hallways</h2> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ManorExplore.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #8e7a9e; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Manor Hallways"> </div> <</if>> <<set _hallRoll = random(1, 14)>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0a2a 0%, #0d0018 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4a0080;"> <<if _hallRoll === 1>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You wander down a long corridor lined with oil paintings. The subjects are all pale figures in dark clothing, their expressions frozen in varying degrees of displeasure. As you pass, you could swear their eyes track you. One portrait near the end of the hall depicts a figure with no face at all — just smooth, blank canvas where features should be. The brass nameplate beneath it reads your name. </p> <<elseif _hallRoll === 2>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> A dining room stretches before you, a long mahogany table set for a feast that never came. Silver cutlery sits tarnished on china plates. Candelabras stand dark and cold. Every chair is pulled out, as if the guests stood up and left in a hurry. On one plate, you notice fresh scratch marks gouged into the porcelain. They look like claw marks. </p> <<elseif _hallRoll === 3>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You push open a door into what was once a library. Bookshelves line every wall from floor to ceiling, but every single book is blank — page after page of empty white. In the center of the room, a single book lies open on a reading stand. It contains a single word, written over and over in increasingly frantic handwriting: <em style="color: #ff6b6b;">LEAVE LEAVE LEAVE LEAVE LEAVE</em> </p> <<elseif _hallRoll === 4>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> A children's nursery. A rocking horse moves gently on its own. A music box on the shelf plays three notes of a lullaby, then stops. The wallpaper is peeling in long strips, revealing older wallpaper beneath — which is also peeling, revealing bare stone covered in scratches. You notice the rocking horse has cast a shadow on the wall. Your shadow is not there. </p> <<elseif _hallRoll === 5>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> The hallway turns and narrows until you're squeezing between the walls. The floral wallpaper gives way to bare plaster, then bare stone, then something that feels organic — warm and slightly damp. You press your palm against it, and it pulses. Once. Like a heartbeat. You pull your hand back and retreat. </p> <<elseif _hallRoll === 6>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You find a ballroom with a cracked marble floor and a ceiling painted with scenes of revelry. Moonlight pours through a shattered skylight. In the center of the floor, footprints are visible in the thick dust — two sets, dancing in a waltz. They circle the room endlessly with no point of entry or exit. As you watch, you hear the faintest strain of violin music from somewhere far away. </p> <<elseif _hallRoll === 7>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You open a door and find yourself in the same hallway you just left. The same crack in the ceiling. The same crooked sconce on the wall. You turn around, but the door behind you now opens onto a different corridor entirely. You walk for what feels like an hour before you recognize anything again. </p> <<elseif _hallRoll === 8>> <<if !$manorMirrorShattered>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> A bathroom. The mirror above the sink is intact, which feels wrong in a place where everything else is broken. You approach it and see your reflection — but it's not moving. It stands perfectly still, watching you with an expression you aren't making. You raise your hand. It doesn't. You back away slowly, and your reflection smiles. </p> <<else>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You find the bathroom again. The sink is dry and cracked. Where the mirror once hung, only an empty frame remains — shards of silvered glass still scattered across the tile floor. You catch your own distorted face in one of the fragments and for a moment it looks like someone else entirely. The air in here is colder than the rest of the manor. You leave quickly. </p> <</if>> <<elseif _hallRoll === 9>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> A grandfather clock stands at the end of the corridor, impossibly tall, its pendulum swinging in perfect silence. The clock face has no numbers — only teeth, arranged in a circle. Both hands point straight down. As you watch, the pendulum slows, stops, and then swings the other direction. You feel a wave of nausea and the distinct sensation of time moving backwards around you. </p> <<elseif _hallRoll === 10>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You find a sitting room where every piece of furniture is nailed to the ceiling. Chairs, tables, a sofa, a rug — all affixed upside-down above you as if gravity simply decided to reverse for this room alone. A teacup rests on the inverted table, still full, not a single drop falling. The chandelier, however, lies shattered on the floor. </p> <<elseif _hallRoll === 11>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> Scratching. From behind the walls, from above the ceiling, from beneath the floorboards — scratching. Rhythmic and deliberate, like fingernails dragging across wood. You press your ear to the wall and the sound stops instantly. Then something presses back from the other side. The wall is warm where it touched. </p> <<elseif _hallRoll === 12>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> A long gallery filled with taxidermied animals. Deer, foxes, birds of every kind — hundreds of glass eyes catching the dim light. None of them are posed naturally. Every single animal is facing the door you entered through. As you walk deeper into the room, you hear the faint creak of heads turning behind you. You don't look back. </p> <<elseif _hallRoll === 13>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You enter a room that is completely empty except for a telephone on the floor. It's ancient — rotary dial, cloth-wrapped cord, no possible connection to anything. It rings. A single, sharp ring that echoes off the bare walls. Then silence. Then it rings again. You stand very still and wait. After the seventh ring, it stops. A voice from the earpiece, muffled but clear, says your name. Just once. </p> <<else>> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.6;"> You step into a conservatory choked with dead plants. Withered vines crawl across every surface, brittle and grey. In the center, a single flower blooms — vivid red, impossibly alive, its petals slick with moisture. It turns to face you as you enter, slowly, like a sunflower tracking the sun. There is no breeze. You reach out to touch it and every dead vine in the room twitches. You leave the flower alone. </p> <</if>> </div> /* Random discoveries - 5% chance each, independent rolls */ <<set _basementRoll = random(1, 100)>> <<set _atticRoll = random(1, 100)>> <<set _obeliskRoll = random(1, 100)>> <<if _obeliskRoll <= 5 && Math.floor($dayNumber / 7) !== $lastObeliskWeek_manor>> <<set $lastObeliskWeek_manor = Math.floor($dayNumber / 7)>> <div style="border: 3px solid #c0c0c0; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #1a1a2a 0%, #0d0d18 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(192,192,192,0.2); margin-bottom: 15px;"> <h3 style="color: #e0e0e0; margin: 0 0 10px 0;">△ A Strange Obelisk</h3> <p style="font-size: 14px; color: #c9a0dc; line-height: 1.6; margin: 0 0 10px 0;"> Through a shattered window at the end of a corridor, you spot something in the manor's overgrown garden. Among the dead rosebushes and thorny brambles, a sleek white obelisk stands where no gardener has tended in decades. Moonlight catches its surface, revealing geometric patterns and four gear symbols. Beneath them, a sequence of numbers: <strong style="color: #ffd700; font-size: 20px; font-family: monospace; letter-spacing: 4px;"><<print $obeliskCodes[5][0]>> <<print $obeliskCodes[5][1]>> <<print $obeliskCodes[5][2]>> <<print $obeliskCodes[5][3]>></strong> </p> <div style="background: #0d0018; padding: 12px; border-radius: 8px; border: 1px solid #888; text-align: center;"> <p style="color: #aaa; font-size: 14px; font-style: italic; margin: 0;">The moonlight shifts and the obelisk dims. You memorize the number before it vanishes into shadow.</p> </div> </div> <</if>> <<if _basementRoll <= 5>> <div style="border: 3px solid #8B0000; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #1a0808 0%, #0d0004 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(139,0,0,0.15); margin-bottom: 15px;"> <h3 style="color: #8B0000; margin: 0 0 10px 0;">💀 You stumble upon... The Basement</h3> <p style="font-size: 14px; color: #7a5a5a; margin: 0 0 10px 0; line-height: 1.4;">A heavy iron door beneath a crumbling staircase. Cold air seeps from the gap below. Stone steps descend into absolute darkness.</p> <<link "<div style='background: linear-gradient(135deg, #8B0000 0%, #4a0000 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Descend to the Basement</div>">> <<goto "ManorBasement">> <</link>> </div> <</if>> <<if _atticRoll <= 5 && !$manorMirrorShattered>> <div style="border: 3px solid #4169E1; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a0820 0%, #060410 100%); box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 10px rgba(65,105,225,0.15); margin-bottom: 15px;"> <h3 style="color: #4169E1; margin: 0 0 10px 0;">🪞 You discover... The Attic</h3> <p style="font-size: 14px; color: #6a7aaa; margin: 0 0 10px 0; line-height: 1.4;">A narrow staircase spirals upward from a hidden landing. Cobwebs hang like curtains across the way.</p> <<link "<div style='background: linear-gradient(135deg, #4169E1 0%, #1a3a80 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Climb to the Attic</div>">> <<goto "ManorAttic">> <</link>> </div> <</if>> <div style="display: flex; justify-content: center; gap: 15px; flex-wrap: wrap; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #4a0080 0%, #2a0050 100%); color: #c9a0dc; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Keep Wandering</div>">> <<goto "ManorHalls">> <</link>> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to the Foyer</div>">> <<goto "ManorInterior">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ManorBasement">> <<set _canStayInManor = $physicalTraits.includes("Vampire") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>> <<if !_canStayInManor && (getTimeOfDay() !== "evening" && getTimeOfDay() !== "night")>> <<goto "ManorPassout">> <</if>> <div style="background: #080004; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #8B0000; text-align: center;">💀 The Basement</h2> <!-- Location Image --> <<if $imageSettings.imagesEnabled && $imageSettings.locationImagesEnabled>> <div style="text-align: center; margin: 20px 0;"> <img src="Images/Locations/ManorBasement.webp" style="max-width: 100%; width: 800px; border-radius: 15px; border: 3px solid #8B0000; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" alt="Manor Basement"> </div> <</if>> <div style="padding: 25px; background: linear-gradient(135deg, #1a0808 0%, #0d0004 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B0000;"> <p style="color: #a07070; font-size: 16px; line-height: 1.6;"> The stone steps are slick with moisture. Each one takes you deeper below the manor, the air growing colder and heavier with every step. At the bottom, a vaulted chamber opens before you, lit by a sourceless reddish glow. Chains hang from the ceiling. Old wooden shelves hold jars of dark liquid. And in the center of the room, resting on a stone platform, sits an enormous coffin — ornate, carved from black wood, with silver filigree depicting thorny vines and crescent moons. </p> </div> <div style="text-align: center; margin-bottom: 25px;"> <<link "<div style='background: linear-gradient(135deg, #8B0000 0%, #4a0000 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 15px rgba(139,0,0,0.4);'>⚰️ Open the Coffin</div>">> <<replace "#basementResult">> <div style="padding: 25px; background: linear-gradient(135deg, #2a0808 0%, #100004 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #cc0000;"> <p style="color: #cc4444; font-size: 16px; line-height: 1.6;"> You grasp the coffin lid and heave. It resists for a moment, then slides open with a grinding screech that echoes through the basement. Inside, the coffin is lined with crimson velvet, stained dark in places. It is empty — no body, no bones. But resting on the velvet is a crystal vial filled with something thick, dark, and red. The moment the lid opens, the smell hits you: iron, copper, blood. An overwhelming thirst seizes you — a craving you've never felt before. Your mouth goes dry. Your vision sharpens. Your hands are shaking. </p> <p style="color: #cc4444; font-size: 16px; line-height: 1.6;"> You don't remember picking up the vial. You don't remember drinking. But the vial is empty in your hand, and the taste of blood fills your mouth. The world spins. Your legs give out. The last thing you see before darkness takes you is the coffin lid sliding shut on its own. </p> <<if !$physicalTraits.includes("Thirsty")>><<run $physicalTraits.push("Thirsty")>><</if>> <<if !$physicalTraits.includes("Blood")>><<run $physicalTraits.push("Blood")>><</if>> <div style="background: #0d0004; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #8B0000; text-align: center;"> <p style="color: #cc0000; font-size: 16px; font-weight: bold; margin: 0;">You gained the Thirsty and Blood traits!</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #333 0%, #111 100%); color: #999; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>...Darkness takes you</div>">> <<goto "The Nest">> <</link>> </div> </div> <<replace "#basementBack">><</replace>> <</replace>> <</link>> </div> <div id="basementResult"></div> <div id="basementBack" style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Go Back Upstairs</div>">> <<goto "ManorInterior">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ManorAttic">> <<set _canStayInManor = $physicalTraits.includes("Vampire") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Blood") || $physicalTraits.includes("Thirsty")>> <<if !_canStayInManor && (getTimeOfDay() !== "evening" && getTimeOfDay() !== "night")>> <<goto "ManorPassout">> <</if>> <div style="background: #060410; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #4169E1; text-align: center;">🪞 The Attic</h2> <div style="padding: 25px; background: linear-gradient(135deg, #0a0820 0%, #060410 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4169E1;"> <p style="color: #8090c0; font-size: 16px; line-height: 1.6;"> The attic is vast and low-ceilinged, draped in cobwebs thick as cloth. Old furniture hides under white sheets like sleeping ghosts. Trunks overflow with moth-eaten clothes and yellowed papers. Rain drips from a hole in the roof into a puddle that never seems to grow. And there, against the far wall, stands a mirror — full-length, framed in tarnished silver, its glass impossibly clean despite the dust and decay around it. </p> </div> <<if $manorMirrorShattered>> <div style="padding: 20px; background: #0a0820; border-radius: 10px; margin-bottom: 25px; border: 2px solid #333; text-align: center;"> <p style="color: #555; font-size: 16px; line-height: 1.6; font-style: italic;"> The silver frame still hangs on the wall, but the mirror is gone — shattered into a thousand pieces that litter the floor like crystallized moonlight. Whatever was behind the glass is no longer there. Or perhaps it's already here, with you. </p> </div> <<else>> <div style="padding: 20px; background: #0a0820; border-radius: 10px; margin-bottom: 25px; border: 2px solid #4169E1; text-align: center;"> <p style="color: #8090c0; font-size: 16px; line-height: 1.6;"> Your reflection stares back at you from the mirror. But something is wrong. It blinks when you don't. Its smile is too wide. Its hand presses against the glass from the other side, as if trying to reach through. The surface ripples like water. </p> <<link "<div style='background: linear-gradient(135deg, #4169E1 0%, #1a3a80 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer; box-shadow: 0 0 15px rgba(65,105,225,0.4);'>🪞 Touch the Mirror</div>">> <<replace "#atticResult">> <div style="padding: 25px; background: linear-gradient(135deg, #0a0820 0%, #000 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #6a8aff;"> <p style="color: #6a8aff; font-size: 16px; line-height: 1.6;"> Your fingertips touch the glass. It ripples outward from the point of contact, warm and liquid. Then a hand shoots through the surface — cold, impossibly strong — and grabs your wrist. You're pulled forward. The world inverts. For an instant you're falling through silver light, tumbling through a space that is neither here nor there. You see yourself — the other you — grinning as it steps out of the mirror and into your world. </p> <p style="color: #6a8aff; font-size: 16px; line-height: 1.6;"> Then the mirror shatters. Glass explodes outward. You're thrown back onto the attic floor, gasping. When you look up, the frame is empty, shards glittering all around you. But something has changed. You feel... doubled. As if part of you is still on the other side. As if something else came back with you. </p> <<if !$physicalTraits.includes("Mirrored")>><<run $physicalTraits.push("Mirrored")>><</if>> <<set $manorMirrorShattered = true>> <div style="background: #060410; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #4169E1; text-align: center;"> <p style="color: #4169E1; font-size: 16px; font-weight: bold; margin: 0;">You gained the Mirrored trait!</p> <p style="color: #aaa; font-size: 13px; margin: 5px 0 0 0;">The manor doors now open freely for you.</p> </div> </div> <</replace>> <</link>> </div> <</if>> <div id="atticResult"></div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #6a0dad 0%, #4a0080 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Go Back Downstairs</div>">> <<goto "ManorInterior">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #000; min-height: 100vh; padding: 40px 20px; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="max-width: 600px; text-align: center;"> <p style="color: #4a0080; font-size: 18px; line-height: 1.8; opacity: 0; animation: fadeIn 2s ease-in forwards;"> Dawn breaks. Pale light creeps through the cracks in the manor walls. The moment the first ray of sunlight touches the floor, the air changes — grows thick, suffocating, wrong. The shadows don't retreat from the light; they coil around you. Your vision blurs. Your legs buckle. The manor does not allow the living to see it by day. </p> <p style="color: #333; font-size: 16px; line-height: 1.8; opacity: 0; animation: fadeIn 2s ease-in 2s forwards;"> When you come to, you're lying in the dirt outside The Nest, shivering and disoriented. You don't remember leaving the manor. You don't remember anything after the light. </p> <div style="opacity: 0; animation: fadeIn 2s ease-in 4s forwards; margin-top: 25px;"> <<link "<div style='background: linear-gradient(135deg, #333 0%, #111 100%); color: #999; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Wake Up at The Nest</div>">> <<goto "The Nest">> <</link>> </div> </div> <style> @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } </style> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ManorSecretHallway">> <!-- Lazy-init the 4-digit secret code on first descent. Persists for the rest of the save. --> <<if !$manorSecretCode>> <<set $manorSecretCode = String(random(0, 9999)).padStart(4, "0")>> <</if>> <style> @keyframes manorHallFlicker { 0%, 92%, 100% { opacity: 0; } 93%, 97% { opacity: 0.15; } } .manor-hall-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 30% 20%, rgba(106,13,173,0.04) 0%, transparent 50%); pointer-events: none; z-index: 0; animation: manorHallFlicker 8s ease-in-out infinite; } @keyframes codePulseGlow { 0%, 100% { text-shadow: 0 0 10px rgba(201,169,255,0.6), 0 0 20px rgba(201,169,255,0.3); } 50% { text-shadow: 0 0 18px rgba(201,169,255,0.9), 0 0 32px rgba(201,169,255,0.5); } } .manor-code-pulse { animation: codePulseGlow 3s ease-in-out infinite; } </style> <div class="manor-hall-overlay"></div> <div style="background: #0a0008; min-height: 100vh; padding: 30px 20px; position: relative; z-index: 1;"> <h1 style="color: #c9a9ff; text-align: center; text-shadow: 0 0 10px rgba(201,169,255,0.4);">🪜 Hidden Hallway</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0d0518 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #6a4a9a; box-shadow: 0 0 25px rgba(201,169,255,0.2);"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.7;"> The ladder lets you down into a narrow stone passage that smells of old earth and cold mortar. The walls are unworked granite, slick with damp, and the only light comes from a faint phosphorescence clinging to the moss in the joints. Your bunny instincts have you crouched and silent without conscious thought, ears straining for a sound that doesn't come. </p> <p style="color: #b8a8d0; font-size: 15px; line-height: 1.6; margin-top: 14px; font-style: italic;"> Someone scratched four numbers deep into the stone at eye-level, and then went over them again with what looks like a thumb dipped in something dark. </p> </div> <div style="text-align: center; margin: 30px auto; max-width: 400px;"> <div style="background: #0d0518; border: 2px solid #c9a9ff; border-radius: 12px; padding: 28px; box-shadow: 0 0 25px rgba(201,169,255,0.3);"> <div style="color: #b8a8d0; font-size: 13px; letter-spacing: 2px; margin-bottom: 12px; text-transform: uppercase;">Carved into the wall</div> <div class="manor-code-pulse" style="color: #ffffff; font-family: 'Courier New', monospace; font-size: 56px; font-weight: bold; letter-spacing: 12px;"> <<= $manorSecretCode>> </div> </div> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); color: white; padding: 12px 28px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 15px; box-shadow: 0 0 12px rgba(106,74,154,0.4);'>Climb back up</div>">> <<goto "ManorInterior">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoLavaPool">> <style> @keyframes lavaGlow2 { 0%, 100% { opacity: 0.3; box-shadow: 0 0 40px rgba(255,61,0,0.3); } 50% { opacity: 0.6; box-shadow: 0 0 80px rgba(255,61,0,0.5); } } </style> <div style="background: #1a0500; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #ff3d00; text-align: center;">🔥 The Bubbling Lava Pool</h2> <div style="padding: 25px; background: #2a0800; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff3d00; animation: lavaGlow2 3s ease-in-out infinite;"> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> A wide pool of molten rock bubbles and churns at the base of a sheer volcanic cliff. The surface glows in shifting patterns of orange and crimson, crusts of black stone forming and dissolving in the liquid fire. The heat is staggering — even standing several meters back, your skin prickles and your clothes feel like they might ignite. Thin wisps of sulfurous smoke curl above the pool. </p> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> You could try to bathe in it... if you thought you could survive. </p> </div> <div id="lavapool-choices" style="text-align: center;"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff3d00 0%, #dd2c00 100%); color: white; padding: 15px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>🔥 Bathe in the Lava</div>">> <<replace "#lavapool-choices">> <<set _isFireCreature = $physicalTraits.includes("Salamander") || $physicalTraits.includes("Pyrow") || $physicalTraits.includes("Cerberus")>> <<if _isFireCreature>> <div style="padding: 25px; background: #2a0800; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6e40;"> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> You wade into the lava. Where it would reduce any normal person to ash in an instant, it laps at your skin like warm bathwater. The molten rock feels thick and heavy, almost viscous, and it glows around your body like liquid gold. You sink deeper, letting the fire wash over you completely. </p> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> When you finally emerge, your skin is marked with faint, swirling patterns where the lava kissed you — scars that glow faintly orange at the edges before fading to a deep, burnished bronze. You feel… different. Tempered. </p> <<if !$physicalTraits.includes("Burnt")>> <<run $physicalTraits.push("Burnt")>> <</if>> <div style="background: #0d0500; padding: 12px; border-radius: 8px; border: 1px solid #ff3d00; text-align: center; margin-top: 15px;"> <p style="color: #ff6e40; font-size: 16px; font-weight: bold; margin: 0;">🔥 You gained the Burnt trait!</p> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Volcano</div>">> <<goto "Volcano">> <</link>> </div> <<else>> <div style="padding: 25px; background: #2a0800; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff0000;"> <p style="color: #ff4444; font-size: 16px; line-height: 1.6;"> The moment your foot touches the surface, pain beyond anything you’ve ever imagined tears through your body. The lava is not water. It does not welcome you. Your skin blisters and blackens instantly. You scream, but the superheated air steals the sound from your throat. </p> <p style="color: #ff4444; font-size: 16px; line-height: 1.6;"> ...You don’t know how long you were unconscious. When you finally open your eyes, you’re staring at a white ceiling. Fluorescent lights. The smell of antiseptic. A nurse is telling you that you’re lucky to be alive, that you’ve been in a coma for an entire year. Three hundred and sixty-five days, gone. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff4444 0%, #cc0000 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Discharged from Hospital</div>">> <<if $rouletteSystem && $rouletteSystem.lockoutStartDay > 0>><<set $rouletteSystem.lockoutStartDay += 365>><</if>> <<set $dayNumber += 365>> <<goto "Hospital">> <</link>> </div> <</if>> <</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 15px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Leave</div>">> <<goto "Volcano">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoFruit">> <div style="background: #1a0a00; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #ff6e40; text-align: center;">🍅 The Volcanic Fruit</h2> <div style="padding: 25px; background: #2a1a0a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6e40;"> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> Growing from a crack in the basalt where a thin stream of lava trickles past, a single plant defies all logic. Its stem is thick and dark as charcoal, and its leaves curl inward like blackened paper. But at the top, a single fruit hangs heavy on the vine — round, plump, and glowing a deep, molten orange. Thin veins of light pulse through its skin like embers, and when you lean close, you can feel warmth radiating from it. </p> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> It smells faintly of cinnamon and smoke. It looks almost edible. Almost. </p> </div> <div id="fruit-choices" style="text-align: center;"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff6e40 0%, #e64a19 100%); color: white; padding: 15px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>🍅 Eat the Fruit</div>">> <<replace "#fruit-choices">> <div style="padding: 25px; background: #2a1a0a; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6e40;"> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> You pluck the fruit from the vine. It’s heavier than it looks, and warmer than any fruit has a right to be. The skin splits easily under your teeth. </p> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> The flavor is unlike anything you’ve ever tasted — sweet and smoky, with a deep, resonant heat that spreads through your chest like swallowing a coal. Your eyes water. Your fingers tingle. The warmth doesn’t fade. It settles into your bones, into your marrow, radiating outward like an internal furnace being lit for the first time. </p> <p style="color: #ff8a65; font-size: 16px; line-height: 1.6;"> The temperature around you hasn’t changed, but it feels… comfortable now. The searing volcanic air that was burning your lungs moments ago feels like a warm breeze. A deep certainty settles in your gut: you will never be bothered by heat or cold again. </p> <<if !$physicalTraits.includes("Inferno")>> <<run $physicalTraits.push("Inferno")>> <</if>> <div style="background: #0d0500; padding: 12px; border-radius: 8px; border: 1px solid #ff6e40; text-align: center; margin-top: 15px;"> <p style="color: #ff6e40; font-size: 16px; font-weight: bold; margin: 0;">🔥 You gained the Inferno trait!</p> <p style="color: #aaa; font-size: 13px; margin: 5px 0 0 0;">You are now immune to extreme heat and cold. Dexterity and Charisma reduced.</p> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Volcano</div>">> <<goto "Volcano">> <</link>> </div> <</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 15px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Leave</div>">> <<goto "Volcano">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoPeak">> <style> @keyframes peakGlow { 0%, 100% { text-shadow: 0 0 10px rgba(255,23,68,0.5); } 50% { text-shadow: 0 0 30px rgba(255,23,68,0.8); } } </style> <div style="background: #0a0000; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #ff1744; text-align: center; animation: peakGlow 3s ease-in-out infinite;">🌋 The Volcano’s Peak</h2> <div style="padding: 25px; background: #1a0500; border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff1744;"> <p style="color: #ff8a80; font-size: 16px; line-height: 1.6;"> The summit of the volcano is a hellscape of liquid fire and choking ash. The crater yawns wide below you, a churning lake of lava that casts everything in shades of orange and blood-red. The air itself seems to glow. Every breath tastes of sulfur and iron. The ground trembles constantly, as if the mountain is breathing. </p> <p style="color: #ff8a80; font-size: 16px; line-height: 1.6;"> The view from up here is staggering — you can see the entire island spread out beneath you like a map. The jungle, the desert, the coastline, everything rendered tiny and fragile by the scale of this monstrous place. </p> </div> <!-- Obelisk Event - always visible (lazy-init the code if missing) --> <<if !$volcanoRedHerring || $volcanoRedHerring.length !== 4>> <<set $volcanoRedHerring = [random(0, 9), random(0, 9), random(0, 9), random(0, 9)]>> <</if>> <div style="background: #1a1020; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #c0c0c0; box-shadow: 0 0 20px rgba(192,192,192,0.2);"> <h3 style="color: #e0e0e0; margin: 0 0 10px 0;">△ A Strange Obelisk</h3> <p style="color: #ff8a80; font-size: 16px; line-height: 1.6;"> Near the crater’s edge, partially buried in hardened lava, stands a sleek white obelisk. It should have been consumed by the heat long ago, but its polished surface is immaculate. Geometric patterns pulse across its face like a circuit board, and near the base, four gear symbols sit in a row with a sequence of numbers seared into the stone: <strong style="color: #ffd700; font-size: 20px; font-family: monospace; letter-spacing: 4px;"><<print $volcanoRedHerring[0]>> <<print $volcanoRedHerring[1]>> <<print $volcanoRedHerring[2]>> <<print $volcanoRedHerring[3]>></strong>. </p> <div style="background: #0a0a1a; padding: 12px; border-radius: 8px; border: 1px solid #888; text-align: center;"> <p style="color: #aaa; font-size: 14px; font-style: italic; margin: 0;">The obelisk hums with a deep vibration you feel in your chest. The molten earth around it stirs but the digits hold their place.</p> </div> </div> <!-- Peak flavor --> <<set _peakEvent = random(1, 3)>> <<if _peakEvent === 1>> <div style="padding: 20px; background: #1a0500; border-radius: 12px; margin-bottom: 25px; border: 2px solid #bf360c;"> <p style="color: #ff8a80; font-size: 16px; line-height: 1.6;"> A massive geyser of lava erupts from a fissure near the crater rim, sending a fountain of liquid fire thirty meters into the air. Glowing droplets rain down around you, hissing as they cool into tiny black beads on the stone. The display is terrifyingly beautiful. </p> </div> <<elseif _peakEvent === 2>> <div style="padding: 20px; background: #1a0500; border-radius: 12px; margin-bottom: 25px; border: 2px solid #bf360c;"> <p style="color: #ff8a80; font-size: 16px; line-height: 1.6;"> The wind shifts and a wall of superheated gas rolls across the peak. For a moment everything vanishes into a haze of orange and grey. When it clears, you notice new cracks in the stone at your feet, glowing faintly with fresh lava. </p> </div> <<else>> <div style="padding: 20px; background: #1a0500; border-radius: 12px; margin-bottom: 25px; border: 2px solid #bf360c;"> <p style="color: #ff8a80; font-size: 16px; line-height: 1.6;"> At the very edge of the crater, you find a flat stone that’s been worn smooth by centuries of heat and wind. From here you can look straight down into the molten heart of the mountain. The lava pulses slowly, rhythmically, like the breathing of something impossibly large and ancient. </p> </div> <</if>> <!-- Dragon Queen: Ancient Altar (always present at the Peak) --> <div style="background:#1a0d02; padding:20px; border-radius:12px; margin-bottom:20px; border:3px solid #ffca6b; box-shadow:0 0 18px rgba(255,140,0,0.2);"> <h3 style="color:#ffca6b; margin:0 0 10px 0;">🔥 An Ancient Altar</h3> <p style="color:#ff8a80; font-size:16px; line-height:1.6;">At the crater’s edge stands a slab of black basalt, ringed with sixteen empty sockets, each one cut to hold a single gem. It hums with the same deep patience as the mountain.</p> <div style="text-align:center; margin-top:12px;"> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#ffca6b 0%,#d4820a 100%); color:#1a0d02; padding:12px 30px; border-radius:8px; font-weight:bold; cursor:pointer;'>Approach the Altar</div>">> <<goto "VolcanoDragonAltar">> <</link>> </div> </div> <<if $dragonEntranceOpen>> <!-- Dragon Queen: revealed passage --> <div style="background:#100500; padding:20px; border-radius:12px; margin-bottom:20px; border:3px solid #ff5722; box-shadow:0 0 22px rgba(255,87,34,0.3);"> <h3 style="color:#ff7043; margin:0 0 10px 0;">🕳️ The Revealed Passage</h3> <p style="color:#ff8a80; font-size:16px; line-height:1.6;">Where the altar drew the lava back, a dark passage descends into the mountain. <<if $dragonFreed>>The pale wrong light is gone from below now; what rises instead is a clean and steady warmth.<<else>>A pale light flickers somewhere far below.<</if>></p> <div style="text-align:center; margin-top:12px;"> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#ff5722 0%,#b03a17 100%); color:white; padding:12px 30px; border-radius:8px; font-weight:bold; cursor:pointer;'>Descend into the Passage</div>">> <<set _dqDest = $dragonFreed ? "MiklaLair" : "DragonQueenChamber">><<goto _dqDest>> <</link>> </div> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ff5722 0%, #e64a19 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Volcano</div>">> <<goto "Volcano">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$oasisAltarDeposits>><<set $oasisAltarDeposits = []>><</if>> <<if !$oasisAltarConsumed>><<set $oasisAltarConsumed = []>><</if>> <style> @keyframes waterGlow { 0%, 100% { box-shadow: 0 0 30px rgba(155,89,182,0.3), 0 0 60px rgba(155,89,182,0.1); } 50% { box-shadow: 0 0 50px rgba(155,89,182,0.5), 0 0 100px rgba(155,89,182,0.2); } } @keyframes figureFloat { 0%, 100% { transform: translateY(0px); } 50% { transform: translateY(-10px); } } @keyframes altarReveal { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } } @keyframes slotGlow { 0%, 100% { box-shadow: 0 0 10px rgba(255,193,7,0.3); } 50% { box-shadow: 0 0 25px rgba(255,193,7,0.6); } } </style> <div style="background: linear-gradient(180deg, #0a0a1a 0%, #1a0a2a 50%, #0a1a2a 100%); min-height: 100vh; padding: 20px; position: relative;"> <div style="animation: waterGlow 4s ease-in-out infinite; border-radius: 15px; padding: 3px;"> <div style="background: #0a0a1a; border-radius: 12px; padding: 25px;"> <h1 style="color: #9b59b6; text-align: center; text-shadow: 0 0 20px rgba(155,89,182,0.5);">🎶 The Siren’s Song</h1> <div id="siren-scene"> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> You stand at the water’s edge, moonlight painting silver ripples across the oasis. Something stirs within you—an ancient resonance between your voice and these hidden waters. </p> <p style="color: #9b59b6; font-size: 17px; margin: 0; line-height: 1.7; font-style: italic;"> You open your mouth and begin to sing. The melody is not one you’ve learned—it rises from somewhere deeper, older. The water responds instantly, glowing with soft violet light from below. </p> </div> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 15px rgba(155,89,182,0.4);'>Step Onto the Water</div>">> <<replace "#siren-scene">> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #9b59b6;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> Your foot touches the surface and it holds. The water is solid beneath you, warm and humming with energy. You walk forward, each step sending rings of violet light outward across the pool. </p> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> Below you, a luminous figure takes shape—translucent, graceful, dancing in slow spiraling motions. It mirrors your movements, or perhaps you mirror it. The figure gestures upward, inviting you to join its dance. </p> <div style="text-align: center; margin: 15px 0;"> <div style="font-size: 60px; animation: figureFloat 3s ease-in-out infinite;">💃</div> </div> <p style="color: #9b59b6; font-size: 16px; margin: 0; line-height: 1.7; font-style: italic; text-align: center;"> The figure beneath the water moves with impossible grace. To reveal what lies below, you must match its dance perfectly. </p> </div> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #9b59b6 0%, #6a0dad 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 15px rgba(155,89,182,0.4);'>Dance in Sync</div>">> <<replace "#siren-scene">> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #ffc107;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> You close your eyes and let the music guide your body. Every sway, every turn, every extension of your arms matches the figure below with impossible precision. Your song and its dance become one. </p> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> The figure looks up at you and smiles. Then it dissolves into light. The water trembles violently—and parts. A great seam opens down the center of the oasis, the waters pulling aside like curtains to reveal the dry bed below. </p> <p style="color: #ffc107; font-size: 17px; margin: 0; line-height: 1.7; font-weight: bold;"> At the center of the exposed bed sits a stone altar, ancient and covered in intricate carvings of sunfish. Seven circular slots are carved into its surface, arranged in a ring. </p> </div> <!-- ALTAR DISPLAY --> <div style="animation: altarReveal 1.5s ease-out; background: linear-gradient(135deg, #2a1a0a 0%, #1a1a0a 100%); border-radius: 15px; padding: 25px; margin-bottom: 20px; border: 3px solid #ffc107; box-shadow: 0 0 30px rgba(255,193,7,0.2);"> <h2 style="color: #ffc107; text-align: center; margin: 0 0 20px 0;">✨ The Sunfish Altar ✨</h2> <p style="color: #aaa; text-align: center; margin: 0 0 20px 0; font-style: italic;">Seven slots await seven offerings. Place each artifact to complete the circle.</p> <p style="color: #888; text-align: center; margin: 0 0 25px 0; font-size: 14px;">(<<print $oasisAltarDeposits.length>> / 7 deposited)</p> <div style="display: grid; grid-template-columns: 1fr; gap: 12px; max-width: 500px; margin: 0 auto;"> <!-- Slot 1: The Sunfish Hook --> <<if $oasisAltarDeposits.includes("The Sunfish Hook")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Sunfish Hook</span> </div> <<elseif $currentArtifact === "The Sunfish Hook">> <div style="background: #1a1a0a; border: 2px solid #9c27b0; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #9c27b0; font-weight: bold; margin-bottom: 8px;">🐟 The Sunfish Hook</div> <<link "<div style='background: #9c27b0; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Sunfish Hook")>> <<run $oasisAltarConsumed.push("The Sunfish Hook")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Sunfish Hook</span> </div> <</if>> <!-- Slot 2: The Gentle Giant's Heart --> <<if $oasisAltarDeposits.includes("The Gentle Giant's Heart")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Gentle Giant’s Heart</span> </div> <<elseif ($currentArtifact === "The Gentle Giant's Heart" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: #1a1a0a; border: 2px solid #e91e63; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #e91e63; font-weight: bold; margin-bottom: 8px;">💖 The Gentle Giant’s Heart</div> <<link "<div style='background: #e91e63; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Gentle Giant's Heart")>> <<run $oasisAltarConsumed.push("The Gentle Giant's Heart")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Gentle Giant’s Heart</span> </div> <</if>> <!-- Slot 3: The Basking Charm --> <<if $oasisAltarDeposits.includes("The Basking Charm")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Basking Charm</span> </div> <<elseif ($currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: #1a1a0a; border: 2px solid #ff9800; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #ff9800; font-weight: bold; margin-bottom: 8px;">☀️ The Basking Charm</div> <<link "<div style='background: #ff9800; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Basking Charm")>> <<run $oasisAltarConsumed.push("The Basking Charm")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Basking Charm</span> </div> <</if>> <!-- Slot 4: The Drifter's Coin --> <<if $oasisAltarDeposits.includes("The Drifter's Coin")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Drifter’s Coin</span> </div> <<elseif ($currentArtifact === "The Drifter's Coin" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: #1a1a0a; border: 2px solid #00bcd4; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #00bcd4; font-weight: bold; margin-bottom: 8px;">🪙 The Drifter’s Coin</div> <<link "<div style='background: #00bcd4; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Drifter's Coin")>> <<run $oasisAltarConsumed.push("The Drifter's Coin")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Drifter’s Coin</span> </div> <</if>> <!-- Slot 5: The Pearl of Abundance --> <<if $oasisAltarDeposits.includes("The Pearl of Abundance")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Pearl of Abundance</span> </div> <<elseif ($currentArtifact === "The Pearl of Abundance" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: #1a1a0a; border: 2px solid #f5f5f5; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #f5f5f5; font-weight: bold; margin-bottom: 8px;">🔮 The Pearl of Abundance</div> <<link "<div style='background: #9e9e9e; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Pearl of Abundance")>> <<run $oasisAltarConsumed.push("The Pearl of Abundance")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Pearl of Abundance</span> </div> <</if>> <!-- Slot 6: The Crowd's Eye --> <<if $oasisAltarDeposits.includes("The Crowd's Eye")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Crowd’s Eye</span> </div> <<elseif ($currentArtifact === "The Crowd's Eye" || ($physicalTraits && $physicalTraits.includes("Naiad")))>> <div style="background: #1a1a0a; border: 2px solid #673ab7; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #673ab7; font-weight: bold; margin-bottom: 8px;">👁️ The Crowd’s Eye</div> <<link "<div style='background: #673ab7; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Crowd's Eye")>> <<run $oasisAltarConsumed.push("The Crowd's Eye")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Crowd’s Eye</span> </div> <</if>> <!-- Slot 7: The Tidal Memory Stone --> <<if $oasisAltarDeposits.includes("The Tidal Memory Stone")>> <div style="background: #1a1a0a; border: 2px solid #ffc107; border-radius: 8px; padding: 12px; text-align: center; animation: slotGlow 3s ease-in-out infinite;"> <span style="color: #ffc107; font-weight: bold;">✅ The Tidal Memory Stone</span> </div> <<elseif $currentArtifact === "The Tidal Memory Stone">> <div style="background: #1a1a0a; border: 2px solid #4dabf7; border-radius: 8px; padding: 12px; text-align: center;"> <div style="color: #4dabf7; font-weight: bold; margin-bottom: 8px;">🌊 The Tidal Memory Stone</div> <<link "<div style='background: #4dabf7; color: white; padding: 8px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Deposit Artifact</div>">> <<run $oasisAltarDeposits.push("The Tidal Memory Stone")>> <<run $oasisAltarConsumed.push("The Tidal Memory Stone")>> <<set $currentArtifact = null>> <<if $oasisAltarDeposits.length === 7 && !$divineSunfishAwarded>> <<if !$physicalTraits.includes("Divine Sunfish")>> <<run $physicalTraits.push("Divine Sunfish")>> <</if>> <<set $divineSunfishAwarded = true>> <</if>> <<goto "OasisSirenDance">> <</link>> </div> <<else>> <div style="background: #1a1a0a; border: 2px solid #333; border-radius: 8px; padding: 12px; text-align: center;"> <span style="color: #555;">❌ The Tidal Memory Stone</span> </div> <</if>> </div> </div> <!-- Divine Sunfish Trait Reveal --> <<if $oasisAltarDeposits.length === 7 && $divineSunfishAwarded>> <div style="background: linear-gradient(135deg, #1a6fc4 0%, #0d4a8a 100%); border-radius: 15px; padding: 25px; margin-bottom: 20px; text-align: center; box-shadow: 0 0 40px rgba(26,111,196,0.4);"> <div style="font-size: 80px; margin-bottom: 15px;">✨🐟✨</div> <h2 style="color: white; margin: 0 0 15px 0; text-shadow: 0 2px 4px rgba(0,0,0,0.3);">The Circle is Complete</h2> <p style="color: rgba(255,255,255,0.9); font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> All seven artifacts pulse in unison. The altar erupts with golden light that shoots skyward, parting the clouds above. A warmth fills you unlike anything you have ever known—the collective power of the sunfish flows through every artifact and into your very soul. </p> <div style="background: rgba(255,255,255,0.2); padding: 15px; border-radius: 10px; display: inline-block;"> <div style="color: white; font-weight: bold; font-size: 20px;">New Trait Acquired: Divine Sunfish</div> <div style="color: rgba(255,255,255,0.8); font-size: 14px; margin-top: 5px;">Blessed by the convergence of all seven sunfish artifacts</div> </div> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Return to the Shore</div>">> <<goto "Oasis">> <</link>> </div> <</replace>> <</link>> </div> <</replace>> <</link>> </div> </div> </div> </div> <</nobr>>
<<nobr>> <<set _hasColdTolerance = ($physicalTraits.includes("Muscular") || $physicalTraits.includes("Sturdy") || $physicalTraits.includes("Fit") || $physicalTraits.includes("Strong") || $mentalTraits.includes("High Stamina") || $mentalTraits.includes("Determined") || $mentalTraits.includes("Disciplined") || $mentalTraits.includes("Brave") || $mentalTraits.includes("Steadfast") || $mentalTraits.includes("Wild") || $mentalTraits.includes("Feral") || $mentalTraits.includes("Blessed") || $mentalTraits.includes("Nocturnal") || $physicalTraits.includes("Werewolf") || $mentalTraits.includes("Werewolf") || $physicalTraits.includes("Weresheep") || $mentalTraits.includes("Weresheep") || $physicalTraits.includes("Werecat") || $mentalTraits.includes("Werecat") || $physicalTraits.includes("Werefox") || $mentalTraits.includes("Werefox") || $physicalTraits.includes("Werebunny") || $mentalTraits.includes("Werebunny") || $physicalTraits.includes("Cerberus") || $mentalTraits.includes("Cerberus") || $physicalTraits.includes("Automaton") || $physicalTraits.includes("Banshee") || $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko") || $physicalTraits.includes("Ocelomeh") || $physicalTraits.includes("Raiju") || $physicalTraits.includes("Vampire") || $physicalTraits.includes("Kitsune") || $physicalTraits.includes("Pharaoh") || $physicalTraits.includes("Salamander") || $physicalTraits.includes("Inferno") || $mentalTraits.includes("Inferno") || $physicalTraits.includes("Pyrow") || $mentalTraits.includes("Pyrow"))>> <<if !_hasColdTolerance>> <div style="background: linear-gradient(180deg, #0a0a1a 0%, #1a1a2a 100%); min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #8B9DAF; text-align: center;">⛰️ The Mountain Peak</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a2a3a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ba3c9;"> <p style="color: #7ba3c9; font-size: 16px; line-height: 1.6;"> The air thins rapidly as you climb higher. Each step is a battle against the howling wind and the numbing cold that seeps into your very bones. Ice crystals sting your face, and the trail ahead disappears into a wall of white. Your muscles seize, your lungs burn, and your body screams at you to turn back. The peak looms somewhere above, hidden in the clouds, but you simply cannot push further without some kind of physical toughness or cold tolerance. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #8B9DAF 0%, #5C6B7A 100%); color: white; padding: 15px 40px; border-radius: 10px; display: inline-block; font-weight: bold; font-size: 16px; cursor: pointer;'>Return to Mountains</div>">> <<goto "Mountains">> <</link>> </div> </div> <<else>> <style> @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .fade-in { animation: fadeIn 1.5s ease-in forwards; } @keyframes lightningFlash { 0% { opacity: 0; } 5% { opacity: 1; } 10% { opacity: 0; } 12% { opacity: 0.8; } 15% { opacity: 0; } 100% { opacity: 0; } } @keyframes electricPulse { 0%, 100% { text-shadow: 0 0 10px rgba(241,196,15,0.3); } 50% { text-shadow: 0 0 30px rgba(241,196,15,0.8), 0 0 60px rgba(241,196,15,0.4); } } </style> <div style="background: linear-gradient(180deg, #0a0a1a 0%, #1a1a2a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #8B9DAF; text-align: center;">⛰️ The Mountain Peak</h1> <!-- Check weather conditions --> <<set _isStormy = $currentWeather === "Stormy">> <<set _lightningStrike = _isStormy>> <<if _lightningStrike>> <!-- STORMY: Lightning strike event --> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a2a 0%, #0a0a1a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #f1c40f; box-shadow: 0 0 20px rgba(241,196,15,0.2);"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> You reach the summit as thunder cracks the sky. The wind is ferocious up here, whipping at your clothes and stinging your eyes. Dark clouds churn directly overhead, lit from within by flashes of violet and white. </p> <p style="color: #f1c40f; font-size: 17px; margin: 0; line-height: 1.7; font-weight: bold;"> You are the highest point for miles. The air tastes of metal and ozone. Every hair on your body stands on end. </p> </div> <div id="peak-scene"> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #f1c40f 0%, #e67e22 100%); color: #1a1a1a; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 15px rgba(241,196,15,0.4);'>Stand Upon the Peak</div>">> <<replace "#peak-scene">> <<if $physicalTraits.includes("Automaton")>> <!-- Automaton: Lightning charges the mechanical body --> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2a1a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #00bfff; box-shadow: 0 0 30px rgba(0,191,255,0.3);"> <p style="color: #00bfff; font-size: 20px; margin: 0 0 15px 0; line-height: 1.7; font-weight: bold; text-align: center;"> ⚡ SYSTEM OVERCHARGED ⚡ </p> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> A column of white light descends from the clouds and strikes your metallic body. Instead of pain, you feel every circuit surge with incredible power. Your mechanical systems absorb the electrical energy, converting it into raw processing power. </p> <p style="color: #00bfff; font-size: 17px; margin: 0; line-height: 1.7; font-weight: bold;"> Your systems are now OVERCHARGED! +300 to all stats for 24 hours. Your fishing efficiency triples. </p> </div> <<run setup.addBuff("automaton_overcharged", 1440)>> <<advancetime 30>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #00bfff 0%, #0080ff 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Climb Back Down (4 hours)</div>">> <<advancetime 240>> <<goto "Mountains">> <</link>> </div> <<elseif $physicalTraits.includes("Electrified")>> <!-- Already has Electrified: struck again but nothing happens --> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2a1a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #f1c40f;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> You plant your feet on the summit stone. The sky splits open with a deafening crack and a bolt of lightning slams into you. The force staggers you backward, but— </p> <p style="color: #f1c40f; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7; font-weight: bold;"> Nothing. The electricity courses through your already-charged body like water through a river. Your skin crackles and sparks, but the energy simply passes through you. You’ve already been claimed by the storm. </p> <p style="color: #aaa; font-size: 16px; margin: 0; line-height: 1.7; font-style: italic;"> The thunder rumbles its disappointment. You’ll have to climb back down on your own. </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #8B9DAF 0%, #6a7a8a 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Climb Back Down (4 hours)</div>">> <<advancetime 240>> <<goto "Mountains">> <</link>> </div> <<else>> <!-- Does NOT have Electrified: gain the trait --> <div style="position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: white; z-index: 9990; animation: lightningFlash 0.5s ease-out forwards; pointer-events: none;"></div> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a0a 0%, #2a2a1a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #f1c40f; box-shadow: 0 0 30px rgba(241,196,15,0.3);"> <p style="color: #f1c40f; font-size: 20px; margin: 0 0 15px 0; line-height: 1.7; font-weight: bold; text-align: center; animation: electricPulse 2s ease-in-out infinite;"> ⚡ CRACK ⚡ </p> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> A column of white light descends from the clouds and strikes you directly. Every nerve in your body ignites at once. The world goes brilliant white, then nothing. </p> </div> <!-- Passout sequence --> <<if !$physicalTraits.includes("Electrified")>> <<run $physicalTraits.push("Electrified")>> <</if>> <<if typeof setup.applyDebuff === "function">> <<run setup.applyDebuff("exhaustion")>> <</if>> <<run setup.setHairMessy()>> <<timed 2s>> <div class="fade-in" style="padding: 15px; background: rgba(241,196,15,0.05); border-radius: 10px; margin-bottom: 15px; border-left: 3px solid #f1c40f;"> <p style="color: #aaa; font-size: 16px; margin: 0; line-height: 1.7;"> Darkness. The smell of ozone and burnt earth. Your muscles twitch and spasm involuntarily. You can feel electricity still crackling across your skin, arcing between your fingers. </p> </div> <</timed>> <<timed 5s>> <div class="fade-in" style="padding: 15px; background: rgba(241,196,15,0.05); border-radius: 10px; margin-bottom: 15px; border-left: 3px solid #f1c40f;"> <p style="color: #aaa; font-size: 16px; margin: 0; line-height: 1.7;"> Time passes. The storm moves on. Rain patters against your unconscious body as the hours drift by. Something inside you has changed—you can feel the current humming in your bones even in the void of sleep. </p> </div> <</timed>> <<timed 8s>> <div class="fade-in" style="padding: 15px; background: rgba(241,196,15,0.1); border-radius: 10px; margin-bottom: 15px; border-left: 3px solid #f1c40f;"> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0; line-height: 1.7;"> You open your eyes to morning light. You’re in the nest, the giant chicken watching you with mild curiosity. Someone or something must have carried you down from the peak. Your entire body tingles with residual energy. </p> <div style="background: rgba(241,196,15,0.15); border: 2px solid #f1c40f; padding: 15px; border-radius: 10px; margin-bottom: 15px;"> <div style="color: #f1c40f; font-weight: bold;">⚡ New Trait Acquired: Electrified</div> <div style="color: #aaa; font-size: 14px;">+30 Dexterity | Struck by lightning atop a mountain peak</div> </div> <p style="color: #e74c3c; font-size: 14px; margin: 0;">😴 You feel exhausted.</p> </div> <</timed>> <<timed 12s>> <<set $timeOfDay = "Morning">> <<goto "The Nest">> <</timed>> <</if>> <</replace>> <</link>> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #4080a0; color: white; padding: 12px 30px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Descend the Far Side (3 hours)</div>">> <<advancetime 180>> <<goto "TundraOfAeternus">> <</link>> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #555; color: white; padding: 12px 30px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Climb Back Down (4 hours)</div>">> <<advancetime 240>> <<goto "Mountains">> <</link>> </div> </div> <<else>> <!-- NOT stormy: normal summit visit --> <<set _peakRoll = random(1, 100)>> <<if _peakRoll <= 25>> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #8B9DAF;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> You reach the summit, chest heaving from the climb. The view is breathtaking—you can see the desert stretching to the south, the jungle canopy to the east, and the ocean glittering on the horizon. </p> <p style="color: #8B9DAF; font-size: 16px; margin: 0; line-height: 1.7; font-style: italic;"> The wind up here is cold and clean. For a moment, the world below seems very small and very far away. </p> </div> <<elseif _peakRoll <= 50>> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #8B9DAF;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> The summit is barren rock, scoured smooth by centuries of wind. A few stubborn tufts of alpine grass cling to crevices. You find scratches carved into the stone—old marks, worn nearly flat by time. Someone else stood here once. </p> <p style="color: #8B9DAF; font-size: 16px; margin: 0; line-height: 1.7; font-style: italic;"> Nothing else of interest. Just the mountain, the sky, and the silence between them. </p> </div> <<elseif _peakRoll <= 75>> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #8B9DAF;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> You pull yourself over the final ledge and collapse onto the flat summit. A hawk circles overhead, riding the thermals. It tilts its head to regard you with one golden eye before banking away into the open sky. </p> <p style="color: #8B9DAF; font-size: 16px; margin: 0; line-height: 1.7; font-style: italic;"> The climb was worth it for the solitude alone. Nothing happens, but the peace is its own reward. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #1a1a2a 0%, #0a1a2a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #8B9DAF;"> <p style="color: #ccc; font-size: 17px; margin: 0 0 15px 0; line-height: 1.7;"> The peak is shrouded in cloud today. Mist swirls around your ankles and you can barely see your own hands. The world below has vanished entirely, leaving only you and the mountain. </p> <p style="color: #8B9DAF; font-size: 16px; margin: 0; line-height: 1.7; font-style: italic;"> You stand in the clouds for a while, listening to nothing. Eventually, the cold drives you back down. </p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Descend the Far Side (3 hours)</div>">> <<advancetime 180>> <<goto "TundraOfAeternus">> <</link>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #8B9DAF 0%, #6a7a8a 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Climb Back Down (4 hours)</div>">> <<advancetime 240>> <<goto "Mountains">> <</link>> </div> <</if>> </div> <</if>> <</nobr>>
<<nobr>> <<if $discoveredTundra === false>> <<set $discoveredTundra = true>> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;"> You crest the summit and, for the first time, do not turn back. The far slope falls away beneath you, gentler than the climb, and the wind at your back seems almost to carry you down. Below the cloud line a vast white country opens up, snow without end, ringed by pale peaks that march off into the distance. The cold here is older than the cold above. It has settled into the bones of the land and never left. </p> </div> <div style="background: rgba(126,200,227,0.12); border: 2px solid #7ec8e3; padding: 15px; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered the Tundra of Aeternus!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">You can now travel here from the Mountains.</p> </div> <</if>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ Tundra of Aeternus</h1> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;"> Snow stretches to every horizon, soft and unbroken, glittering where the thin light touches it. The silence is total. No birds, no wind for the moment, only the slow drift of flakes from a colorless sky. Your breath hangs in front of you and freezes. The cold is enormous and patient, and it has all the time in the world. </p> </div> <<if setup.flona.isPresentAt("TundraOfAeternus")>> <<if $flonaMet === false>> <div style="padding: 20px; background: rgba(126,200,227,0.10); border: 2px solid #7ec8e3; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #cfe8f5; font-size: 15px; margin: 0 0 12px 0; line-height: 1.6;"> Far out on the snow a figure stands watching you. Silver and still, a long tail drifting behind her in the wind. She does not run. </p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 12px 30px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Approach the figure</div>">> <<goto "FlonaFirstMeet">> <</link>> </div> <<else>> <div style="padding: 20px; background: rgba(126,200,227,0.10); border: 2px solid #7ec8e3; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #cfe8f5; font-size: 15px; margin: 0 0 12px 0; line-height: 1.6;"> Flona waits near her den in the snow, tail curled around her feet, watching you with warm violet eyes. </p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 12px 30px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Speak with Flona</div>">> <<goto "FlonaTalk">> <</link>> </div> <</if>> <<elseif setup.flona.playerIsTrueSelf() && $discoveredFlonaTent>> <div style="padding: 20px; background: rgba(126,200,227,0.08); border: 2px solid #4a6b7a; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #9bbccc; font-size: 15px; font-style: italic; margin: 0; line-height: 1.6;"> Her tracks lead off across the snow, toward a tent half hidden in the drifts. She is not here. She is home. </p> </div> <<else>> <div style="padding: 20px; background: rgba(126,200,227,0.06); border: 2px dashed #4a6b7a; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #7a98a8; font-size: 15px; font-style: italic; margin: 0; line-height: 1.6;"> Nothing stirs across the expanse. For now the tundra keeps to itself, vast and silent under the snow. </p> </div> <</if>> <h2 style="color: #aee0f5; text-align: center; margin-top: 10px;">Across the Tundra</h2> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">Explore the Tundra</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">Set out across the white country and see what the snow is keeping from you.</p> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Explore the Tundra</div>">> <<advancetime 120>> <<goto "TundraExplore">> <</link>> </div> <<if $discoveredFrozenLake>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">Frozen Lake</h3> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Walk to the Frozen Lake</div>">> <<advancetime 30>> <<goto "TundraFrozenLake">> <</link>> </div> <</if>> <<if $discoveredStandingStones>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">Marble Standing Stones</h3> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Walk to the Standing Stones</div>">> <<advancetime 30>> <<goto "TundraStandingStones">> <</link>> </div> <</if>> <<if $discoveredFlonaTent>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">Flona's Tent</h3> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Walk to Flona's Tent</div>">> <<advancetime 30>> <<goto "FlonaTent">> <</link>> </div> <</if>> <<if $discoveredTundraCave>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">Cave Entrance</h3> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Walk to the Cave Entrance</div>">> <<advancetime 30>> <<goto "TundraCave">> <</link>> </div> <</if>> <<if $discoveredTaiga>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">The Taiga</h3> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Walk to the Taiga</div>">> <<advancetime 30>> <<goto "TundraTaiga">> <</link>> </div> <</if>> <<if $discoveredMist>> <div style="border: 3px solid #7ec8e3; border-radius: 10px; padding: 15px; background: linear-gradient(135deg, #0a1420 0%, #050f1a 100%); margin-bottom: 12px;"> <h3 style="color: #aee0f5; margin: 0 0 10px 0;">The Misty Veil</h3> <<link "<div style='background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Walk to the Misty Veil</div>">> <<advancetime 30>> <<goto "TundraMist">> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Climb Back Over the Peak (3 hours)</div>">> <<advancetime 180>> <<goto "Mountains">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if setup.flona.playerIsTrueSelf()>> <<set $flonaMet = true>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <div style="text-align: center; margin-bottom: 20px;"> <img src="Images/NPCs/StaticNPCs/Flona_Vulri.webp" alt="Flona Vulri" style="max-width: 280px; max-height: 460px; border-radius: 12px; border: 2px solid #7ec8e3; box-shadow: 0 0 24px rgba(126,200,227,0.35);" onerror="this.style.display='none';"> </div> <div style="padding: 22px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 18px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> The figure does not flee as you cross the snow toward her. She is tall, silver from ear to tail, wrapped in blue and white and old gold, and she watches you come with the patience of someone who has watched a great many things arrive and leave. </p> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> <span style="color: #e8c98a;">"A long way to come,"</span> she says, and her voice is low and warm, the kind of voice that has hushed crying things to sleep. <span style="color: #e8c98a;">"Over the peak, down the cold side, all the way out here. Not many make the crossing. The mountain turns most of them back long before they ever reach my snow."</span> </p> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> Her violet eyes move over you, and something in them softens. </p> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0;"> <span style="color: #e8c98a;">"There is something steady in you,"</span> she says at last, quiet, as though she is looking straight past the cold to the soul beneath it. <span style="color: #e8c98a;">"I do not feel that often, out here."</span> She inclines her head. <span style="color: #e8c98a;">"I am Flona. The snow and I keep to ourselves, but you are welcome at my fire. Stay a while, if the wind allows it."</span> </p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Thank her, and stay a while</div>">> <<goto setup.flona.homeLocation()>> <</link>> </div> </div> <<else>> <<goto "TundraOfAeternus">> <</if>> <</nobr>>
<<nobr>> <<if setup.flona.playerIsTrueSelf()>> <<set _flonaLine = random(1, 4)>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <div style="text-align: center; margin-bottom: 18px;"> <img src="Images/NPCs/StaticNPCs/Flona_Vulri_Portrait.webp" alt="Flona Vulri" style="max-width: 200px; border-radius: 12px; border: 2px solid #7ec8e3; box-shadow: 0 0 20px rgba(126,200,227,0.3);" onerror="this.onerror=null; this.src='Images/NPCs/StaticNPCs/Flona_Vulri.webp';"> </div> <div style="padding: 22px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 18px; border: 2px solid #7ec8e3;"> <<if _flonaLine === 1>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0;"> <span style="color: #e8c98a;">"Sit. Warm your hands."</span> Flona shifts to make room beside her in the snow as if it were the most comfortable place in the world. <span style="color: #e8c98a;">"The cold out here is honest. It does not pretend to be anything kinder than it is. I have always liked that about it."</span> </p> <<elseif _flonaLine === 2>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0;"> <span style="color: #e8c98a;">"You look tired, little traveler."</span> Her tail sweeps a clean half circle in the snow. <span style="color: #e8c98a;">"The world below takes and takes from people like you. Up here it cannot reach you. Rest as long as you need. I am not going anywhere."</span> </p> <<elseif _flonaLine === 3>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0;"> <span style="color: #e8c98a;">"The snow keeps its own counsel,"</span> she says softly, watching the flakes come down. <span style="color: #e8c98a;">"I have been here longer than I can rightly say. Long enough that the cold feels like an old friend, and the silence like a warm one. It is good to share it with someone, now and then."</span> </p> <<else>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0;"> <span style="color: #e8c98a;">"There is tea, if the wind ever lets the fire stand."</span> Flona smiles, and the whole cold expanse seems a degree warmer for it. <span style="color: #e8c98a;">"Come back and sit with me when the cold below gets to be too much. There will always be a place at it for you."</span> </p> <</if>> </div> <<if $questData && $questData.active && $questData.active["clair_sandman"] && !setup.witchSpells.hasQuestItem("flona_charm") && !$clairFlonaCharmGiven>> <div style="padding: 16px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 12px; margin-bottom: 18px; border: 2px solid #a78bfa;"> <p style="color: #cfe8f5; font-size: 15px; line-height: 1.7; margin: 0 0 10px 0;"> You ask, a little awkwardly, whether she has anything she has made with her own hands. Something a friend could keep. </p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #6a4fa8 100%); color: white; padding: 10px 24px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Ask for a token</div>">> <<if setup.witchSpells.canTap()>> <<run (function(){ var v = State.variables; if (!v.questItems) v.questItems = []; v.questItems.push({ id: "flona_charm", name: "Carved Snow Charm", description: "A small fox carved from pale wood, worn smooth by patient hands. It smells faintly of woodsmoke and clean cold.", questId: "clair_sandman" }); if (setup.questSystem) setup.questSystem.addNotification("item_received", "Received: Carved Snow Charm"); })()>> <<goto "FlonaTalk">> <</if>> <</link>> </div> <</if>> <<if setup.witchSpells.hasQuestItem("flona_charm")>> <div style="padding: 12px 16px; background: #0a1420; border-radius: 12px; margin-bottom: 18px; border: 1px solid #7ec8e3;"> <p style="color: #9bbccc; font-size: 14px; margin: 0; font-style: italic;"> "It is only a winter's whittling," Flona says, folding your fingers over the little carved fox. "But if it matters to someone, then it matters. Tell your dreaming friend the snow says hello." </p> </div> <</if>> <<if setup.islandLore.isAskable("Flona Vulri")>> <div style="background:linear-gradient(135deg,#1a1430,#0e0a1c); border:2px solid #7a6aa8; border-radius:10px; padding:14px 16px; margin:0 auto 15px; max-width:620px;"> <p style="color:#cdbdf0; font-size:15px; line-height:1.6; margin:0 0 10px 0;">You steer the talk toward the island itself. How does this place work? How long has it stood?</p> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#7a6aa8,#4a3d70); color:white; padding:9px 22px; border-radius:9px; font-weight:bold; cursor:pointer;'>Ask about the island</div>">> <<if setup.canCombineTap()>> <<set $lastLocationBeforeAsk = "FlonaTalk">> <<run setup.islandLore.recordAsk("Flona Vulri")>> <<goto "IslandLoreAccount">> <</if>> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Step back into the snow</div>">> <<goto setup.flona.homeLocation()>> <</link>> </div> </div> <<else>> <<goto "TundraOfAeternus">> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "TundraExplore">> <div style="background: #0a0f1a; min-height: 100vh; padding: 40px 20px;"> <h2 style="color: #aee0f5; text-align: center;">❄️ Tundra Exploration</h2> <<set _eventRoll = random(1, 100)>> <<set _orbRoll = random(1, 100)>> <<if !$blueOrbFound && setup.hasColdResistance() && _orbRoll === 1>> <<set $blueOrbFound = true>> <<set $blueOrbCount = ($blueOrbCount || 0) + 1>> <div style="padding:22px;background:linear-gradient(135deg,#0a1a3a 0%,#06122a 100%);border-radius:15px;margin-bottom:20px;border:2px solid #4aa8ff;box-shadow:0 0 28px rgba(60,140,255,0.4);text-align:center;"> <p style="color:#cfe8ff;font-size:16px;line-height:1.7;">Half buried in a drift, something catches the thin light and holds it. You dig it free with numb fingers: a perfect sphere of deep blue glass, warm to the touch despite the cold, a slow current of paler blue turning endlessly inside it. It does not belong here, and it does not belong to this world.</p> <p style="color:#7fc0ff;font-size:18px;font-weight:bold;margin:12px 0 0;">🔵 You found the Blue Orb!</p> <p style="color:#9bbccc;font-size:13px;margin:5px 0 0;">There is only one. Whatever it is for, you will never find another.</p> </div> <</if>> <div style="padding: 25px; background: #102030; border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <<if _eventRoll <= 18 && !$discoveredFrozenLake>> <<set $discoveredFrozenLake = true>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">You follow a long shallow grade down until the snow gives way to a sheet of ice so wide you cannot see the far shore. A frozen lake, still and pale beneath the frost, locked solid from edge to edge.</p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered the Frozen Lake!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">You can now travel here from the Tundra.</p> </div> <<elseif _eventRoll <= 34 && !$discoveredStandingStones>> <<set $discoveredStandingStones = true>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">Through a break in the drifts you come upon a ring of tall stones. Marble, every one, veined and white and older than anything else out here, standing in a circle as though they were set with great care and then forgotten.</p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered the Marble Standing Stones!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">You can now travel here from the Tundra.</p> </div> <<elseif _eventRoll <= 52 && !$discoveredFlonaTent>> <<set $discoveredFlonaTent = true>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">A thread of woodsmoke draws you across the snow to a wide tent pitched in the lee of a bank, its hide walls painted with faded blue and gold. A banked hearth glows somewhere within. This is where Flona lives.</p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered Flona's Tent!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">She makes her home here now.</p> </div> <<elseif _eventRoll <= 66 && !$discoveredTundraCave>> <<set $discoveredTundraCave = true>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">The land rises into a black shoulder of rock, and at its base yawns the mouth of a cave. Cold air breathes out of it, older than the snow above. You cannot see how far back it goes.</p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered a Cave Entrance!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">You can now travel here from the Tundra.</p> </div> <<elseif _eventRoll <= 82 && !$discoveredTaiga>> <<set $discoveredTaiga = true>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">The open white gives way to trees, rank on rank of frost laden conifers standing silent in the snow. A taiga, deep and dim, the kind of forest that swallows sound.</p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered the Taiga!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">You can now travel here from the Tundra.</p> </div> <<elseif _eventRoll <= 94 && !$discoveredMist>> <<set $discoveredMist = true>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">A low bank of mist hangs over a hollow in the snow, pale and unmoving though there is no wind to hold it. It does not look like ordinary weather.</p> <div style="background: #050f1a; padding: 15px; border-radius: 10px; margin-top: 15px; border: 1px solid #7ec8e3; text-align: center;"> <p style="color: #aee0f5; font-size: 18px; font-weight: bold; margin: 0;">❄️ You discovered the Misty Veil!</p> <p style="color: #9bbccc; font-size: 14px; margin: 5px 0 0 0;">You can now travel here from the Tundra.</p> </div> <<else>> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">You wander the snowfields for a long while, breath steaming in front of you, and find nothing new this time.</p> <</if>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Return to the Tundra</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ Frozen Lake</h1> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">The lake lies before you, a vast plain of pale ice scoured smooth by the wind. Cracks run through it like white veins, deep and silent, and far out the surface fades into the haze with no far shore in sight. Whatever water sleeps beneath the ice has been still a very long time. Your reflection follows you, dim and gray, as you walk the frozen edge.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Back to the Tundra</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ Marble Standing Stones</h1> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">The stones stand in a wide ring, taller than you, white marble gone gray with age and veined like old hands. Snow has banked against their feet and frost feathers every surface, yet the marble itself is warmer to the touch than it has any right to be out here. Someone raised these, once, and shaped them with care. Whatever they were for, the snow has kept the answer to itself.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Back to the Tundra</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ The Taiga</h1> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">Under the trees the light goes blue and dim. Frost laden conifers stand close on every side, their branches bowed under the weight of snow, and the silence is deep enough to hear your own heart. Now and then a branch lets go its load with a soft heavy sound, and then the quiet closes back over. The forest goes on further than you care to follow today.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Back to the Tundra</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ Cave Entrance</h1> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7;">The cave mouth opens in the black rock like a held breath. Cold air drifts out of it, faintly sweet, carrying a smell of stone and deep water. A few steps in, the daylight gives out and the dark takes over completely. You have no torch, no rope, and no good reason to trust your footing. For now you stay at the threshold, looking in at a black that does not look back.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Back to the Tundra</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ The Misty Veil</h1> <div style="padding: 25px; background: linear-gradient(135deg, #102030 0%, #050f1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #7ec8e3;"> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;">You step into the mist. It closes around you at once, soft and cold and thick enough that your own hands go gray and vague in front of you. The ground seems to tilt. North and south come loose from each other. You press on, sure the far side is only a few steps more.</p> <p style="color: #cfe8f5; font-size: 16px; line-height: 1.7; margin: 0;">And then you are standing in clear air again, at the edge of the hollow, facing out. Your own footprints lead in and turn and come back out, though you do not remember turning. The mist hangs where it was, pale and patient. It will not have you. Not yet.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Step back</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0a1420 0%, #14202e 100%); min-height: 100vh; padding: 30px 20px;"> <h1 style="color: #aee0f5; text-align: center;">❄️ Flona's Tent</h1> <<if setup.flona.isPresentAt("FlonaTent")>> <<if $flonaMet === false>> <div style="padding: 20px; background: rgba(126,200,227,0.10); border: 2px solid #7ec8e3; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #cfe8f5; font-size: 15px; margin: 0 0 12px 0; line-height: 1.6;">You lift the painted flap. Inside, warmth and lamplight, and a silver figure who turns at the sound of you, unsurprised, as though she has been expecting company for some time.</p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 12px 30px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Step inside</div>">> <<goto "FlonaFirstMeet">> <</link>> </div> <<else>> <div style="padding: 20px; background: rgba(126,200,227,0.10); border: 2px solid #7ec8e3; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #cfe8f5; font-size: 15px; margin: 0 0 12px 0; line-height: 1.6;">The tent is warm and close and smells of cedar smoke. Flona sits by the little hearth, tail curled around her feet, and makes room for you without a word.</p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 12px 30px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Speak with Flona</div>">> <<goto "FlonaTalk">> <</link>> </div> <</if>> <<else>> <div style="padding: 20px; background: rgba(126,200,227,0.06); border: 2px dashed #4a6b7a; border-radius: 12px; margin-bottom: 25px; text-align: center;"> <p style="color: #7a98a8; font-size: 15px; font-style: italic; margin: 0; line-height: 1.6;">The tent stands quiet, its flap tied shut. Flona is not here. Her hearth is banked low and her things are folded away, waiting for her to come home.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #7ec8e3 0%, #4080a0 100%); color: white; padding: 14px 36px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px;'>Back to the Tundra</div>">> <<goto "TundraOfAeternus">> <</link>> </div> </div> <</nobr>>
<<nobr>> /* KitsuneHypnotize - multi-stage erotic hypnosis scene */ <<set _npcName = $youkoHypnotizeTarget>> <<set _npcData = $npcs.find(function(n) { return n.name === _npcName; })>> <<set _npcGender = (_npcData && _npcData.bodyParts && _npcData.bodyParts.gender) ? _npcData.bodyParts.gender : "male">> <<set _npcPronoun = (_npcGender === "female") ? "she" : "he">> <<set _npcPronounObj = (_npcGender === "female") ? "her" : "him">> <<set _npcPronounPos = (_npcGender === "female") ? "her" : "his">> <<set _isRevnaOrRoisin = (_npcName === "Revna McKraken" || _npcName === "Roisin Sullivan")>> <!-- Player trait checks --> <<set _isDominant = $mentalTraits.includes("Dominant")>> <<set _isSubmissive = $mentalTraits.includes("Submissive")>> <<set _isFlirty = $mentalTraits.includes("Flirty")>> <<set _isAwkward = $mentalTraits.includes("Awkward")>> <<set _isConfident = $mentalTraits.includes("Confident")>> <<set _isKind = $mentalTraits.includes("Kind")>> <div style="background: linear-gradient(135deg, #1a0a2e 0%, #2a1a3a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 700px; margin: 0 auto;"> <h1 style="color: #9b59b6; text-align: center; text-shadow: 0 0 20px rgba(155,89,182,0.8); margin-bottom: 5px;">🦊 Kitsune Hypnosis 🦊</h1> <p style="color: #888; text-align: center; margin: 0 0 20px 0;">with <<print _npcName>></p> <!-- Stage indicator --> <div style="display: flex; justify-content: center; gap: 8px; margin-bottom: 25px;"> <div style="width: 50px; height: 4px; border-radius: 2px; background: <<if $youkoHypnotizeStage >= 1>>#9b59b6<<else>>#333<</if>>;"></div> <div style="width: 50px; height: 4px; border-radius: 2px; background: <<if $youkoHypnotizeStage >= 2>>#9b59b6<<else>>#333<</if>>;"></div> <div style="width: 50px; height: 4px; border-radius: 2px; background: <<if $youkoHypnotizeStage >= 3>>#9b59b6<<else>>#333<</if>>;"></div> </div> /* ======================== STAGE 1: INITIATION ======================== */ <<if $youkoHypnotizeStage === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #3a2a4a 0%, #2a1a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _npcGender === "male">> The fox magic stirs inside you, warm and intoxicating. Your eyes take on a faint violet glow as you approach <<print _npcName>>, and you can feel the supernatural charm radiating from your skin like perfume. <<print _npcPronoun.toUpperCase()>> notices you and pauses, something shifting in <<print _npcPronounPos>> expression — a slight glaze in the eyes, a parting of the lips. Your Kitsune nature reaches out to <<print _npcPronounObj>> like invisible silk threads, already beginning to wind around <<print _npcPronounPos>> will. <<else>> The fox magic stirs inside you, warm and intoxicating. Your eyes take on a faint violet glow as you approach <<print _npcName>>, and you can feel the supernatural charm radiating from your skin like perfume. She notices you and pauses, her breath catching. Something in her eyes softens, a flush rising in her cheeks. Your Kitsune nature reaches out to her like invisible silk threads, already beginning to wind around her thoughts. <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6;"> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">How do you begin the enchantment?</h2> <div style="display: grid; gap: 15px;"> <!-- Entrancing Gaze --> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>🌀 Entrancing Gaze</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isDominant>>Lock eyes and command their attention<<elseif _isConfident>>Hold their gaze with magnetic intensity<<elseif _isAwkward>>Catch their eyes accidentally... then hold them<<else>>Mesmerizing stare that pierces their soul<</if>></span></div>">> <<set $youkoHypnotizeChoices.push("gaze")>> <<set $youkoHypnotizeStage = 2>> <<goto "KitsuneHypnotize">> <</link>> <!-- Seductive Dance --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>💃 Seductive Dance</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isFlirty>>Sway your hips, tail swishing hypnotically<<elseif _isSubmissive>>Shy, graceful movements that entrance<<else>>Let your body move with supernatural allure<</if>></span></div>">> <<set $youkoHypnotizeChoices.push("dance")>> <<set $youkoHypnotizeStage = 2>> <<goto "KitsuneHypnotize">> <</link>> <!-- Whispered Command --> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>🗣️ Whispered Command</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isKind>>Lean close, breathy and sweet<<elseif _isDominant>>A low, commanding purr in their ear<<else>>Press your lips to their ear and whisper<</if>></span></div>">> <<set $youkoHypnotizeChoices.push("whisper")>> <<set $youkoHypnotizeStage = 2>> <<goto "KitsuneHypnotize">> <</link>> <!-- Fox Fire Charm --> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>✨ Fox Fire Charm</strong><br><span style='color: #aaa; font-size: 14px;'>Unleash your supernatural fox energy — glowing eyes, floating embers</span></div>">> <<set $youkoHypnotizeChoices.push("foxfire")>> <<set $youkoHypnotizeStage = 2>> <<goto "KitsuneHypnotize">> <</link>> </div> </div> /* ======================== STAGE 2: DEEPENING ======================== */ <<elseif $youkoHypnotizeStage === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #3a2a4a 0%, #2a1a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $youkoHypnotizeChoices[0] === "gaze">> <<if _npcGender === "male">> You catch <<print _npcName>>'s eyes and hold them. Your irises pulse with violet light, each slow blink sending waves of warmth through <<print _npcPronounPos>> mind. <<print _npcPronoun.toUpperCase()>> tries to look away but can't — your gaze is an anchor, pulling <<print _npcPronounObj>> deeper with every heartbeat. <<print _npcPronounPos.toUpperCase()>> pupils dilate, jaw slackens, breathing deepens. "That's it," you murmur, your voice carrying an otherworldly resonance. "Just look at me. Nothing else matters." A dreamy half-smile crosses <<print _npcPronounPos>> face as your charm takes hold. <<else>> You catch <<print _npcName>>'s eyes and hold them. Your irises pulse with violet light, each slow blink sending waves of warmth through her mind. She tries to look away but can't — your gaze is an anchor, pulling her deeper with every heartbeat. Her pupils dilate, lips part, breathing deepens. "That's it," you murmur, your voice carrying an otherworldly resonance. "Just look at me. Nothing else matters." A dreamy smile crosses her face as your charm winds itself around her thoughts. <</if>> <<elseif $youkoHypnotizeChoices[0] === "dance">> <<if _npcGender === "male">> You begin to sway, your movements fluid and mesmerizing, your fox tail sweeping in slow, hypnotic arcs behind you. <<print _npcName>>'s eyes follow every curve of your body, unable to look away. You roll your hips, trail your fingers along your own neck, and <<print _npcPronoun>> mirrors the motion unconsciously, swaying in time with you. The air between you thickens with violet motes of light. <<print _npcPronounPos.toUpperCase()>> expression goes slack, entranced by the supernatural grace of your movements. <<else>> You begin to sway, your movements fluid and mesmerizing, your fox tail sweeping in slow, hypnotic arcs behind you. <<print _npcName>>'s eyes follow every curve of your body, unable to look away. You roll your hips, trail your fingers along your own collarbone, and she mirrors the motion unconsciously, swaying in time with you. The air between you thickens with violet motes of light. Her expression goes dreamy, lips parted, completely entranced by the supernatural grace of your dance. <</if>> <<elseif $youkoHypnotizeChoices[0] === "whisper">> <<if _npcGender === "male">> You lean in close, so close your lips nearly brush <<print _npcName>>'s ear. Your breath is warm, carrying the subtle, intoxicating scent of fox magic. "Listen to my voice," you breathe, and the words sink into <<print _npcPronounPos>> mind like honey. <<print _npcPronoun.toUpperCase()>> shivers, goosebumps rising along <<print _npcPronounPos>> neck. Each whispered word wraps tighter around <<print _npcPronounPos>> thoughts, softening resistance, filling <<print _npcPronounObj>> with a warm, hazy obedience. <<print _npcPronounPos.toUpperCase()>> eyelids flutter as your charm seeps deeper. <<else>> You lean in close, so close your lips nearly brush <<print _npcName>>'s ear. Your breath is warm, carrying the subtle, intoxicating scent of fox magic. "Listen to my voice," you breathe, and the words sink into her mind like honey. She shivers, goosebumps cascading down her neck. Each whispered word wraps tighter around her thoughts, softening resistance, filling her with a warm, hazy yearning. Her eyelids flutter and her body sways toward you involuntarily as your charm seeps deeper. <</if>> <<else>> <<if _npcGender === "male">> Your eyes blaze violet as you unleash the full force of your fox spirit. Ethereal flames flicker to life around you — not hot, but warm, seductive, casting dancing violet shadows. Small fox-fire motes drift between you and <<print _npcName>>, each one carrying a whisper of enchantment. <<print _npcPronoun.toUpperCase()>> stares, mouth open, as the supernatural display overwhelms <<print _npcPronounPos>> senses. The fox fire swirls around <<print _npcPronounObj>>, caressing <<print _npcPronounPos>> skin with phantom warmth. <<print _npcPronounPos.toUpperCase()>> resistance crumbles as the ancient magic wraps around <<print _npcPronounPos>> mind. <<else>> Your eyes blaze violet as you unleash the full force of your fox spirit. Ethereal flames flicker to life around you — not hot, but warm, seductive, casting dancing violet shadows. Small fox-fire motes drift between you and <<print _npcName>>, each one carrying a whisper of enchantment. She stares, lips parted, as the supernatural display overwhelms her senses. The fox fire swirls around her, caressing her skin with phantom warmth. Her eyes go glassy, resistance crumbling as the ancient magic wraps around her mind like silk. <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6;"> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">Deepen the trance...</h2> <div style="display: grid; gap: 15px;"> <!-- Gentle Touch --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>💋 Gentle Touch</strong><br><span style='color: #aaa; font-size: 14px;'>Caress their face, stroke their hair — let your touch carry the enchantment deeper</span></div>">> <<set $youkoHypnotizeChoices.push("touch")>> <<set $youkoHypnotizeStage = 3>> <<goto "KitsuneHypnotize">> <</link>> <!-- Passionate Kiss --> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>🔥 Passionate Kiss</strong><br><span style='color: #aaa; font-size: 14px;'>Press your lips to theirs, transferring the full weight of your hypnotic energy</span></div>">> <<set $youkoHypnotizeChoices.push("kiss")>> <<set $youkoHypnotizeStage = 3>> <<goto "KitsuneHypnotize">> <</link>> <!-- Mental Domination --> <<link "<div style='background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ffc107;'>👀 Mental Domination</strong><br><span style='color: #aaa; font-size: 14px;'>Command them with your eyes — they obey without question</span></div>">> <<set $youkoHypnotizeChoices.push("mentalDom")>> <<set $youkoHypnotizeStage = 3>> <<goto "KitsuneHypnotize">> <</link>> <!-- Fox Spirit Embrace --> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>🦊 Fox Spirit Embrace</strong><br><span style='color: #aaa; font-size: 14px;'>Wrap your tail around them, enveloping them in supernatural warmth</span></div>">> <<set $youkoHypnotizeChoices.push("embrace")>> <<set $youkoHypnotizeStage = 3>> <<goto "KitsuneHypnotize">> <</link>> </div> </div> /* ======================== STAGE 3: THE CHARM ======================== */ <<elseif $youkoHypnotizeStage === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #3a2a4a 0%, #2a1a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $youkoHypnotizeChoices[1] === "touch">> <<if _npcGender === "male">> Your hand rises to <<print _npcName>>'s face, fingers trailing along <<print _npcPronounPos>> jawline with feather-light tenderness. Where you touch, warmth blooms, the fox charm sinking through skin into bone. You brush <<print _npcPronounPos>> hair back, your fingertips grazing <<print _npcPronounPos>> temple, and you feel <<print _npcPronounPos>> thoughts soften like wax. <<print _npcPronoun.toUpperCase()>> leans into your palm, eyes half-closed, a low sound of contentment rumbling in <<print _npcPronounPos>> chest. Your thumb traces <<print _npcPronounPos>> lower lip and <<print _npcPronoun>> trembles, completely surrendered to the intimacy of your enchanted touch. <<else>> Your hand rises to <<print _npcName>>'s face, fingers trailing along her jawline with feather-light tenderness. Where you touch, warmth blooms, the fox charm sinking through skin into bone. You brush her hair back, your fingertips grazing her temple, and you feel her thoughts soften like wax. She leans into your palm, eyes half-closed, a soft sigh escaping her lips. Your thumb traces her lower lip and she trembles, completely surrendered to the intimacy of your enchanted touch. <</if>> <<elseif $youkoHypnotizeChoices[1] === "kiss">> <<if _npcGender === "male">> You cup <<print _npcName>>'s face and press your lips to <<print _npcPronounPos>>. The moment your mouths meet, the full weight of your Kitsune charm pours through the kiss like liquid fire. <<print _npcPronoun.toUpperCase()>> stiffens for a heartbeat, then melts against you, <<print _npcPronounPos>> hands gripping your waist as the enchantment floods <<print _npcPronounPos>> senses. The kiss deepens, your tongue carrying the taste of fox magic — intoxicating, addictive. When you finally pull back, <<print _npcPronounPos>> eyes are glazed, lips swollen, chasing your mouth for more. <<else>> You cup <<print _npcName>>'s face and press your lips to hers. The moment your mouths meet, the full weight of your Kitsune charm pours through the kiss like liquid fire. She stiffens for a heartbeat, then melts against you, her hands clutching your shoulders as the enchantment floods her senses. The kiss deepens, your tongue carrying the taste of fox magic — intoxicating, addictive. When you finally pull back, her eyes are glazed, lips swollen, chasing your mouth breathlessly for more. <</if>> <<elseif $youkoHypnotizeChoices[1] === "mentalDom">> <<if _npcGender === "male">> You fix <<print _npcName>> with your glowing violet eyes and will <<print _npcPronounObj>> to kneel. Without hesitation, <<print _npcPronoun>> sinks to <<print _npcPronounPos>> knees, eyes locked on yours, expression blank and adoring. "Good," you purr, circling <<print _npcPronounObj>> slowly. Your fingers trail across <<print _npcPronounPos>> shoulders and <<print _npcPronoun>> shivers, utterly pliant under your supernatural authority. You tilt <<print _npcPronounPos>> chin up with one finger. "You want to please me, don't you?" you whisper. <<print _npcPronoun.toUpperCase()>> nods slowly, completely under your spell. <<else>> You fix <<print _npcName>> with your glowing violet eyes and will her to kneel. Without hesitation, she sinks to her knees, eyes locked on yours, expression blank and adoring. "Good," you purr, circling her slowly. Your fingers trail across her shoulders and she shivers, utterly pliant under your supernatural authority. You tilt her chin up with one finger. "You want to please me, don't you?" you whisper. She nods slowly, completely under your spell, eyes shining with devotion. <</if>> <<else>> <<if _npcGender === "male">> Your fox tail curls around <<print _npcName>>, the soft fur brushing against <<print _npcPronounPos>> skin. <<print _npcPronoun.toUpperCase()>> sighs deeply as the supernatural warmth seeps into <<print _npcPronounObj>>, your spirit wrapping around <<print _npcPronounPos>> mind like a warm blanket. You pull <<print _npcPronounObj>> close, pressing your body against <<print _npcPronounPos>>, and <<print _npcPronoun>> sinks into the embrace as if you're the only solid thing in the world. <<print _npcPronounPos.toUpperCase()>> breathing slows to match yours, heartbeat synchronizing, mind falling into perfect, blissful alignment with your will. <<else>> Your fox tail curls around <<print _npcName>>, the soft fur brushing against her skin. She sighs deeply as the supernatural warmth seeps into her, your spirit wrapping around her mind like a warm blanket. You pull her close, pressing your body against hers, and she sinks into the embrace as if you're the only solid thing in the world. Her breathing slows to match yours, heartbeat synchronizing, mind falling into perfect, blissful alignment with your will. <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #9b59b6;"> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">Complete the enchantment...</h2> <div style="display: grid; gap: 15px;"> <!-- Loving Devotion --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>💝 Loving Devotion</strong><br><span style='color: #aaa; font-size: 14px;'>Implant feelings of love and loyalty deep in their enchanted mind</span></div>">> <<set $youkoHypnotizeChoices.push("devotion")>> <<goto "KitsuneHypnotizeResult">> <</link>> <!-- Binding Charm --> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>🔗 Binding Charm</strong><br><span style='color: #aaa; font-size: 14px;'>A mystical bond that compels affection — they can't help but be drawn to you</span></div>">> <<set $youkoHypnotizeChoices.push("binding")>> <<goto "KitsuneHypnotizeResult">> <</link>> <!-- Memory Rewrite --> <<link "<div style='background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ffc107;'>✨ Memory Rewrite</strong><br><span style='color: #aaa; font-size: 14px;'>Alter their memories — replace coldness with warmth, distance with closeness</span></div>">> <<set $youkoHypnotizeChoices.push("rewrite")>> <<goto "KitsuneHypnotizeResult">> <</link>> </div> </div> <</if>> <!-- Cancel button (stage 1 only) --> <<if $youkoHypnotizeStage === 1>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #444; color: #aaa; padding: 10px 25px; border-radius: 8px; cursor: pointer;'>← Cancel</div>">> <<set $youkoHypnotizeStage = 0>> <<set $youkoHypnotizeChoices = []>> <<goto "Abilities">> <</link>> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set _npcName = $youkoHypnotizeTarget>> <<set _npcData = $npcs.find(function(n) { return n.name === _npcName; })>> <<set _npcGender = (_npcData && _npcData.bodyParts && _npcData.bodyParts.gender) ? _npcData.bodyParts.gender : "male">> <<set _npcPronoun = (_npcGender === "female") ? "she" : "he">> <<set _npcPronounObj = (_npcGender === "female") ? "her" : "him">> <<set _npcPronounPos = (_npcGender === "female") ? "her" : "his">> <<set _isRevnaOrRoisin = (_npcName === "Revna McKraken" || _npcName === "Roisin Sullivan")>> <<set _pointChange = _isRevnaOrRoisin ? -200 : 100>> <!-- Apply effects --> <<run setup.addRelationshipPoints(_npcName, _pointChange)>> <<set $youkoHypnotizeUsedToday = true>> <<set $youkoLastHypnotized = _npcName>> <<set $youkoLastHypnotizePoints = _pointChange>> <div style="background: linear-gradient(135deg, #1a0a2e 0%, #2a1a3a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 700px; margin: 0 auto;"> <h1 style="color: #9b59b6; text-align: center; text-shadow: 0 0 20px rgba(155,89,182,0.8); margin-bottom: 25px;">🦊 Enchantment Complete 🦊</h1> <!-- Charm completion scene --> <div style="padding: 20px; background: linear-gradient(135deg, #3a2a4a 0%, #2a1a3a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9b59b6;"> <<if !_isRevnaOrRoisin>> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $youkoHypnotizeChoices[2] === "devotion">> <<if _npcGender === "male">> You press your forehead to <<print _npcName>>'s, violet light pulsing between you. "You adore me," you breathe, and the words sink into <<print _npcPronounPos>> mind like roots into soil. <<print _npcPronounPos.toUpperCase()>> expression transforms — suspicion melting into warmth, wariness becoming tenderness. When you step back, <<print _npcPronoun>> blinks slowly, a soft smile on <<print _npcPronounPos>> face, looking at you as if seeing you for the first time. "I... I don't know what came over me," <<print _npcPronoun>> murmurs, flushed and dazed. "But I feel... warm when I look at you." <<else>> You press your forehead to <<print _npcName>>'s, violet light pulsing between you. "You adore me," you breathe, and the words sink into her mind like roots into soil. Her expression transforms — uncertainty melting into warmth, distance becoming closeness. When you step back, she blinks slowly, a dreamy smile on her face, looking at you as if seeing you for the first time. "I... I don't know what came over me," she murmurs, cheeks flushed. "But I feel... drawn to you. Like I always have been." <</if>> <<elseif $youkoHypnotizeChoices[2] === "binding">> <<if _npcGender === "male">> You trace a glowing violet sigil on <<print _npcName>>'s chest with your fingertip. The symbol sinks into <<print _npcPronounPos>> skin, invisible but powerful — a mystical tether connecting <<print _npcPronounPos>> heart to yours. <<print _npcPronoun.toUpperCase()>> gasps as the binding takes hold, eyes widening. The enchantment settles like a second heartbeat, a constant pull toward you that <<print _npcPronoun>> won't even realize is there. <<print _npcPronoun.toUpperCase()>> shakes <<print _npcPronounPos>> head as the trance lifts, but the warmth in <<print _npcPronounPos>> eyes when <<print _npcPronoun>> looks at you says everything. <<else>> You trace a glowing violet sigil on <<print _npcName>>'s chest with your fingertip. The symbol sinks into her skin, invisible but powerful — a mystical tether connecting her heart to yours. She gasps as the binding takes hold, eyes widening. The enchantment settles like a second heartbeat, a constant pull toward you she won't even realize is there. She shakes her head as the trance lifts, but the warmth in her eyes when she looks at you says everything. <</if>> <<else>> <<if _npcGender === "male">> You reach into <<print _npcName>>'s entranced mind and gently reshape <<print _npcPronounPos>> memories of you. Cold encounters become warm. Annoyances become endearing quirks. Distance becomes intimacy. The violet magic weaves through <<print _npcPronounPos>> thoughts like thread through fabric, altering the pattern without breaking it. When <<print _npcPronoun>> wakes, <<print _npcPronoun>>'ll remember shared laughter, meaningful glances, a growing connection that was always there. <<print _npcPronoun.toUpperCase()>> blinks, confused but smiling. "Sorry, I zoned out. What were we talking about?" <<print _npcPronoun.toUpperCase()>> looks at you with familiar affection. <<else>> You reach into <<print _npcName>>'s entranced mind and gently reshape her memories of you. Cold encounters become warm. Annoyances become endearing quirks. Distance becomes intimacy. The violet magic weaves through her thoughts like thread through fabric, altering the pattern without breaking it. When she wakes, she'll remember shared laughter, meaningful glances, a connection that was always there. She blinks, confused but smiling. "Sorry, I zoned out for a second. What were we talking about?" She looks at you with familiar warmth. <</if>> <</if>> </p> <<else>> <!-- Revna/Roisin resistance scene --> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _npcName === "Revna McKraken">> For a moment, the enchantment takes hold — Revna's eyes go glassy, her shoulders relaxing. But then something ancient and powerful surges up from within her, shattering your charm like glass. Her eyes snap into focus, burning with fury. "You dare try that fox magic on ME?" she snarls, supernatural power crackling around her. "I am Revna McKraken. Your parlor tricks are nothing compared to my will." She shoves you back, and you feel the enchantment rebound, your own magic recoiling painfully. This was a mistake. <<else>> The hypnosis sinks in — Roisin's expression softens, her guard dropping. But only for a heartbeat. Something sharp and dangerous flashes in her eyes as she tears through the enchantment with sheer force of will. "Nice try, fox," she says coldly, straightening her clothes. "But I've dealt with your kind before." Her glare is ice and iron. "Try that again and you'll find out exactly how unpleasant I can be." The failed charm leaves a bitter taste in your mouth and a very angry Roisin. <</if>> </p> <</if>> </div> <!-- Results --> <div style="padding: 20px; background: #1a1a2e; border-radius: 15px; margin-bottom: 25px; border: 1px solid #9b59b6;"> <h3 style="color: #9b59b6; margin: 0 0 15px 0;">🦊 Results</h3> <<if _pointChange > 0>> <div style="background: #1a3a1a; padding: 10px; border-radius: 8px; border: 1px solid #51cf66; margin-bottom: 10px;"> <p style="color: #51cf66; margin: 0; font-size: 14px;">✨ <<print _npcName>> gained <<print _pointChange>> relationship points</p> </div> <<else>> <div style="background: #3a1a1a; padding: 10px; border-radius: 8px; border: 1px solid #ff6b6b; margin-bottom: 10px;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px;">⚠️ <<print _npcName>> resisted! <<print _pointChange>> relationship points</p> </div> <</if>> <p style="color: #aaa; margin: 10px 0 0 0; font-size: 13px;">Hypnotize ability used for today.</p> </div> <!-- Return button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Return to Abilities</div>">> <<set $youkoHypnotizeStage = 0>> <<set $youkoHypnotizeChoices = []>> <<goto "Abilities">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> /* JinkoEatFish - excluded passage, do not set $lastLocation */ <div style="background: linear-gradient(135deg, #1a0a0a 0%, #2a1a1a 100%); min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #e74c3c; text-align: center; text-shadow: 0 0 20px rgba(231,76,60,0.8);">🐟 Jinko Fish Feast</h1> <div style="padding: 15px; background: #2a2a2a; border-radius: 10px; margin-bottom: 20px; border: 2px solid #e74c3c;"> <p style="color: #ccc; font-size: 14px; margin: 0; text-align: center;"> Devour a fish to gain temporary stat buffs. Rarer fish = stronger buffs. Mythical fish grant the permanent Fish trait (+20% all stats). </p> </div> <<if $fishInventory && $fishInventory.length > 0>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _i = 0; _i < $fishInventory.length; _i++>> <<set _fish = $fishInventory[_i]>> <<set _rarity = _fish.rarity || "common">> <<set _rarityColor = "#ffffff">> <<set _buffDesc = _rarity === "mythical" ? "Grants Fish Trait (+20% all stats permanently!)" : (_rarity === "legendary" ? "+20% all stats for 1 hour" : (_rarity === "epic" ? "+15% all stats for 1 hour" : (_rarity === "rare" ? "+10% all stats for 1 hour" : (_rarity === "uncommon" ? "+5% all stats for 1 hour" : "+1% all stats for 1 hour"))))>> <div style="border: 2px solid <<print _rarityColor>>; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h4 style="color: <<print _rarityColor>>; margin: 0 0 5px 0;"><<print _fish.name>></h4> <p style="color: #888; font-size: 12px; margin: 0 0 5px 0; text-transform: capitalize;"><<print _rarity>></p> <p style="color: #ccc; font-size: 13px; margin: 0 0 10px 0;"><<print _buffDesc>></p> <<capture _i, _rarity>> <<link "<div style='background: #e74c3c; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Devour</div>">> <<if _rarity === "mythical">> <<if !$physicalTraits.includes("Fish")>> <<run $physicalTraits.push("Fish")>> <</if>> <<set $jinkoLastAte = "mythical">> <<elseif _rarity === "legendary">> <<run setup.addBuff("jinko_fish_legendary", 60)>> <<set $jinkoLastAte = "legendary">> <<elseif _rarity === "epic">> <<run setup.addBuff("jinko_fish_epic", 60)>> <<set $jinkoLastAte = "epic">> <<elseif _rarity === "rare">> <<run setup.addBuff("jinko_fish_rare", 60)>> <<set $jinkoLastAte = "rare">> <<elseif _rarity === "uncommon">> <<run setup.addBuff("jinko_fish_uncommon", 60)>> <<set $jinkoLastAte = "uncommon">> <<else>> <<run setup.addBuff("jinko_fish_common", 60)>> <<set $jinkoLastAte = "common">> <</if>> <<run $fishInventory.splice(_i, 1)>> <<goto "JinkoEatFish">> <</link>> <</capture>> </div> <</for>> </div> <<else>> <div style="padding: 20px; background: #2a2a2a; border-radius: 10px; margin-bottom: 25px; text-align: center;"> <p style="color: #888; font-size: 16px; margin: 0;">No fish in your inventory. Go fishing first!</p> </div> <</if>> <<if $jinkoLastAte>> <div style="padding: 15px; background: linear-gradient(135deg, #1a4a1a 0%, #2d6b2d 100%); border-radius: 10px; margin-bottom: 20px; border: 2px solid #51cf66;"> <<if $jinkoLastAte === "mythical">> <p style="color: #ffffff; font-size: 18px; margin: 0; text-align: center; font-weight: bold;">🌟 You devoured a mythical fish and gained the Fish trait! +20% all stats permanently! 🌟</p> <<else>> <p style="color: #51cf66; font-size: 16px; margin: 0; text-align: center;">You devoured a <<print $jinkoLastAte>> fish and feel power surging through you!</p> <</if>> </div> <<set $jinkoLastAte = undefined>> <</if>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Return to Abilities</div>">> <<goto "Abilities">> <</link>> </div> </div></div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(135deg, #1a1a2e 0%, #2a2a3a 100%); min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <div style="padding: 20px; border-radius: 10px; background: #2a2a2a; border: 2px solid #3498db;"> <h3 style="color: #3498db; text-align: center; margin-top: 0;">🌤️ Weather Control Module</h3> <p style="color: #ccc; font-size: 14px; margin: 0; text-align: center;"> Expend your Overcharged energy to force a weather change. Current weather: <strong style="color: #ffd700;"><<print $currentWeather>></strong> </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 2px solid #f1c40f; border-radius: 10px; padding: 15px; background: #2a2a2a; text-align: center;"> <h3 style="color: #f1c40f; margin: 0 0 10px 0;">☀️ Clear</h3> <<link "<div style='background: #f1c40f; color: #1a1a1a; padding: 10px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Set Clear</div>">> <<set $currentWeather = "Clear">> <<run setup.removeBuff("automaton_overcharged")>> <<goto "Abilities">> <</link>> </div> <div style="border: 2px solid #95a5a6; border-radius: 10px; padding: 15px; background: #2a2a2a; text-align: center;"> <h3 style="color: #95a5a6; margin: 0 0 10px 0;">☁️ Cloudy</h3> <<link "<div style='background: #95a5a6; color: #1a1a1a; padding: 10px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Set Cloudy</div>">> <<set $currentWeather = "Cloudy">> <<run setup.removeBuff("automaton_overcharged")>> <<goto "Abilities">> <</link>> </div> <div style="border: 2px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a; text-align: center;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🌧️ Rainy</h3> <<link "<div style='background: #3498db; color: white; padding: 10px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Set Rainy</div>">> <<set $currentWeather = "Rainy">> <<run setup.removeBuff("automaton_overcharged")>> <<goto "Abilities">> <</link>> </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Close</div>">> <<replace "#ability-detail">><</replace>> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="padding: 20px; border-radius: 10px; background: #2a2a2a; border: 2px solid #ffd700;"> <h3 style="color: #ffd700; text-align: center; margin-top: 0; text-shadow: 0 0 30px rgba(255,215,0,0.8);">👑 Pharaoh's Divine Powers</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Weather Control --> <div style="border: 2px solid #3498db; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #3498db; margin: 0 0 10px 0;">🌤️ Weather Control</h3> <p style="color: #ccc; font-size: 13px; margin: 0 0 10px 0;">Current: <strong><<print $currentWeather>></strong></p> <div style="display: flex; gap: 8px; flex-wrap: wrap;"> <<link "<div style='background: #f1c40f; color: #1a1a1a; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold;'>☀️ Clear</div>">><<set $currentWeather = "Clear">><<goto "PharaohPowers">><</link>> <<link "<div style='background: #95a5a6; color: #1a1a1a; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold;'>☁️ Cloudy</div>">><<set $currentWeather = "Cloudy">><<goto "PharaohPowers">><</link>> <<link "<div style='background: #3498db; color: white; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold;'>🌧️ Rainy</div>">><<set $currentWeather = "Rainy">><<goto "PharaohPowers">><</link>> <<link "<div style='background: #e74c3c; color: white; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold;'>⛈️ Stormy</div>">><<set $currentWeather = "Stormy">><<goto "PharaohPowers">><</link>> </div> </div> <!-- Chest Size Control --> <div style="border: 2px solid #e056a0; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #e056a0; margin: 0 0 10px 0;">👗 Chest Size</h3> <p style="color: #ccc; font-size: 13px; margin: 0 0 10px 0;">Current: <strong><<print $bodyParts.chest>></strong></p> <div style="display: flex; gap: 8px; flex-wrap: wrap;"> <<link "<div style='background: #e056a0; color: white; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold;'>⬆ Increase</div>">> <<set _sizes = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx = _sizes.indexOf($bodyParts.chest)>> <<if _idx < _sizes.length - 1>><<set $bodyParts.chest = _sizes[_idx + 1]>><</if>> <<goto "PharaohPowers">> <</link>> <<link "<div style='background: #c0448f; color: white; padding: 6px 12px; border-radius: 4px; cursor: pointer; font-size: 13px; font-weight: bold;'>⬇ Decrease</div>">> <<set _sizes = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx = _sizes.indexOf($bodyParts.chest)>> <<if _idx > 0>><<set $bodyParts.chest = _sizes[_idx - 1]>><</if>> <<goto "PharaohPowers">> <</link>> </div> </div> <!-- NPC Gender Change --> <div style="border: 2px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">🔄 Change NPC Gender</h3> <p style="color: #ccc; font-size: 13px; margin: 0 0 10px 0;">Select an NPC to toggle their gender.</p> <<link "<div style='background: #9b59b6; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Select NPC</div>">> <<set $pharaohGenderLocation = $lastLocation>> <<goto "PharaohGenderChange">> <</link>> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Close</div>">> <<replace "#ability-detail">><</replace>> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(135deg, #2a1a00 0%, #1a0a00 100%); min-height: 100vh; padding: 20px;"> <div style="background: rgba(42,42,42,0.85); padding: 20px; border-radius: 10px;"> <h1 style="color: #9b59b6; text-align: center;">🔄 Divine Gender Transformation</h1> <p style="color: #ccc; text-align: center; margin-bottom: 20px;">Select an NPC in your current area to toggle their gender.</p> <<set _pharaohLoc = $pharaohGenderLocation || $lastLocation>> <<set _excluded = ["Revna McKraken", "Luna Snow", "Roisin Sullivan"]>> <<set _foundNPCs = false>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _i = 0; _i < $npcs.length; _i++>> <<set _npc = $npcs[_i]>> <<set _npcName = _npc.name>> /* Check if NPC belongs to this location: job location OR any schedule slot OR currently here */ <<set _npcBelongs = false>> /* Check job location */ <<set _npcJob = Array.isArray(_npc.jobs) ? _npc.jobs[0] : _npc.jobs>> <<if setup.jobLocations[_npcJob] === _pharaohLoc>><<set _npcBelongs = true>><</if>> /* Check schedule default location */ <<if !_npcBelongs>> <<set _schedKey = _npc.scheduleSource || _npc.originalName || _npc.permanentId || _npc.name>> <<set _sched = setup.npcLocationSchedules[_schedKey]>> <<if _sched && _sched.defaultLocation === _pharaohLoc>><<set _npcBelongs = true>><</if>> /* Check all schedule time slots */ <<if !_npcBelongs && _sched && _sched.customSchedule>> <<for _dayKey, _daySlots range _sched.customSchedule>> <<if !_npcBelongs>> <<for _slot range _daySlots>> <<if _slot.location === _pharaohLoc>><<set _npcBelongs = true>><</if>> <</for>> <</if>> <</for>> <</if>> <</if>> /* Check if NPC is currently at this location right now */ <<if !_npcBelongs>> <<set _curLoc = setup.getNPCLocation(_npc, $dayOfWeek, Math.floor($timeInMinutes / 60) % 24)>> <<if _curLoc === _pharaohLoc>><<set _npcBelongs = true>><</if>> <</if>> <<if _npcBelongs && !_excluded.includes(_npcName) && _npc.bodyParts>> <<set _foundNPCs = true>> <div style="border: 2px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h4 style="color: #d4b3ff; margin: 0 0 5px 0;"><<print _npcName>></h4> <p style="color: #aaa; font-size: 13px; margin: 0 0 10px 0;">Current: <<print _npc.bodyParts.gender>></p> <<capture _npcName>> <<link "<div style='background: #9b59b6; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Toggle Gender</div>">> <<set _targetNpc = $npcs.find(function(n) { return n.name === _npcName; })>> <<if _targetNpc && _targetNpc.bodyParts>> <<if _targetNpc.bodyParts.gender === "male">> <<set _targetNpc.bodyParts.gender = "female">> <<else>> <<set _targetNpc.bodyParts.gender = "male">> <</if>> <</if>> <<goto "PharaohGenderChange">> <</link>> <</capture>> </div> <</if>> <</for>> </div> <<if !_foundNPCs>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; text-align: center; margin-bottom: 20px;"> <p style="color: #888;">No NPCs belong to this area.</p> </div> <</if>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Back to Abilities</div>">> <<goto "Abilities">> <</link>> </div> </div></div> <</nobr>>
<<nobr>> <div style="padding: 20px; border-radius: 10px; background: #2a2a2a; border: 2px solid #e056a0;"> <h3 style="color: #e056a0; text-align: center; margin-top: 0; text-shadow: 0 0 20px rgba(224,86,160,0.8);">🪞 Cheshire Mirror</h3> <div style="padding: 15px; background: #2a2a2a; border-radius: 10px; margin-bottom: 20px; border: 2px solid #e056a0;"> <p style="color: #ccc; font-size: 14px; margin: 0; text-align: center;"> Gaze into the mirror and let your Cheshire essence reshape your form. </p> <p style="color: #aaa; font-size: 13px; margin: 10px 0 0 0; text-align: center;"> Chest: <strong><<print $bodyParts.chest>></strong> | Butt: <strong><<print $bodyParts.butt>></strong> </p> </div> <<set _sizes = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 2px solid #e056a0; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #e056a0; margin: 0 0 10px 0;">👗 Increase Chest</h3> <<set _chestIdx = _sizes.indexOf($bodyParts.chest)>> <<if _chestIdx >= _sizes.length - 1>> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center;">Already Maximum Size</div> <<else>> <<link "<div style='background: #e056a0; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Grow Chest</div>">> <<set _sizes2 = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx2 = _sizes2.indexOf($bodyParts.chest)>> <<if _idx2 < _sizes2.length - 1>><<set $bodyParts.chest = _sizes2[_idx2 + 1]>><</if>> <<set $cheshireSexToday = false>> <<goto "Abilities">> <</link>> <</if>> </div> <div style="border: 2px solid #c0448f; border-radius: 10px; padding: 15px; background: #2a2a2a;"> <h3 style="color: #c0448f; margin: 0 0 10px 0;">🍑 Increase Butt</h3> <<set _buttIdx = _sizes.indexOf($bodyParts.butt)>> <<if _buttIdx >= _sizes.length - 1>> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center;">Already Maximum Size</div> <<else>> <<link "<div style='background: #c0448f; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Grow Butt</div>">> <<set _sizes3 = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx3 = _sizes3.indexOf($bodyParts.butt)>> <<if _idx3 < _sizes3.length - 1>><<set $bodyParts.butt = _sizes3[_idx3 + 1]>><</if>> <<set $cheshireSexToday = false>> <<goto "Abilities">> <</link>> <</if>> </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Close</div>">> <<replace "#ability-detail">><</replace>> <</link>> </div> </div> <</nobr>>
<<nobr>> /* DarkAngelSwap - excluded passage, do not set $lastLocation */ <div style="padding: 20px; border-radius: 10px; background: #2a2a2a; border: 2px solid #cc66ff;"> <h3 style="color: #cc66ff; text-align: center; margin-top: 0;">😈 Dark Angel — Forced Trait Swap</h3> <div style="padding: 15px; background: #2a1a3a; border-radius: 10px; border: 2px solid #cc66ff; margin-bottom: 20px;"> <p style="color: #ccc; margin: 0; line-height: 1.6;"> Your dark power allows you to force NPCs who dislike you to swap their traits with yours. Select an NPC with a negative relationship (Disliked or worse) to swap a mutually exclusive trait pair. </p> </div> <<set _foundTargets = false>> <<set _npcsHere = setup.getNPCsAtLocation($lastLocation)>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-bottom: 20px;"> <<for _i = 0; _i < _npcsHere.length; _i++>> <<set _npcName = _npcsHere[_i].name>> <<set _rel = $relationships[_npcName]>> <<if _rel && _rel.level <= -1>> <<set _foundTargets = true>> <<capture _npcName, _rel>> <<link "<div style='background: linear-gradient(135deg, #3a1a4a, #2a0a3a); border: 2px solid #cc66ff; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer;'><p style='color: #cc66ff; font-weight: bold; margin: 0 0 5px 0;'><<print _npcName>></p><p style='color: #888; font-size: 12px; margin: 0;'>Relationship: <<print _rel.level>></p></div>">> <<set $darkAngelTarget = _npcName>> <<goto "DarkAngelSwapSelect">> <</link>> <</capture>> <</if>> <</for>> </div> <<if !_foundTargets>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; text-align: center;"> <p style="color: #888;">No NPCs with negative relationships are in your current area.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Close</div>">> <<replace "#ability-detail">><</replace>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npcName = $darkAngelTarget>> <<set _npcData = $npcs.find(function(n) { return n.name === _npcName; })>> <div style="background: linear-gradient(180deg, #1a0a2a 0%, #0a0a1a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #cc66ff; text-align: center;">😈 Swap Traits with <<print _npcName>></h1> <<set _swappable = []>> <<set _npcTraits = _npcData.physicalTraits || []>> <<set _npcWontTrade = (_npcData.preferences && _npcData.preferences.wontTrade) ? _npcData.preferences.wontTrade : []>> <!-- Find mutually exclusive matches --> <<for _groupName, _group range setup.exclusiveTraitGroups>> <<for _pi = 0; _pi < $physicalTraits.length; _pi++>> <<if _group.includes($physicalTraits[_pi])>> <<for _ni = 0; _ni < _npcTraits.length; _ni++>> <<if _group.includes(_npcTraits[_ni]) && $physicalTraits[_pi] !== _npcTraits[_ni] && !_npcWontTrade.includes(_npcTraits[_ni])>> <<run _swappable.push({playerTrait: $physicalTraits[_pi], npcTrait: _npcTraits[_ni], group: _groupName})>> <</if>> <</for>> <</if>> <</for>> <</for>> <!-- Appearance & Body Part Swaps --> <<if _npcData.appearance && $appearance>> <!-- Hair Color swap --> <<if _npcData.appearance.hairColor && $appearance.hairColor && _npcData.appearance.hairColor !== $appearance.hairColor && !_npcWontTrade.includes("hairColor")>> <<run _swappable.push({playerTrait: $appearance.hairColor + " Hair", npcTrait: _npcData.appearance.hairColor + " Hair", group: "Hair Color", swapType: "appearance", property: "hairColor", playerValue: $appearance.hairColor, npcValue: _npcData.appearance.hairColor})>> <</if>> <!-- Skin Tone swap --> <<if _npcData.appearance.skinTone && $appearance.skinTone && _npcData.appearance.skinTone.toLowerCase() !== $appearance.skinTone.toLowerCase() && !_npcWontTrade.includes("skinTone")>> <<run _swappable.push({playerTrait: $appearance.skinTone.toUpperFirst() + " Skin", npcTrait: _npcData.appearance.skinTone.toUpperFirst() + " Skin", group: "Skin Tone", swapType: "appearance", property: "skinTone", playerValue: $appearance.skinTone, npcValue: _npcData.appearance.skinTone})>> <</if>> <</if>> <<if _npcData.bodyParts && $bodyParts>> <!-- Chest Size swap --> <<if _npcData.bodyParts.chest && $bodyParts.chest && _npcData.bodyParts.chest.toLowerCase() !== $bodyParts.chest.toLowerCase() && !_npcWontTrade.includes("chest")>> <<run _swappable.push({playerTrait: $bodyParts.chest.toUpperFirst() + " Chest", npcTrait: _npcData.bodyParts.chest.toUpperFirst() + " Chest", group: "Chest Size", swapType: "bodyPart", property: "chest", playerValue: $bodyParts.chest, npcValue: _npcData.bodyParts.chest})>> <</if>> <!-- Butt Size swap --> <<if _npcData.bodyParts.butt && $bodyParts.butt && _npcData.bodyParts.butt.toLowerCase() !== $bodyParts.butt.toLowerCase() && !_npcWontTrade.includes("butt")>> <<run _swappable.push({playerTrait: $bodyParts.butt.toUpperFirst() + " Butt", npcTrait: _npcData.bodyParts.butt.toUpperFirst() + " Butt", group: "Butt Size", swapType: "bodyPart", property: "butt", playerValue: $bodyParts.butt, npcValue: _npcData.bodyParts.butt})>> <</if>> <!-- Genitals swap --> <<if _npcData.bodyParts.genitals && $bodyParts.genitals && _npcData.bodyParts.genitals !== $bodyParts.genitals && !_npcWontTrade.includes("genitals")>> <<run _swappable.push({playerTrait: $bodyParts.genitals.toUpperFirst(), npcTrait: _npcData.bodyParts.genitals.toUpperFirst(), group: "Genitals", swapType: "bodyPart", property: "genitals", playerValue: $bodyParts.genitals, npcValue: _npcData.bodyParts.genitals})>> <</if>> <</if>> <<if _swappable.length === 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; text-align: center; margin-bottom: 20px;"> <p style="color: #888;">No swappable attributes found with <<print _npcName>>.</p> </div> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px; margin-bottom: 20px;"> <<for _s = 0; _s < _swappable.length; _s++>> <<capture _swappable[_s]>> <<link "<div style='background: #2a1a3a; border: 2px solid #cc66ff; padding: 15px; border-radius: 8px; cursor: pointer;'><p style='color: #ff6b6b; margin: 0 0 5px 0;'>Give: <<print _swappable[_s].playerTrait>></p><p style='color: #51cf66; margin: 0 0 5px 0;'>Receive: <<print _swappable[_s].npcTrait>></p><p style='color: #888; font-size: 11px; margin: 0;'>(<<print _swappable[_s].group>>)</p></div>">> <<set _swap = _swappable[_s]>> <<set _npcRef = $npcs.find(function(n) { return n.name === $darkAngelTarget; })>> <<if _swap.swapType === "appearance">> /* Appearance swap (hair color, skin tone) */ <<set _oldPlayerVal = $appearance[_swap.property]>> <<set $appearance[_swap.property] = _swap.npcValue>> <<set _npcRef.appearance[_swap.property] = _oldPlayerVal>> <<elseif _swap.swapType === "bodyPart">> /* Body part swap (chest, butt, genitals) */ <<set _oldPlayerVal = $bodyParts[_swap.property]>> <<set $bodyParts[_swap.property] = _swap.npcValue>> <<set _npcRef.bodyParts[_swap.property] = _oldPlayerVal>> <<else>> /* Trait swap (physicalTraits) */ <<run $physicalTraits.delete(_swap.playerTrait)>> <<if !$physicalTraits.includes(_swap.npcTrait)>> <<run $physicalTraits.push(_swap.npcTrait)>> <</if>> <<run _npcRef.physicalTraits.delete(_swap.npcTrait)>> <<if !_npcRef.physicalTraits.includes(_swap.playerTrait)>> <<run _npcRef.physicalTraits.push(_swap.playerTrait)>> <</if>> <</if>> <<set $darkAngelLastSwap = {gave: _swap.playerTrait, received: _swap.npcTrait, npc: $darkAngelTarget, group: _swap.group}>> <<goto "DarkAngelSwapResult">> <</link>> <</capture>> <</for>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Back</div>">> <<goto "Abilities">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npcData = $npcs.find(function(n) { return n.name === $darkAngelLastSwap.npc; })>> <<set _npcGender = (_npcData && _npcData.bodyParts && _npcData.bodyParts.gender) ? _npcData.bodyParts.gender : "male">> <<set _they = (_npcGender === "female") ? "she" : "he">> <<set _They = (_npcGender === "female") ? "She" : "He">> <<set _them = (_npcGender === "female") ? "her" : "him">> <<set _their = (_npcGender === "female") ? "her" : "his">> <<set _Their = (_npcGender === "female") ? "Her" : "His">> <<set _theirs = (_npcGender === "female") ? "hers" : "his">> <div style="background: linear-gradient(180deg, #1a0a2a 0%, #0a0a1a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 700px; margin: 0 auto;"> <h1 style="color: #cc66ff; text-align: center; text-shadow: 0 0 30px rgba(204,102,255,0.6);">😈 Dark Communion</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2a1a3a 0%, #1a0a2a 100%); border-radius: 10px; border: 2px solid #cc66ff; margin-bottom: 20px;"> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 0;"> You find <<print $darkAngelLastSwap.npc>> alone, and the darkness inside you surges with anticipation. Your black wings unfurl, blotting out the light around you both. A faint purple halo flickers above your head, casting <<print _their>> face in shifting violet shadows. <<print _They>> sees you and <<print _their>> expression twists, hostility and fear warring across <<print _their>> features. </p> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 15px 0 0 0;"> “Stay away from me,” <<print $darkAngelLastSwap.npc>> warns, backing against the wall. But the darkness is already reaching for <<print _them>>, tendrils of shadow curling from your wings like living smoke. <<print _They>> tries to move but <<print _their>> limbs won’t obey. Your corruption holds <<print _them>> fast. </p> </div> <div style="padding: 20px; background: #2a1a3a; border-radius: 10px; border: 1px solid #9933cc; margin-bottom: 20px;"> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 0;"> You close the distance between you with deliberate, predatory grace. Your fingertips find <<print _their>> chin and tilt it upward, forcing <<print _them>> to meet your eyes. Your irises glow a deep, pulsing violet, and you watch the defiance in <<print _their>> gaze flicker and crack. </p> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 15px 0 0 0;"> “You have something I want,” you whisper, and your voice reverberates with dark power. You press your body against <<print _theirs>>, the warmth of your skin against <<print _their>> trembling form. Your wings fold around you both, creating a cocoon of shadow and heat. In this darkness there is only you, <<print _them>>, and the electric tension between your bodies. </p> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 15px 0 0 0;"> You lean in close, your lips brushing the shell of <<print _their>> ear. “This will only hurt for a moment,” you breathe. <<print _They>> tries to protest but the sound dies in <<print _their>> throat as your hand presses flat against <<print _their>> chest. Dark energy pulses between you, and <<print _they>> gasps, <<print _their>> back arching, body pressing involuntarily into yours. </p> </div> <div style="padding: 20px; background: linear-gradient(135deg, #1a0a2a 0%, #2a0a3a 100%); border-radius: 10px; border: 1px solid #7722aa; margin-bottom: 20px;"> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 0;"> The extraction begins. You feel <<print _their>> essence, the core of <<print _their>> <strong style="color: #51cf66;"><<print $darkAngelLastSwap.received>></strong>, pulsing like a second heartbeat beneath your palm. You curl your fingers and <em>pull</em>. <<print _They>> cries out, <<print _their>> body convulsing against yours, fingers clawing at your wings as the trait tears free from <<print _them>> in a rush of violet light. </p> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 15px 0 0 0;"> The energy floods into you, hot and heady. Your body trembles with the influx, the new trait weaving itself into the fabric of who you are. At the same time, your own <strong style="color: #ff6b6b;"><<print $darkAngelLastSwap.gave>></strong> flows down your arm and into <<print _them>>, an exchange of essence that leaves you both gasping and shuddering. </p> <p style="color: #ddd; font-size: 15px; line-height: 1.8; margin: 15px 0 0 0;"> For a long, breathless moment you stay pressed together, foreheads touching, both of you trembling with the aftershocks of the transfer. <<print _Their>> eyes are unfocused, <<print _their>> lips parted, <<print _their>> body slack against yours. The intimacy of it, two souls forcibly intertwined, is intoxicating. </p> </div> <div style="padding: 20px; background: #2a2a3a; border-radius: 10px; border: 1px solid #666; margin-bottom: 20px;"> <p style="color: #aaa; font-size: 14px; line-height: 1.6; margin: 0; font-style: italic;"> You retract your wings and step back, licking your lips. <<print $darkAngelLastSwap.npc>> slumps against the wall, drained and confused, <<print _their>> body still tingling where your darkness touched <<print _them>>. <<print _They>> won’t forget this. Nobody ever forgets. </p> </div> <div style="padding: 15px; background: #1a0a2a; border-radius: 10px; border: 2px solid #cc66ff; margin-bottom: 20px;"> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 8px 0; text-align: center;">Gave <<print $darkAngelLastSwap.npc>>: <strong><<print $darkAngelLastSwap.gave>></strong></p> <p style="color: #51cf66; font-size: 16px; margin: 0; text-align: center;">Took from <<print _them>>: <strong><<print $darkAngelLastSwap.received>></strong></p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Back to Abilities</div>">> <<goto "Abilities">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> /* SalamanderCook - excluded passage, do not set $lastLocation */ <div style="padding: 20px; border-radius: 10px; background: #2a2a2a; border: 2px solid #e74c3c;"> <h3 style="color: #e74c3c; text-align: center; margin-top: 0;">🔥 Salamander Cooking</h3> <div style="padding: 15px; background: #3a1a0a; border-radius: 10px; border: 2px solid #e74c3c; margin-bottom: 20px;"> <p style="color: #ccc; margin: 0; line-height: 1.6;"> Your inner fire lets you cook anywhere! Select a recipe to prepare using ingredients from your inventory. </p> </div> <!-- Recipe Grid --> <<set _recipes = Object.keys(setup.recipes || {})>> <<if _recipes.length === 0>> <p style="color: #888; text-align: center;">No recipes available.</p> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 15px; margin-bottom: 20px;"> <<for _recipeId, _recipe range setup.recipes>> <<set _canCook = true>> <<for _ingName, _ingAmount range _recipe.ingredients>> <<if !$kitchenInventory || !$kitchenInventory.ingredients || !$kitchenInventory.ingredients[_ingName] || $kitchenInventory.ingredients[_ingName] < _ingAmount>> <<set _canCook = false>> <</if>> <</for>> <div style="background: #2a1a0a; border: 2px solid <<if _canCook>>#e74c3c<<else>>#444<</if>>; border-radius: 10px; padding: 15px;"> <h3 style="color: <<if _canCook>>#e74c3c<<else>>#666<</if>>; margin: 0 0 8px 0;"><<print _recipe.name>></h3> <p style="color: #888; font-size: 13px; margin: 0 0 8px 0;"> Ingredients: <<for _ingName, _ingAmount range _recipe.ingredients>> <<set _have = ($kitchenInventory && $kitchenInventory.ingredients && $kitchenInventory.ingredients[_ingName]) ? $kitchenInventory.ingredients[_ingName] : 0>> <span style="color: <<if _have >= _ingAmount>>#51cf66<<else>>#ff6b6b<</if>>;"><<print _ingName>> (<<print _have>>/<<print _ingAmount>>)</span> <</for>> </p> <p style="color: #888; font-size: 12px; margin: 0 0 10px 0;">⏰ <<print _recipe.time>> min</p> <<if _canCook>> <<capture _recipeId, _recipe>> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🔥 Cook</div>">> <<for _ingName, _ingAmount range _recipe.ingredients>> <<set $kitchenInventory.ingredients[_ingName] -= _ingAmount>> <</for>> <<set _buff = setup.getRandomFoodBuff(_recipe.cost || 10)>> <<set _buffDuration = (_recipe.time || 30) * 4>> <<if !$foodInventory>><<set $foodInventory = []>><</if>> <<run $foodInventory.push({name: _recipe.name, buffId: _buff.type, buffDuration: _buffDuration, buffStrength: _buff.strength})>> <<set $salamanderCookNotify = _recipe.name>> <<run advanceTime(_recipe.time)>> <<goto "Abilities">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center;">Missing ingredients</div> <</if>> </div> <</for>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Close</div>">> <<replace "#ability-detail">><</replace>> <</link>> </div> </div> <</nobr>>
<<nobr>> /* RaijuSex - excluded passage, do not set $lastLocation */ <div style="background: linear-gradient(180deg, #1a1a0a 0%, #0a0a00 100%); min-height: 100vh; padding: 20px;"> <div style="padding: 20px; border-radius: 10px; background: #2a2a2a; border: 2px solid #f1c40f;"> <h3 style="color: #f1c40f; text-align: center; margin-top: 0;">⚡ Raiju Encounter</h3> <div style="padding: 15px; background: #2a2a1a; border-radius: 10px; border: 2px solid #f1c40f; margin-bottom: 20px;"> <p style="color: #ccc; margin: 0; line-height: 1.6;"> Your Raiju nature craves physical connection. Select an NPC to approach. </p> </div> <<set _foundNPCs = false>> <<set _npcsHere = setup.getNPCsAtLocation($lastLocation)>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 10px; margin-bottom: 20px;"> <<for _i = 0; _i < _npcsHere.length; _i++>> <<set _npc = _npcsHere[_i]>> <<set _npcName = _npc.name>> <<if _npcName === "Luna" || _npcName === "Revna McKraken">> <<else>> <<set _rel = $relationships[_npcName]>> <<set _relLevel = (_rel) ? _rel.level : 0>> <<set _foundNPCs = true>> <<set _willLosePoints = _relLevel < 3>> <<capture _npcName, _relLevel, _willLosePoints>> <<link "<div style='background: #2a2a1a; border: 2px solid <<if _willLosePoints>>#ff6b6b<<else>>#f1c40f<</if>>; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer;'><p style='color: #f1c40f; font-weight: bold; margin: 0 0 5px 0;'><<print _npcName>></p><p style='color: #888; font-size: 12px; margin: 0;'>Level: <<print _relLevel>><<if _willLosePoints>> <span style='color: #ff6b6b;'>(-50 pts)</span><</if>></p></div>">> <<if _willLosePoints>> <<run setup.addRelationshipPoints(_npcName, -50)>> <</if>> <!-- Satisfy sexual needs --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <</if>> <<set $raijuLastTarget = _npcName>> <<set $raijuLostPoints = _willLosePoints>> <<run advanceTime(60)>> <<goto "RaijuSexResult">> <</link>> <</capture>> <</if>> <</for>> </div> <<if !_foundNPCs>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; text-align: center;"> <p style="color: #888;">There are no NPCs nearby right now.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Close</div>">> <<replace "#ability-detail">><</replace>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npcName = $raijuLastTarget>> <<set _npcData = $npcs.find(function(n) { return n.name === _npcName; })>> <<set _npcGender = (_npcData && _npcData.bodyParts && _npcData.bodyParts.gender) ? _npcData.bodyParts.gender : "male">> <<set _npcPronoun = (_npcGender === "female") ? "she" : "he">> <<set _npcPronounObj = (_npcGender === "female") ? "her" : "him">> <<set _npcPronounPos = (_npcGender === "female") ? "her" : "his">> <<set _npcChest = (_npcData && _npcData.bodyParts && _npcData.bodyParts.chest) ? _npcData.bodyParts.chest : "flat">> <<set _npcButt = (_npcData && _npcData.bodyParts && _npcData.bodyParts.butt) ? _npcData.bodyParts.butt : "small">> <<set _npcGenitals = (_npcData && _npcData.bodyParts && _npcData.bodyParts.genitals) ? _npcData.bodyParts.genitals : "penis">> <<set _npcHasVagina = (_npcGenitals === "vagina" || _npcGenitals === "tight vagina" || _npcGenitals === "loose vagina")>> <<set _npcHasPenis = (_npcGenitals === "penis" || _npcGenitals === "big penis" || _npcGenitals === "small penis")>> <<set _npcHasBreasts = (_npcChest !== "flat" && _npcChest !== "flat masculine")>> <<set _rel = $relationships[_npcName] || {level: 0, points: 0}>> <div style="background: linear-gradient(180deg, #1a1a0a 0%, #0a0a00 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 700px; margin: 0 auto;"> <h1 style="color: #f1c40f; text-align: center; text-shadow: 0 0 20px rgba(241,196,15,0.8); margin-bottom: 25px;">⚡ Electrical Afterglow ⚡</h1> <!-- Climax Scene --> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a0a 0%, #1a1a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f1c40f;"> <<if $raijuEncounterChoices[3] === "fullDischarge">> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _npcGender === "male">> Every nerve in your body ignites simultaneously as the electricity you've been building erupts in a blinding flash. Your back arches violently, lightning arcing from your fingertips into <<print _npcName>>'s <<if _npcHasBreasts>><<print _npcChest>> chest<<else>>chest<</if>>. <<print _npcPronoun.toUpperCase()>> cries out, muscles locking as the current surges through both of you. The room flickers with golden light as wave after wave of electric ecstasy tears through your body. Your thighs clamp around <<print _npcPronounObj>> as you ride the final pulse, a scream caught in your throat, replaced by a sound somewhere between a moan and a crack of thunder. <<else>> Every nerve in your body ignites simultaneously as the electricity you've been building erupts in a blinding flash. Your back arches violently, lightning arcing from your fingertips across <<print _npcName>>'s skin. She gasps, her whole body trembling as the current courses between you both. Golden light flickers across the room as wave after wave of electric ecstasy rolls through you. Your hands grip her <<print _npcButt>> hips as you ride the final devastating pulse, a scream tearing from your lips that sounds like a crack of thunder echoing off the walls. <</if>> </p> <<elseif $raijuEncounterChoices[3] === "chainLightning">> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _npcGender === "male">> The first climax hits you like a lightning strike — sudden, devastating, whiting out your vision. But instead of fading, the current bounces back from <<print _npcName>>'s body into yours, triggering a second wave. Then a third. Each one chains into the next, electricity arcing back and forth between your bodies in an endless loop of pleasure. <<print _npcPronoun.toUpperCase()>> groans against your neck, body shaking, caught in the same relentless circuit. Four, five waves crash through you before the current finally dissipates, leaving you both gasping, skin tingling, the faint smell of ozone lingering in the air. <<else>> The first climax hits you like a lightning strike — sudden, devastating, whiting out your vision. But instead of fading, the current bounces back from <<print _npcName>>'s body into yours, triggering a second wave. Then a third. Each one chains into the next, electricity arcing back and forth between your bodies in an endless loop. She cries out against your shoulder, nails digging into your skin, caught in the same relentless circuit. Four, five waves crash through you before the current finally dissipates, leaving you both trembling, skin alive with static, the faint smell of ozone clinging to the sheets. <</if>> </p> <<else>> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _npcGender === "male">> You feel <<print _npcName>>'s rhythm sync perfectly with yours, and in that moment the electricity stops flowing in one direction — it becomes a closed circuit, a feedback loop of pure sensation. You climax together in an explosion of light, golden sparks showering from your entwined bodies. <<print _npcPronoun.toUpperCase()>> buries <<print _npcPronounPos>> face against your neck, groaning your name as the electricity discharges through every point of contact. The world goes white, then slowly, beautifully dark. When your vision clears, you're both panting, tangled together, tiny sparks still dancing across your sweat-slicked skin. <<else>> You feel <<print _npcName>>'s rhythm sync perfectly with yours, and in that moment the electricity stops flowing in one direction — it becomes a closed circuit, a feedback loop of pure sensation. You climax together in an explosion of light, golden sparks showering from your entwined bodies. She buries her face in your hair, crying your name as the electricity discharges through every point of contact. The world goes white, then slowly, beautifully dark. When your vision clears, you're both panting, tangled together, tiny sparks still dancing across your glistening skin. <</if>> </p> <</if>> </div> <!-- Post-Encounter NPC Reaction --> <div style="padding: 20px; background: #2a2a2a; border-radius: 15px; margin-bottom: 25px; border: 1px solid #555;"> <<if _rel.level >= 3>> <p style="color: #ccc; font-size: 15px; line-height: 1.7; margin: 0;"> <<if _npcGender === "male">> <<print _npcName>> pulls you close afterward, pressing <<print _npcPronounPos>> lips to your forehead. "That was... I don't have words," <<print _npcPronoun>> murmurs against your hair, fingers tracing lazy circles on your back. A comfortable warmth settles between you, different from the electricity — something softer, more human. <<else>> <<print _npcName>> curls against you afterward, her breathing slowly steadying. "That was... incredible," she whispers, pressing her lips to your shoulder. Her fingers find yours, intertwining gently. A comfortable warmth settles between you, different from the electricity — something softer, more tender. <</if>> </p> <<else>> <p style="color: #ccc; font-size: 15px; line-height: 1.7; margin: 0;"> <<if _npcGender === "male">> <<print _npcName>> pulls away quickly once it's over, running a hand through <<print _npcPronounPos>> disheveled hair. The look <<print _npcPronoun>> gives you is complicated — part satisfaction, part resentment. "That was..." <<print _npcPronoun>> trails off, looking away. "Don't expect this to change anything between us." <<else>> <<print _npcName>> rolls away quickly once it's over, gathering herself. The look she gives you is complicated — flushed and breathless but guarded. "That was..." she starts, then shakes her head. "Don't think this changes anything between us." <</if>> </p> <</if>> </div> <!-- Mechanical Results --> <div style="padding: 20px; background: #1a1a2e; border-radius: 15px; margin-bottom: 25px; border: 1px solid #f1c40f;"> <h3 style="color: #f1c40f; margin: 0 0 15px 0;">⚡ Results</h3> <!-- Relationship penalty --> <<if $raijuLostPoints>> <<run setup.addRelationshipPoints(_npcName, -50)>> <div style="background: #3a1a1a; padding: 10px; border-radius: 8px; border: 1px solid #ff6b6b; margin-bottom: 10px;"> <p style="color: #ff6b6b; margin: 0; font-size: 14px;">⚠️ <<print _npcName>> lost 50 relationship points (low relationship level)</p> </div> <</if>> <!-- Satisfy sexual needs --> <<if typeof setup.satisfySlutSexualNeeds === "function">> <<run setup.satisfySlutSexualNeeds()>> <</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">> <<run setup.satisfyCheshireCatSexualNeeds()>> <</if>> <!-- Honeybee honey --> <<if $physicalTraits.includes("Honeybee")>> <<set $honeyInventory = ($honeyInventory || 0) + 1>> <div style="background: #2a2a1a; padding: 10px; border-radius: 8px; border: 1px solid #f39c12; margin-bottom: 10px;"> <p style="color: #f39c12; margin: 0; font-size: 14px;">🍯 Produced 1 honey (Honeybee)</p> </div> <</if>> <!-- Sexual skill XP --> <<if $sexualSkills>> <<if $raijuEncounterChoices[1] === "oral">> <<run setup.addSexualSkillExp("oralGiving", 15)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+15 Oral (Giving) XP</p> <<elseif $raijuEncounterChoices[1] === "vaginal">> <<run setup.addSexualSkillExp("vaginal", 15)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+15 Vaginal XP</p> <<elseif $raijuEncounterChoices[1] === "penetrate">> <<run setup.addSexualSkillExp("vaginal", 15)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+15 Vaginal XP</p> <<elseif $raijuEncounterChoices[1] === "hands">> <<run setup.addSexualSkillExp("handjobs", 10)>> <<run setup.addSexualSkillExp("fingering", 10)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+10 Handjobs XP, +10 Fingering XP</p> <<elseif $raijuEncounterChoices[1] === "breasts">> <<run setup.addSexualSkillExp("titfuck", 15)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+15 Titfuck XP</p> <<elseif $raijuEncounterChoices[1] === "boobjob">> <<run setup.addSexualSkillExp("titfuck", 20)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+20 Titfuck XP</p> <</if>> <!-- Bonus XP from approach --> <<if $raijuEncounterChoices[0] === "dominant">> <<run setup.addSexualSkillExp("domination", 10)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+10 Domination XP</p> <<elseif $raijuEncounterChoices[0] === "seductive">> <<run setup.addSexualSkillExp("sensual", 10)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+10 Sensual XP</p> <<elseif $raijuEncounterChoices[0] === "playful">> <<run setup.addSexualSkillExp("teasing", 10)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+10 Teasing XP</p> <<elseif $raijuEncounterChoices[0] === "overwhelming">> <<run setup.addSexualSkillExp("rough", 10)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+10 Rough XP</p> <</if>> <!-- Enhancement XP --> <<if $raijuEncounterChoices[2] === "voltageSurge">> <<run setup.addSexualSkillExp("rough", 8)>> <<run setup.addSexualSkillExp("stamina", 8)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+8 Rough XP, +8 Stamina XP</p> <<elseif $raijuEncounterChoices[2] === "slowDischarge">> <<run setup.addSexualSkillExp("sensual", 8)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+8 Sensual XP</p> <<elseif $raijuEncounterChoices[2] === "lightningDom">> <<run setup.addSexualSkillExp("domination", 8)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+8 Domination XP</p> <<elseif $raijuEncounterChoices[2] === "sharedCircuit">> <<run setup.addSexualSkillExp("sensual", 8)>> <p style="color: #51cf66; margin: 5px 0; font-size: 13px;">+8 Sensual XP</p> <</if>> <</if>> <!-- Time advance --> <<run advanceTime(60)>> <p style="color: #aaa; margin: 10px 0 0 0; font-size: 13px;">⏰ 1 hour has passed</p> </div> <!-- Return button --> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>← Return to Abilities</div>">> <<set $raijuEncounterStage = 0>> <<set $raijuEncounterChoices = []>> <<set $raijuEncounterSkillsUsed = []>> <<goto "Abilities">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: #04101a; min-height: 100vh; padding: 20px;"> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #0a1a2a 0%, #00101a 100%); border: 3px solid #4aa8ff; color: #4aa8ff; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(74,168,255,0.3); display: inline-block;'>← Put the card away</div>">><<goto "Inventory">><</link>> </div> <h1 style="color: #4aa8ff; text-align: center; margin: 0 0 10px 0; text-shadow: 0 0 15px rgba(74,168,255,0.5);">A Recipe in Foreign Script</h1> <<if $skills && ($skills.includes("Foreign Language") || $skills.includes("Languages"))>> <p style="color: #9cc4e0; font-size: 14px; line-height: 1.6; text-align: center; margin: 0 auto 20px auto; max-width: 600px;">Your knowledge of foreign languages turns the dense script into something you can follow. It is a recipe, written as a list of what to combine.</p> <div style="background: #06121e; border-radius: 10px; border: 1px solid #4aa8ff; max-width: 560px; margin: 0 auto 20px auto; overflow: hidden;"> <div style="padding: 12px 16px; border-bottom: 1px solid #16344a; color: #cfe6ff; font-size: 15px;">1. Abyssal Jelly</div> <div style="padding: 12px 16px; border-bottom: 1px solid #16344a; color: #cfe6ff; font-size: 15px;">2. Energy Drink</div> <div style="padding: 12px 16px; border-bottom: 1px solid #16344a; color: #cfe6ff; font-size: 15px;">3. Mithril Ore</div> <div style="padding: 12px 16px; border-bottom: 1px solid #16344a; color: #cfe6ff; font-size: 15px;">4. Tomato</div> <div style="padding: 12px 16px; color: #ffd700; font-size: 18px; font-weight: bold;">5. ?</div> </div> <<else>> <p style="color: #9cc4e0; font-size: 14px; line-height: 1.6; text-align: center; margin: 0 auto; max-width: 600px;">The card is covered in dense foreign writing. The letters curl and knot in a way you cannot begin to read. Someone who knows another language might make sense of it.</p> <</if>> </div> <</nobr>>
<<nobr>> <div style="background: #0d0804; min-height: 100vh; padding: 20px;"> <!-- Back Button --> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2a1a0a 0%, #1a0a00 100%); border: 3px solid #cd7f32; color: #cd7f32; padding: 15px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 20px rgba(205,127,50,0.3); display: inline-block;'>← Close Book</div>">><<goto "Inventory">><</link>> </div> <h1 style="color: #cd7f32; text-align: center; margin: 0 0 10px 0; text-shadow: 0 0 15px rgba(205,127,50,0.5);">The Mechanical Codex</h1> <p style="color: #c9a06c; font-size: 14px; line-height: 1.6; text-align: center; margin: 0 0 20px 0; max-width: 600px; margin-left: auto; margin-right: auto;"> You flip through the worn pages. Most of the text is in a language you can’t read — angular symbols mixed with technical diagrams of gears and mechanisms. The pages contain a sequence of entries — some printed in ink, others left blank with faint outlines, as if waiting to be filled in. </p> <!-- Codex sequence: 1837 [Jungle] [Desert] 7396 [Mountain] [Manor] 1901 --> <div style="background: #0d0804; border-radius: 10px; border: 1px solid #cd7f32; overflow: hidden; max-width: 650px; margin: 0 auto 20px auto;"> <!-- Entry 1: 1837 (printed) --> <div style="padding: 15px; border-bottom: 1px solid #3a2a1a; text-align: center;"> <span style="color: #ffd700; font-size: 32px; font-weight: bold; font-family: monospace; text-shadow: 0 0 10px rgba(255,215,0,0.5); letter-spacing: 6px;"><<print $obeliskCodes[0][0]>><<print $obeliskCodes[0][1]>><<print $obeliskCodes[0][2]>><<print $obeliskCodes[0][3]>></span> <p style="color: #666; font-size: 11px; margin: 5px 0 0 0; font-style: italic;">Printed in metallic ink</p> </div> <!-- Entry 2: Jungle (blank - fillable) --> <div style="padding: 15px; border-bottom: 1px solid #3a2a1a;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div style="flex: 1; min-width: 180px;"> <div style="background: #1a1508; padding: 10px; border-radius: 6px; border: 1px dashed #2ecc71;"> <p style="color: #6a8a5a; font-size: 12px; margin: 0; line-height: 1.5; font-style: italic;">Where green curtains hang from a ceiling with no room, and the floor breathes wet and warm. Where roots drink from the sky and the earth never dries. Seek the white bone among the tangled fingers.</p> </div> </div> <div style="text-align: center;"> <p style="color: #888; font-size: 11px; margin: 0 0 5px 0;">Your notes:</p> <<textbox "$codexEntry_jungle" $codexEntry_jungle>> </div> </div> </div> <!-- Entry 3: Desert (blank - fillable) --> <div style="padding: 15px; border-bottom: 1px solid #3a2a1a;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div style="flex: 1; min-width: 180px;"> <div style="background: #1a1508; padding: 10px; border-radius: 6px; border: 1px dashed #c2953a;"> <p style="color: #a08050; font-size: 12px; margin: 0; line-height: 1.5; font-style: italic;">Where the ocean has no water and the waves are made of gold. Where the sun claims dominion and shade is a forgotten word. A grave of glass that rises where nothing should grow.</p> </div> </div> <div style="text-align: center;"> <p style="color: #888; font-size: 11px; margin: 0 0 5px 0;">Your notes:</p> <<textbox "$codexEntry_desert" $codexEntry_desert>> </div> </div> </div> <!-- Entry 4: 7396 (printed) --> <div style="padding: 15px; border-bottom: 1px solid #3a2a1a; text-align: center;"> <span style="color: #ffd700; font-size: 32px; font-weight: bold; font-family: monospace; text-shadow: 0 0 10px rgba(255,215,0,0.5); letter-spacing: 6px;"><<print $obeliskCodes[3][0]>><<print $obeliskCodes[3][1]>><<print $obeliskCodes[3][2]>><<print $obeliskCodes[3][3]>></span> <p style="color: #666; font-size: 11px; margin: 5px 0 0 0; font-style: italic;">Printed in metallic ink</p> </div> <!-- Entry 5: Mountain (blank - fillable) --> <div style="padding: 15px; border-bottom: 1px solid #3a2a1a;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div style="flex: 1; min-width: 180px;"> <div style="background: #1a1508; padding: 10px; border-radius: 6px; border: 1px dashed #8B9DAF;"> <p style="color: #7090a0; font-size: 12px; margin: 0; line-height: 1.5; font-style: italic;">Where giants sleep with mouths of stone and breath of frost. Where the world tilts upward and the air grows thin and sharp. Between the teeth of the sleeping giant, something smooth waits in the cold.</p> </div> </div> <div style="text-align: center;"> <p style="color: #888; font-size: 11px; margin: 0 0 5px 0;">Your notes:</p> <<textbox "$codexEntry_mountain" $codexEntry_mountain>> </div> </div> </div> <!-- Entry 6: Manor (blank - fillable) --> <div style="padding: 15px; border-bottom: 1px solid #3a2a1a;"> <div style="display: flex; gap: 15px; align-items: center; flex-wrap: wrap;"> <div style="flex: 1; min-width: 180px;"> <div style="background: #1a1508; padding: 10px; border-radius: 6px; border: 1px dashed #9b59b6;"> <p style="color: #8060a0; font-size: 12px; margin: 0; line-height: 1.5; font-style: italic;">Where grandeur rots and empty eyes watch from hollow frames. Only the pale queen’s light reveals the path. Among thorns that guard a fallen crown, the white sentinel stands where no gardener tends.</p> </div> </div> <div style="text-align: center;"> <p style="color: #888; font-size: 11px; margin: 0 0 5px 0;">Your notes:</p> <<textbox "$codexEntry_manor" $codexEntry_manor>> </div> </div> </div> <!-- Entry 7: 1901 (printed) --> <div style="padding: 15px; text-align: center;"> <span style="color: #ffd700; font-size: 32px; font-weight: bold; font-family: monospace; text-shadow: 0 0 10px rgba(255,215,0,0.5); letter-spacing: 6px;"><<print $obeliskCodes[6][0]>><<print $obeliskCodes[6][1]>><<print $obeliskCodes[6][2]>><<print $obeliskCodes[6][3]>></span> <p style="color: #666; font-size: 11px; margin: 5px 0 0 0; font-style: italic;">Printed in metallic ink</p> </div> </div> <p style="color: #888; font-size: 13px; margin: 0; font-style: italic; text-align: center;">On the last page, a crude ink sketch shows a room — copper pipes on the ceiling, riveted steel floor, a door with four gears. Unmistakable.</p> </div> <!-- Style the textboxes to match the steampunk theme --> <style> .passage input[type="text"] { background: #1a1008 !important; border: 2px solid #cd7f32 !important; color: #ffd700 !important; font-family: monospace !important; font-size: 20px !important; font-weight: bold !important; text-align: center !important; width: 100px !important; padding: 8px !important; border-radius: 6px !important; letter-spacing: 4px !important; text-shadow: 0 0 8px rgba(255,215,0,0.4) !important; } .passage input[type="text"]:focus { outline: none !important; border-color: #ffd700 !important; box-shadow: 0 0 10px rgba(255,215,0,0.4) !important; } </style> <</nobr>>
<<nobr>> /* Clear hypnotize target if player did not come from an NPC menu or the hypnotize flow */ <<set _npcPages = ["NPCInteraction", "NPCTalk", "NPCTalkResponse", "NPCSocialSelect", "NPCGiftResponse", "TradeInterface", "SellTraits", "KitsuneHypnotize", "KitsuneHypnotizeResult", "Abilities"]>> <<if _npcPages.indexOf(previous()) === -1>> <<set $tradingWithNPC = null>> <</if>> <div style="max-width: 800px; margin: 0 auto; padding: 20px;"> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 20px; border: 3px solid #ff6b6b; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h2 style="color: #ff6b6b; margin-top: 0;">✨ Transformation Abilities</h2> <div style="display: flex; flex-direction: column; gap: 15px;"> /* ===== ANGEL LINE ===== */ <<if $physicalTraits.includes("Angel") || $physicalTraits.includes("Cupid")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #ffd700;"> <div style="color: #ffd700; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;"><<if $physicalTraits.includes("Cupid")>>Angel → Cupid<<else>>Angel<</if>></div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700, #fff3bf); color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(255,215,0,0.5);'>😇 Purify — Remove Negative Traits</div>">> <<set _purified = []>> <<set _newPhysical = []>> <<for _t range $physicalTraits>> <<if setup.isNegativeTrait(_t)>> <<run _purified.push(_t)>> <<else>> <<run _newPhysical.push(_t)>> <</if>> <</for>> <<set _newMental = []>> <<for _t range $mentalTraits>> <<if setup.isNegativeTrait(_t)>> <<run _purified.push(_t)>> <<else>> <<run _newMental.push(_t)>> <</if>> <</for>> <<set _newSkills = []>> <<for _t range $skills>> <<if setup.isNegativeTrait(_t)>> <<run _purified.push(_t)>> <<else>> <<run _newSkills.push(_t)>> <</if>> <</for>> <<set $physicalTraits = _newPhysical>> <<set $mentalTraits = _newMental>> <<set $skills = _newSkills>> <<set $angelLastPurified = _purified>> <<goto "Abilities">> <</link>> </div> </div> <</if>> /* ===== WERECAT LINE ===== */ <<if $physicalTraits.includes("Cheshire Cat") || $physicalTraits.includes("Jinko")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #e056a0;"> <div style="color: #e056a0; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;"><<if $physicalTraits.includes("Cheshire Cat")>>Werecat → Cheshire Cat<<elseif $physicalTraits.includes("Jinko")>>Werecat → Jinko<</if>></div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<if $physicalTraits.includes("Cheshire Cat")>> <<if !$cheshireSexToday>> <div style="background: #444; color: #888; padding: 10px 20px; border-radius: 8px; font-weight: bold;">🪞 Mirror — Increase Size (Requires Daily Sex)</div> <<else>> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #e056a0; margin-top: 5px;"> <p style="color: #ccc; font-size: 13px; margin: 0 0 8px 0;">🪞 Chest: <strong><<print $bodyParts.chest>></strong> | Butt: <strong><<print $bodyParts.butt>></strong></p> <<set _sizes = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<set _chestIdx = _sizes.indexOf($bodyParts.chest)>> <<if _chestIdx >= _sizes.length - 1>> <div style="background: #444; color: #888; padding: 8px 16px; border-radius: 6px; font-weight: bold;">👗 Chest Max</div> <<else>> <<link "<div style='background: linear-gradient(135deg, #e056a0, #c0448f); color: white; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer;'>👗 Grow Chest</div>">> <<set _sizes2 = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx2 = _sizes2.indexOf($bodyParts.chest)>> <<if _idx2 < _sizes2.length - 1>><<set $bodyParts.chest = _sizes2[_idx2 + 1]>><</if>> <<set $cheshireSexToday = false>> <<goto "Abilities">> <</link>> <</if>> <<set _buttIdx = _sizes.indexOf($bodyParts.butt)>> <<if _buttIdx >= _sizes.length - 1>> <div style="background: #444; color: #888; padding: 8px 16px; border-radius: 6px; font-weight: bold;">🍑 Butt Max</div> <<else>> <<link "<div style='background: linear-gradient(135deg, #c0448f, #a03070); color: white; padding: 8px 16px; border-radius: 6px; font-weight: bold; cursor: pointer;'>🍑 Grow Butt</div>">> <<set _sizes3 = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx3 = _sizes3.indexOf($bodyParts.butt)>> <<if _idx3 < _sizes3.length - 1>><<set $bodyParts.butt = _sizes3[_idx3 + 1]>><</if>> <<set $cheshireSexToday = false>> <<goto "Abilities">> <</link>> <</if>> </div> </div> <</if>> <</if>> <<if $physicalTraits.includes("Jinko")>> <<link "<div style='background: linear-gradient(135deg, #e74c3c, #c0392b); color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(231,76,60,0.5);'>🐟 Eat Fish — Stat Buffs</div>">> <<goto "JinkoEatFish">> <</link>> <</if>> </div> </div> <</if>> /* ===== WEREWOLF LINE ===== */ <<if $physicalTraits.includes("Anubis")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #c9a227;"> <div style="color: #c9a227; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Werewolf → Anubis</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #1a0a3a, #3a1a0a); color: #ffd700; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; border: 2px solid #ffd700; box-shadow: 0 0 10px rgba(255,215,0,0.4);'>☀️ Clear the Skies</div>">> <<set $currentWeather = "Clear">> <<goto "Abilities">> <</link>> </div> </div> <</if>> /* ===== LIVING DOLL LINE ===== */ <<if $physicalTraits.includes("Automaton")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #95a5a6;"> <div style="color: #95a5a6; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Living Doll → Automaton</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #95a5a6, #7f8c8d); color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(149,165,166,0.5);'>⚙️ Rest Mode — Sleep Anywhere</div>">> <<advancetime 480>> <<run setup.removeDebuff("exhaustion")>> <<set $lastSleepTime = setup.getTotalGameMinutes()>><<run setup.removeDebuff("dive_injury")>> <<run setup.addBuff("well_rested", 480)>><<run setup.mining && setup.mining.refillEnergy && setup.mining.refillEnergy()>> <<goto "Abilities">> <</link>> <<if $activeBuffs && $activeBuffs.some(function(b) { return b.id === "automaton_overcharged"; })>> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #3498db; margin-top: 5px; width: 100%;"> <p style="color: #ccc; font-size: 13px; margin: 0 0 8px 0;">🌤️ Weather: <strong style="color: #ffd700;"><<print $currentWeather>></strong> (Costs Overcharged)</p> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<link "<div style='background: #f1c40f; color: #1a1a1a; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 13px;'>☀️ Clear</div>">> <<set $currentWeather = "Clear">> <<run setup.removeBuff("automaton_overcharged")>> <<goto "Abilities">> <</link>> <<link "<div style='background: #95a5a6; color: #1a1a1a; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 13px;'>☁️ Cloudy</div>">> <<set $currentWeather = "Cloudy">> <<run setup.removeBuff("automaton_overcharged")>> <<goto "Abilities">> <</link>> <<link "<div style='background: #3498db; color: white; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 13px;'>🌧️ Rainy</div>">> <<set $currentWeather = "Rainy">> <<run setup.removeBuff("automaton_overcharged")>> <<goto "Abilities">> <</link>> </div> </div> <<else>> <div style="background: #444; color: #888; padding: 10px 20px; border-radius: 8px; font-weight: bold;">🌤️ Weather Control (Requires Overcharged)</div> <</if>> </div> </div> <</if>> /* ===== SLUT LINE ===== */ <<if $physicalTraits.includes("Raiju")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #f1c40f;"> <div style="color: #f1c40f; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Slut → Raiju</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <div style="width: 100%;"> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #f1c40f; margin-top: 5px;"> <<set _foundNPCs = false>> <<set _npcsHere = setup.getNPCsAtLocation($lastLocation)>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-bottom: 10px;"> <<for _i = 0; _i < _npcsHere.length; _i++>> <<set _npc = _npcsHere[_i]>> <<set _npcName = _npc.name>> <<if _npcName === "Luna" || _npcName === "Revna McKraken">> <<else>> <<set _rel = $relationships[_npcName]>> <<set _relLevel = (_rel) ? _rel.level : 0>> <<set _foundNPCs = true>> <<set _willLosePoints = _relLevel < 3>> <<capture _npcName, _relLevel, _willLosePoints>> <<link "<div style='background: #2a2a1a; border: 1px solid <<if _willLosePoints>>#ff6b6b<<else>>#f1c40f<</if>>; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer;'><p style='color: #f1c40f; font-weight: bold; margin: 0; font-size: 13px;'><<print _npcName>></p><p style='color: #888; font-size: 11px; margin: 2px 0 0 0;'>Lv: <<print _relLevel>><<if _willLosePoints>> <span style='color: #ff6b6b;'>(-50)</span><</if>></p></div>">> <<set $raijuLastTarget = _npcName>> <<set $raijuLostPoints = _willLosePoints>> <<set $raijuEncounterStage = 1>> <<set $raijuEncounterChoices = []>> <<set $raijuEncounterSkillsUsed = []>> <<goto "RaijuEncounter">> <</link>> <</capture>> <</if>> <</for>> </div> <<if !_foundNPCs>> <p style="color: #888; font-size: 13px; text-align: center;">No NPCs are in your current area right now.</p> <</if>> </div> </div> </div> </div> <</if>> /* ===== LIZARDMAN LINE ===== */ <<if $physicalTraits.includes("Salamander") || $physicalTraits.includes("Cerberus")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #e74c3c;"> <div style="color: #e74c3c; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;"><<if $physicalTraits.includes("Cerberus")>>Cerberus<<else>>Lizardman → Salamander<</if>></div> <<if $salamanderCookNotify>> <div style="background: #1a3a1a; border: 2px solid #51cf66; border-radius: 10px; padding: 15px; margin-bottom: 10px; text-align: center; width: 100%;"> <p style="color: #51cf66; font-size: 16px; font-weight: bold; margin: 0 0 5px 0;">🍽️ Meal Ready!</p> <p style="color: #ccc; font-size: 14px; margin: 0;">Your <<print $salamanderCookNotify>> has been added to your food inventory!</p> </div> <<set $salamanderCookNotify = false>> <</if>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <div style="width: 100%;"> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #e74c3c; margin-top: 5px;"> <p style="color: #ccc; font-size: 13px; margin: 0 0 8px 0;">🔥 Your inner fire lets you cook anywhere!</p> <<set _recipes = Object.keys(setup.recipes || {})>> <<if _recipes.length === 0>> <p style="color: #888; text-align: center;">No recipes available.</p> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; margin-bottom: 10px;"> <<for _recipeId, _recipe range setup.recipes>> <<set _canCook = true>> <<for _ingName, _ingAmount range _recipe.ingredients>> <<if !$kitchenInventory || !$kitchenInventory.ingredients || !$kitchenInventory.ingredients[_ingName] || $kitchenInventory.ingredients[_ingName] < _ingAmount>> <<set _canCook = false>> <</if>> <</for>> <div style="background: #2a1a0a; border: 1px solid <<if _canCook>>#e74c3c<<else>>#444<</if>>; border-radius: 8px; padding: 10px;"> <h4 style="color: <<if _canCook>>#e74c3c<<else>>#666<</if>>; margin: 0 0 5px 0; font-size: 14px;"><<print _recipe.name>></h4> <p style="color: #888; font-size: 12px; margin: 0 0 5px 0;"> <<for _ingName, _ingAmount range _recipe.ingredients>> <<set _have = ($kitchenInventory && $kitchenInventory.ingredients && $kitchenInventory.ingredients[_ingName]) ? $kitchenInventory.ingredients[_ingName] : 0>> <span style="color: <<if _have >= _ingAmount>>#51cf66<<else>>#ff6b6b<</if>>;"><<print _ingName>> (<<print _have>>/<<print _ingAmount>>)</span> <</for>> </p> <p style="color: #888; font-size: 11px; margin: 0 0 8px 0;">⏰ <<print _recipe.time>> min</p> <<if _canCook>> <<capture _recipeId, _recipe>> <<link "<div style='background: #e74c3c; color: white; padding: 6px; border-radius: 4px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>🔥 Cook</div>">> <<for _ingName, _ingAmount range _recipe.ingredients>> <<set $kitchenInventory.ingredients[_ingName] -= _ingAmount>> <</for>> <<set _buff = setup.getRandomFoodBuff(_recipe.cost || 10)>> <<set _buffDuration = (_recipe.time || 30) * 4>> <<if !$foodInventory>><<set $foodInventory = []>><</if>> <<run $foodInventory.push({name: _recipe.name, buffId: _buff.type, buffDuration: _buffDuration, buffStrength: _buff.strength})>> <<set $salamanderCookNotify = _recipe.name>> <<run advanceTime(_recipe.time)>> <<goto "Abilities">> <</link>> <</capture>> <<else>> <div style="background: #444; color: #888; padding: 6px; border-radius: 4px; text-align: center; font-size: 13px;">Missing ingredients</div> <</if>> </div> <</for>> </div> <</if>> </div> </div> </div> </div> <</if>> /* ===== WEREFOX LINE ===== */ <<if $physicalTraits.includes("Kitsune")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #9b59b6;"> <div style="color: #9b59b6; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Werefox → Kitsune</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<if $youkoHypnotizeUsedToday>> <div style="background: #444; color: #888; padding: 10px 20px; border-radius: 8px; font-weight: bold;">🦊 Hypnotize (Used Today)</div> <<else>> <div style="width: 100%;"> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #9b59b6; margin-top: 5px;"> <p style="color: #ccc; font-size: 13px; margin: 0 0 8px 0;">🦊 Select an NPC in your area to hypnotize. Once per day. Revna and Roisin will resist (-200 pts).</p> <<set _foundNPCs = false>> <<set _npcsHere = setup.getNPCsAtLocation($lastLocation)>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-bottom: 10px;"> <<for _i = 0; _i < _npcsHere.length; _i++>> <<set _npc = _npcsHere[_i]>> <<set _npcName = _npc.name>> <<set _rel = $relationships[_npcName]>> <<if _rel>> <<set _foundNPCs = true>> <<set _isResistant = (_npcName === "Revna McKraken" || _npcName === "Roisin Sullivan")>> <<capture _npcName, _rel, _isResistant>> <<link "<div style='background: #2a1a3a; border: 1px solid <<if _isResistant>>#ff6b6b<<else>>#9b59b6<</if>>; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer;'><p style='color: #9b59b6; font-weight: bold; margin: 0; font-size: 13px;'><<print _npcName>></p><p style='color: #888; font-size: 11px; margin: 2px 0 0 0;'>Lv: <<print _rel.level>><<if _isResistant>> <span style='color: #ff6b6b;'>(Resists)</span><</if>></p></div>">> <<set $youkoHypnotizeTarget = _npcName>> <<set $youkoHypnotizeStage = 1>> <<set $youkoHypnotizeChoices = []>> <<goto "KitsuneHypnotize">> <</link>> <</capture>> <</if>> <</for>> </div> <<if !_foundNPCs>> <p style="color: #888; font-size: 13px; text-align: center;">No NPCs are in your current area right now.</p> <</if>> </div> </div> <</if>> </div> </div> <</if>> <<if setup.slime.isPlayerSlimeBodied() || $slimePossessionActive>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #51e0a8;"> <div style="color: #51e0a8; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Slime</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #2bb583, #6effc0); color: #06281e; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(43,181,131,0.5);'>🫧 Slime Powers</div>">><<goto "SlimePanel">><</link>> </div> </div> <</if>> /* ===== OTHER ABILITIES ===== */ <<if $physicalTraits.includes("Honeybee") || $physicalTraits.includes("Dark Angel") || $physicalTraits.includes("Pharaoh")>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #aaa;"> <div style="color: #aaa; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Other Abilities</div> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<if $physicalTraits.includes("Honeybee")>> <<set _honeyCount = $honeyInventory || 0>> <<if _honeyCount > 0>> <<set _honeyBtnText = "<div style='background: linear-gradient(135deg, #f39c12, #e67e22); color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(243,156,18,0.5);'>🍯 Consume Honey (×" + _honeyCount + ")</div>">> <<link _honeyBtnText>> <<set $honeyInventory -= 1>> <<run setup.addBuff("honeybee_lustful", 180)>> <<goto "Abilities">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 10px 20px; border-radius: 8px; font-weight: bold;">🍯 Consume Honey (No Honey)</div> <</if>> <<if _honeyCount > 0 && ($emptyJars || 0) > 0>> <<set _jarBtnText = "<div style='background: linear-gradient(135deg, #daa520, #b8860b); color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(218,165,32,0.5);'>🫙 Jar Honey (×" + _honeyCount + " honey, ×" + ($emptyJars || 0) + " jars)</div>">> <<link _jarBtnText>> <<set $honeyInventory -= 1>> <<set $emptyJars -= 1>> <<set $jarredHoney = ($jarredHoney || 0) + 1>> <<goto "Abilities">> <</link>> <<elseif _honeyCount > 0 && ($emptyJars || 0) <= 0>> <div style="color: #888; font-style: italic; padding: 10px;">Need empty jars to bottle honey (sold at Grocery Store)</div> <</if>> <<if ($jarredHoney || 0) > 0>> <div style="color: #daa520; margin-top: 5px; padding: 5px 10px;">🫙 Jarred Honey: <<print $jarredHoney>></div> <</if>> /* Honey Milk Production */ <<set _hasLactating = $physicalTraits && $physicalTraits.includes("Lactating")>> <<if _hasLactating>> <div style="margin-top: 15px; padding-top: 15px; border-top: 1px solid #555;"> <div style="color: #f0c040; font-weight: bold; margin-bottom: 8px;">🍯🥛 Honey Milk</div> <<if $madeHoneyMilkToday>> <div style="color: #888; font-style: italic; padding: 10px;">You've already made honey milk today. Come back tomorrow.</div> <<elseif _honeyCount <= 0>> <div style="color: #888; font-style: italic; padding: 10px;">Need honey to make honey milk.</div> <<elseif ($milkInventory || 0) <= 0>> <div style="color: #888; font-style: italic; padding: 10px;">Need bottled milk to make honey milk.</div> <<elseif ($emptyBottles || 0) <= 0>> <div style="color: #888; font-style: italic; padding: 10px;">Need an empty bottle to store honey milk (sold at Grocery Store).</div> <<else>> <<set _hmBtnText = "<div style='background: linear-gradient(135deg, #f0c040, #e8a020); color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(240,192,64,0.5);'>🍯🥛 Make Honey Milk (1 honey + 1 milk + 1 bottle)</div>">> <<link _hmBtnText>> <<set $honeyInventory -= 1>> <<set $milkInventory -= 1>> <<set $emptyBottles -= 1>> <<set $honeyMilkInventory = ($honeyMilkInventory || 0) + 1>> <<set $madeHoneyMilkToday = true>> <<goto "Abilities">> <</link>> <</if>> <<if ($honeyMilkInventory || 0) > 0>> <div style="color: #f0c040; margin-top: 5px; padding: 5px 10px;">🍯🥛 Honey Milk: <<print $honeyMilkInventory>></div> <</if>> </div> <</if>> <</if>> <<if $physicalTraits.includes("Dark Angel")>> <div style="width: 100%;"> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #cc66ff; margin-top: 5px;"> <p style="color: #ccc; font-size: 13px; margin: 0 0 8px 0;">😈 Force NPCs who dislike you to swap traits. Select an NPC with negative relationship:</p> <<set _foundTargets = false>> <<set _npcsHere = setup.getNPCsAtLocation($lastLocation)>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin-bottom: 10px;"> <<for _i = 0; _i < _npcsHere.length; _i++>> <<set _npcData = _npcsHere[_i]>> <<set _npcName = _npcData.name>> <<set _rel = $relationships[_npcName]>> <<if _rel && _rel.level <= -1>> <<set _foundTargets = true>> <<capture _npcName, _npcData>> <<link "<div style='background: linear-gradient(135deg, #3a1a4a, #2a0a3a); border: 1px solid #cc66ff; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer;'><p style='color: #cc66ff; font-weight: bold; margin: 0; font-size: 13px;'><<print _npcName>></p><p style='color: #888; font-size: 11px; margin: 2px 0 0 0;'>Rel: <<print _rel.level>></p></div>">> <<set $darkAngelTarget = _npcName>> <<goto "DarkAngelSwapSelect">> <</link>> <</capture>> <</if>> <</for>> </div> <<if !_foundTargets>> <p style="color: #888; font-size: 13px; text-align: center;">No NPCs with negative relationships are in your current area.</p> <</if>> </div> </div> <</if>> <<if $physicalTraits.includes("Pharaoh")>> <div style="width: 100%;"> <div style="padding: 10px; background: #1a1a2e; border-radius: 8px; border: 1px solid #ffd700; margin-top: 5px;"> <p style="color: #ffd700; font-weight: bold; font-size: 14px; margin: 0 0 10px 0;">👑 Pharaoh's Divine Powers</p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px;"> /* Weather Control */ <div style="border: 1px solid #3498db; border-radius: 8px; padding: 10px; background: #2a2a2a;"> <h4 style="color: #3498db; margin: 0 0 5px 0; font-size: 13px;">🌤️ Weather Control</h4> <p style="color: #ccc; font-size: 12px; margin: 0 0 8px 0;">Current: <strong><<print $currentWeather>></strong></p> <div style="display: flex; gap: 6px; flex-wrap: wrap;"> <<link "<div style='background: #f1c40f; color: #1a1a1a; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>☀️ Clear</div>">><<set $currentWeather = "Clear">><<goto "Abilities">><</link>> <<link "<div style='background: #95a5a6; color: #1a1a1a; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>☁️ Cloudy</div>">><<set $currentWeather = "Cloudy">><<goto "Abilities">><</link>> <<link "<div style='background: #3498db; color: white; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>🌧️ Rainy</div>">><<set $currentWeather = "Rainy">><<goto "Abilities">><</link>> <<link "<div style='background: #e74c3c; color: white; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>⛈️ Stormy</div>">><<set $currentWeather = "Stormy">><<goto "Abilities">><</link>> </div> </div> /* Chest Size Control */ <div style="border: 1px solid #e056a0; border-radius: 8px; padding: 10px; background: #2a2a2a;"> <h4 style="color: #e056a0; margin: 0 0 5px 0; font-size: 13px;">👗 Chest Size</h4> <p style="color: #ccc; font-size: 12px; margin: 0 0 8px 0;">Current: <strong><<print $bodyParts.chest>></strong></p> <div style="display: flex; gap: 6px; flex-wrap: wrap;"> <<link "<div style='background: #e056a0; color: white; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>⬆ Increase</div>">> <<set _sizes = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx = _sizes.indexOf($bodyParts.chest)>> <<if _idx < _sizes.length - 1>><<set $bodyParts.chest = _sizes[_idx + 1]>><</if>> <<goto "Abilities">> <</link>> <<link "<div style='background: #c0448f; color: white; padding: 5px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>⬇ Decrease</div>">> <<set _sizes = ["flat", "flat masculine", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _idx = _sizes.indexOf($bodyParts.chest)>> <<if _idx > 0>><<set $bodyParts.chest = _sizes[_idx - 1]>><</if>> <<goto "Abilities">> <</link>> </div> </div> /* NPC Gender Change */ <div style="border: 1px solid #9b59b6; border-radius: 8px; padding: 10px; background: #2a2a2a;"> <h4 style="color: #9b59b6; margin: 0 0 5px 0; font-size: 13px;">🔄 Change NPC Gender</h4> <p style="color: #ccc; font-size: 12px; margin: 0 0 8px 0;">Toggle any NPC's gender.</p> <<link "<div style='background: #9b59b6; color: white; padding: 5px 10px; border-radius: 4px; text-align: center; cursor: pointer; font-weight: bold; font-size: 12px;'>Select NPC</div>">> <<set $pharaohGenderLocation = $lastLocation>> <<goto "PharaohGenderChange">> <</link>> </div> </div> </div> </div> <</if>> </div> </div> <</if>> </div> <!-- Angel Purify Results --> <<if $angelLastPurified && $angelLastPurified.length > 0>> <div style="background: linear-gradient(135deg, #4a3a1a 0%, #2a1a0a 100%); padding: 15px; border-radius: 10px; margin-top: 15px; border: 2px solid #ffd700; box-shadow: 0 0 20px rgba(255,215,0,0.3);"> <p style="color: #ffd700; font-weight: bold; margin: 0 0 5px 0;">😇 Purified! Removed:</p> <p style="color: #ffc107; margin: 0;"><<print $angelLastPurified.join(", ")>></p> </div> <<set $angelLastPurified = []>> <<elseif $angelLastPurified && $angelLastPurified.length === 0 && ($physicalTraits.includes("Angel") || $physicalTraits.includes("Cupid"))>> <div style="background: #2a2a2a; padding: 10px; border-radius: 8px; margin-top: 15px; border: 1px solid #51cf66;"> <p style="color: #51cf66; margin: 0; text-align: center;">✨ You are already pure. No negative traits found.</p> </div> <<set $angelLastPurified = undefined>> <</if>> </div> <!-- Back Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back</div>">> <<if $lastLocation && $lastLocation !== "Abilities">> <<goto $lastLocation>> <<else>> <<goto "Body">> <</if>> <</link>> </div> </div> <</nobr>>
<<nobr>> /* RaijuEncounter - multi-stage electric sex scene */ <<set _npcName = $raijuLastTarget>> <<set _npcData = $npcs.find(function(n) { return n.name === _npcName; })>> <<set _npcGender = (_npcData && _npcData.bodyParts && _npcData.bodyParts.gender) ? _npcData.bodyParts.gender : "male">> <<set _npcPronoun = (_npcGender === "female") ? "she" : "he">> <<set _npcPronounObj = (_npcGender === "female") ? "her" : "him">> <<set _npcPronounPos = (_npcGender === "female") ? "her" : "his">> <<set _npcPronounCap = (_npcGender === "female") ? "She" : "He">> <<set _npcChest = (_npcData && _npcData.bodyParts && _npcData.bodyParts.chest) ? _npcData.bodyParts.chest : "flat">> <<set _npcButt = (_npcData && _npcData.bodyParts && _npcData.bodyParts.butt) ? _npcData.bodyParts.butt : "small">> <<set _npcGenitals = (_npcData && _npcData.bodyParts && _npcData.bodyParts.genitals) ? _npcData.bodyParts.genitals : "penis">> <<set _npcHasVagina = (_npcGenitals === "vagina" || _npcGenitals === "tight vagina" || _npcGenitals === "loose vagina")>> <<set _npcHasPenis = (_npcGenitals === "penis" || _npcGenitals === "big penis" || _npcGenitals === "small penis")>> <<set _npcHasBreasts = (_npcChest !== "flat" && _npcChest !== "flat masculine")>> <!-- Player trait checks --> <<set _isDominant = $mentalTraits.includes("Dominant")>> <<set _isSubmissive = $mentalTraits.includes("Submissive")>> <<set _isFlirty = $mentalTraits.includes("Flirty")>> <<set _isAwkward = $mentalTraits.includes("Awkward")>> <<set _isConfident = $mentalTraits.includes("Confident")>> <<set _isKind = $mentalTraits.includes("Kind")>> <<set _isBitchy = $mentalTraits.includes("Bitchy")>> <<set _isEnergetic = $mentalTraits.includes("Energetic")>> <!-- Body part checks --> <<set _hasVagina = ($bodyParts && ($bodyParts.genitals === "vagina" || $bodyParts.genitals === "tight vagina" || $bodyParts.genitals === "loose vagina"))>> <<set _hasPenis = ($bodyParts && ($bodyParts.genitals === "penis" || $bodyParts.genitals === "big penis" || $bodyParts.genitals === "small penis"))>> <<set _chestSize = ($bodyParts && $bodyParts.chest) ? $bodyParts.chest : "flat">> <<set _buttSize = ($bodyParts && $bodyParts.butt) ? $bodyParts.butt : "flat">> <<set _playerGenitals = ($bodyParts && $bodyParts.genitals) ? $bodyParts.genitals : "penis">> <<set _hasMediumBreasts = (_chestSize === "medium" || _chestSize === "large" || _chestSize === "huge" || _chestSize === "giant" || _chestSize === "gigantic")>> <<set _hasLargeBreasts = (_chestSize === "large" || _chestSize === "huge" || _chestSize === "giant" || _chestSize === "gigantic")>> <<set _hasHugeBreasts = (_chestSize === "huge" || _chestSize === "giant" || _chestSize === "gigantic")>> <<set _hasLargeButt = (_buttSize === "large" || _buttSize === "huge" || _buttSize === "giant" || _buttSize === "gigantic")>> <<set _hasHugeButt = (_buttSize === "huge" || _buttSize === "giant" || _buttSize === "gigantic")>> <<set _playerChestDesc = (_chestSize === "gigantic") ? "gigantic" : (_chestSize === "giant") ? "massive" : (_chestSize === "huge") ? "huge" : (_chestSize === "large") ? "large" : (_chestSize === "medium") ? "full" : (_chestSize === "small") ? "small" : "flat">> <<set _playerButtDesc = (_buttSize === "gigantic") ? "gigantic" : (_buttSize === "giant") ? "massive" : (_buttSize === "huge") ? "huge" : (_buttSize === "large") ? "large" : (_buttSize === "medium") ? "round" : (_buttSize === "small") ? "small" : "flat">> <<set _npcChestDesc = (_npcChest === "gigantic") ? "gigantic" : (_npcChest === "giant") ? "massive" : (_npcChest === "huge") ? "huge" : (_npcChest === "large") ? "large" : (_npcChest === "medium") ? "full" : (_npcChest === "small") ? "small" : "flat">> <<set _npcButtDesc = (_npcButt === "gigantic") ? "gigantic" : (_npcButt === "giant") ? "massive" : (_npcButt === "huge") ? "huge" : (_npcButt === "large") ? "large" : (_npcButt === "medium") ? "round" : (_npcButt === "small") ? "small" : "flat">> <<set _playerBigPenis = (_playerGenitals === "big penis")>> <<set _playerSmallPenis = (_playerGenitals === "small penis")>> <<set _npcBigPenis = (_npcGenitals === "big penis")>> <<set _npcSmallPenis = (_npcGenitals === "small penis")>> <div style="background: linear-gradient(180deg, #1a1a0a 0%, #0a0a00 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 700px; margin: 0 auto;"> <h1 style="color: #f1c40f; text-align: center; text-shadow: 0 0 20px rgba(241,196,15,0.8); margin-bottom: 5px;">⚡ Raiju Encounter ⚡</h1> <p style="color: #888; text-align: center; margin: 0 0 20px 0;">with <<print _npcName>></p> <!-- Stage indicator --> <div style="display: flex; justify-content: center; gap: 8px; margin-bottom: 25px;"> <div style="width: 40px; height: 4px; border-radius: 2px; background: <<if $raijuEncounterStage >= 1>>#f1c40f<<else>>#333<</if>>;"></div> <div style="width: 40px; height: 4px; border-radius: 2px; background: <<if $raijuEncounterStage >= 2>>#f1c40f<<else>>#333<</if>>;"></div> <div style="width: 40px; height: 4px; border-radius: 2px; background: <<if $raijuEncounterStage >= 3>>#f1c40f<<else>>#333<</if>>;"></div> <div style="width: 40px; height: 4px; border-radius: 2px; background: <<if $raijuEncounterStage >= 4>>#f1c40f<<else>>#333<</if>>;"></div> </div> /* ======================== STAGE 1: APPROACH ======================== */ <<if $raijuEncounterStage === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a0a 0%, #1a1a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f1c40f;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _npcGender === "male">> Your skin prickles with static as you spot <<print _npcName>> nearby. The Raiju instinct rises in your blood like a building charge — raw, electric need that makes your fingertips spark and your breath quicken. <<print _npcPronoun.toUpperCase()>> notices the faint golden glow around your skin and <<print _npcPronounPos>> eyes widen slightly, a mix of wariness and fascination crossing <<print _npcPronounPos>> face. <<else>> Your skin prickles with static as you spot <<print _npcName>> nearby. The Raiju instinct rises in your blood like a building charge — raw, electric need that makes your fingertips spark and your breath quicken. She notices the faint golden glow dancing across your skin and her eyes widen, a flush creeping up her neck as she senses the crackling energy radiating from you. <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f1c40f;"> <h2 style="color: #f1c40f; margin: 0 0 15px 0;">How do you approach?</h2> <div style="display: grid; gap: 15px;"> <!-- Aggressive Charge --> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>⚡ Aggressive Charge</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isDominant>>Pin them down with crackling authority<<elseif _isConfident>>Strike with electric confidence<<elseif _isBitchy>>Demanding, sparking with impatience<<else>>Surge forward, electricity blazing<</if>></span></div>">> <<set $raijuEncounterChoices.push("dominant")>> <<set $raijuEncounterStage = 2>> <<goto "RaijuEncounter">> <</link>> <!-- Seductive Spark --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>✨ Seductive Spark</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isFlirty>>Expert teasing, trailing sparks along their skin<<elseif _isKind>>Gentle touches that leave tingling warmth<<elseif _isAwkward>>Shy sparks, blushing but drawn to them<<else>>Slow, deliberate touches that crackle with static<</if>></span></div>">> <<set $raijuEncounterChoices.push("seductive")>> <<set $raijuEncounterStage = 2>> <<goto "RaijuEncounter">> <</link>> <!-- Playful Shock --> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #9b59b6;'>🎭 Playful Shock</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isEnergetic>>Bouncing with electric excitement, zapping them playfully<<elseif _isFlirty>>Mischievous little shocks, daring them to react<<elseif _isAwkward>>Accidentally zapping them, then giggling nervously<<else>>Teasing sparks and flirty zaps<</if>></span></div>">> <<set $raijuEncounterChoices.push("playful")>> <<set $raijuEncounterStage = 2>> <<goto "RaijuEncounter">> <</link>> <!-- Overwhelming Surge --> <<link "<div style='background: #1a1a1a; border: 2px solid #f1c40f; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #f1c40f;'>🌩️ Overwhelming Surge</strong><br><span style='color: #aaa; font-size: 14px;'><<if _isSubmissive>>Lose control to the primal current, overwhelmed by need<<elseif _isDominant>>Channel raw power, barely contained<<else>>Let the electricity take over completely<</if>></span></div>">> <<set $raijuEncounterChoices.push("overwhelming")>> <<set $raijuEncounterStage = 2>> <<goto "RaijuEncounter">> <</link>> </div> </div> /* ======================== STAGE 2: THE ACT ======================== */ <<elseif $raijuEncounterStage === 2>> <!-- Scene text based on Stage 1 choice --> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a0a 0%, #1a1a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f1c40f;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $raijuEncounterChoices[0] === "dominant">> <<if _npcGender === "male">> You close the distance in a heartbeat, electricity crackling around your body like a golden aura. Your hand shoots out, grabbing <<print _npcName>> by the collar and pulling <<print _npcPronounObj>> close. The shock of contact makes <<print _npcPronounObj>> gasp, <<print _npcPronounPos>> muscles tensing under the current. "You're mine right now," you growl against <<print _npcPronounPos>> ear, sparks dancing from your lips. <<print _npcPronoun.toUpperCase()>> shudders, resistance crumbling as the electricity turns <<print _npcPronounPos>> knees weak. <<else>> You close the distance in a heartbeat, electricity crackling around your body like a golden aura. Your hand finds the back of <<print _npcName>>'s neck, pulling her close. The shock of contact makes her gasp, her whole body trembling under the current. "You're mine right now," you whisper against her ear, sparks dancing from your lips to her skin. She whimpers, her hands gripping your arms as her resistance melts under the electric onslaught. <</if>> <<elseif $raijuEncounterChoices[0] === "seductive">> <<if _npcGender === "male">> You approach slowly, deliberately, letting the static build between you with every step. Your fingertips trail along <<print _npcName>>'s arm, leaving a tingling wake of golden sparks. <<print _npcPronoun.toUpperCase()>> inhales sharply, skin prickling with goosebumps. You press your body against <<print _npcPronounPos>>, <<if _hasMediumBreasts>>your <<print _playerChestDesc>> breasts pressing into <<print _npcPronounPos>> chest, <</if>>feeling the electricity arc between every point of contact. "Feel that?" you murmur, your lips brushing <<print _npcPronounPos>> jaw. <<print _npcPronoun.toUpperCase()>> nods, already breathless, hands finding your <<if _hasLargeButt>><<print _playerButtDesc>> <</if>>waist. <<else>> You approach slowly, deliberately, letting the static build between you with every step. Your fingertips trail along <<print _npcName>>'s arm, leaving a tingling wake of golden sparks. She inhales sharply, goosebumps rising across her skin. You lean in close, <<if _hasMediumBreasts>>pressing your <<print _playerChestDesc>> breasts against her, <</if>>your lips finding her neck, feeling the electricity arc between your mouth and her pulse point. "Feel that?" you whisper. She shivers, nodding, her hands rising to grip your <<if _hasLargeButt>><<print _playerButtDesc>> hips<<else>>shoulders<</if>> as the current flows between you. <</if>> <<elseif $raijuEncounterChoices[0] === "playful">> <<if _npcGender === "male">> You grin mischievously and press your finger to <<print _npcName>>'s chest — zap! A spark jumps between you and <<print _npcPronoun>> flinches, then laughs. "Oh, you think that's funny?" you tease, sending another spark along <<print _npcPronounPos>> collarbone. <<print _npcPronoun.toUpperCase()>> grabs your wrist, pulling you closer, and the contact sends a cascade of electricity through you both. The playful mood shifts into something hungrier as your bodies press together, sparks flying where skin meets skin. <<else>> You grin mischievously and press your finger to <<print _npcName>>'s collarbone — zap! A spark jumps between you and she squeaks, then laughs breathlessly. "Oh you liked that?" you tease, trailing another spark down her arm. She grabs your hand, pulling you closer, and the contact sends a cascade of electricity through you both. The playfulness shifts into something hungrier as your bodies press together, sparks dancing everywhere skin meets skin. <</if>> <<else>> <<if _npcGender === "male">> The electricity overwhelms your control. Your whole body lights up gold, arcs of lightning jumping from your skin to anything nearby. <<print _npcName>> barely has time to react before you crash into <<print _npcPronounObj>>, the full force of your electric charge surging between your bodies. <<print _npcPronoun.toUpperCase()>> gasps, caught in the current, <<print _npcPronounPos>> body pressed flush against yours<<if _hasMediumBreasts>>, your <<print _playerChestDesc>> breasts crushed between you<</if>> as the electricity binds you together. Every nerve ending is on fire. You can't think — only feel the crackling, consuming need. <<else>> The electricity overwhelms your control. Your whole body lights up gold, arcs of lightning jumping from your skin to everything nearby. <<print _npcName>> barely has time to react before you crash into her, the full force of your electric charge surging between your bodies. She gasps, caught in the current, her <<if _npcHasBreasts>><<print _npcChestDesc>> breasts pressing<<else>>body pressed flush<</if>> against yours<<if _hasMediumBreasts>>, your <<print _playerChestDesc>> breasts crushed between you<</if>> as the electricity binds you together. Every nerve ending is on fire. You can't think — only feel the crackling, consuming need pulsing through every inch of you. <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f1c40f;"> <h2 style="color: #f1c40f; margin: 0 0 15px 0;">What do you want?</h2> <div style="display: grid; gap: 15px;"> <!-- Electrified Oral (always available) --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>👅 Electrified Oral</strong><br><span style='color: #aaa; font-size: 14px;'>Your sparking tongue and tingling lips on their most sensitive areas</span></div>">> <<set $raijuEncounterChoices.push("oral")>> <<set $raijuEncounterStage = 3>> <<goto "RaijuEncounter">> <</link>> <!-- Riding the Lightning (vagina only) --> <<if _hasVagina>> <<link "<div style='background: #1a1a1a; border: 2px solid #f1c40f; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #f1c40f;'>🔥 Riding the Lightning</strong><br><span style='color: #aaa; font-size: 14px;'>Take them inside you, electricity flowing through your core</span></div>">> <<set $raijuEncounterChoices.push("vaginal")>> <<set $raijuEncounterStage = 3>> <<goto "RaijuEncounter">> <</link>> <</if>> <!-- Thunderstrike (penis only) --> <<if _hasPenis>> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>⚡ Thunderstrike</strong><br><span style='color: #aaa; font-size: 14px;'>Penetrate them with your electrically charged body</span></div>">> <<set $raijuEncounterChoices.push("penetrate")>> <<set $raijuEncounterStage = 3>> <<goto "RaijuEncounter">> <</link>> <</if>> <!-- Charged Hands (always available) --> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>✋ Charged Hands</strong><br><span style='color: #aaa; font-size: 14px;'>Explore every inch of them with tingling, electric fingers</span></div>">> <<set $raijuEncounterChoices.push("hands")>> <<set $raijuEncounterStage = 3>> <<goto "RaijuEncounter">> <</link>> <!-- Shock & Worship (medium+ breasts) --> <<if _hasMediumBreasts>> <<link "<div style='background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ffc107;'>💋 Shock & Worship</strong><br><span style='color: #aaa; font-size: 14px;'>Electrified breast play, smother them with sparking warmth</span></div>">> <<set $raijuEncounterChoices.push("breasts")>> <<set $raijuEncounterStage = 3>> <<goto "RaijuEncounter">> <</link>> <</if>> <!-- Electric Boob Job (medium+ breasts, male NPC with penis) --> <<if _hasMediumBreasts && _npcGender === "male" && _npcHasPenis>> <<link "<div style='background: #1a1a1a; border: 2px solid #c71585; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #c71585;'>⚡ Electric Boob Job</strong><br><span style='color: #aaa; font-size: 14px;'>Squeeze him between your sparking breasts, voltage building with every stroke</span></div>">> <<set $raijuEncounterChoices.push("boobjob")>> <<set $raijuEncounterStage = 3>> <<goto "RaijuEncounter">> <</link>> <</if>> </div> </div> /* ======================== STAGE 3: ENHANCEMENT ======================== */ <<elseif $raijuEncounterStage === 3>> <!-- Scene text based on Stage 2 choice --> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a0a 0%, #1a1a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f1c40f;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $raijuEncounterChoices[1] === "oral">> <<if _npcGender === "male">> <<if _npcHasPenis>>You drop to your knees, looking up at <<print _npcName>> with crackling golden eyes. Your tongue traces up <<print _npcPronounPos>> <<if _npcBigPenis>>impressive <</if>>length, tiny sparks jumping from your lips at every point of contact. <<print _npcPronoun.toUpperCase()>> groans, hands fisting in your hair, as the electric tingling sensation spreads from your mouth through <<print _npcPronounPos>> entire body. You take <<print _npcPronounObj>> deeper, your throat humming with current, every swirl of your tongue sending jolts of pleasure that make <<print _npcPronounPos>> legs shake.<<else>>You push <<print _npcName>> back and sink between <<print _npcPronounPos>> thighs, your lips trailing sparks along <<print _npcPronounPos>> inner legs. Your tongue finds <<print _npcPronounPos>> center and <<print _npcPronoun>> cries out at the first electric contact — a tingling warmth that pulses through <<print _npcPronounPos>> most sensitive nerves. You work <<print _npcPronounObj>> expertly, each lick sending golden sparks dancing across <<print _npcPronounPos>> skin. <<print _npcPronoun.toUpperCase()>> grips your hair, <<print _npcPronounPos>> <<print _npcButtDesc>> thighs trembling around your head as the electricity builds and builds.<</if>> <<else>> <<if _npcHasPenis>>You drop to your knees before <<print _npcName>>, looking up with crackling golden eyes. Your sparking tongue traces along her <<if _npcBigPenis>>impressive <</if>>length, making her gasp at every point of contact. You take her deeper, your throat humming with current, every swirl of your tongue sending jolts of electric pleasure through her body. Her hands fist in your hair, legs trembling as the tingling sensation builds and builds.<<else>>You guide <<print _npcName>> back against the wall and sink between her thighs, your lips trailing sparks along her inner legs. Your tongue finds her center and she cries out at the first electric contact — a tingling warmth that pulses through her most sensitive nerves. You work her expertly, each lick sending golden sparks dancing across her skin. Her hands grip your hair, her <<print _npcButtDesc>> thighs trembling around your head as the electricity builds and builds, making every touch ten times more intense.<</if>> <</if>> <<elseif $raijuEncounterChoices[1] === "vaginal">> <<if _npcGender === "male">> <<if _npcHasPenis>>You push <<print _npcName>> down and straddle <<print _npcPronounObj>>, the electricity between your bodies making both of you gasp as you lower yourself onto <<print _npcPronounObj>>. The sensation is extraordinary — your inner walls pulse with electrical current, gripping and tingling around <<print _npcPronounPos>> <<if _npcBigPenis>>thick <</if>>length. <<print _npcPronoun.toUpperCase()>> arches beneath you, <<print _npcPronounPos>> hands gripping your <<if _hasLargeButt>><<print _playerButtDesc>> hips<<else>>hips<</if>>, overwhelmed, as you begin to move. Each roll of your <<if _hasLargeButt>><<print _playerButtDesc>> <</if>>hips sends a surge of lightning through your core, golden sparks showering from where your bodies connect.<<else>>You pull <<print _npcName>> close, guiding <<print _npcPronounPos>> hand between your thighs. The electricity in your body focuses there, pulsing, aching. As <<print _npcPronounPos>> fingers slide inside you, the current wraps around them, making <<print _npcPronounObj>> gasp. You moan, your <<if _hasLargeButt>><<print _playerButtDesc>> <</if>>hips rocking against <<print _npcPronounPos>> hand, each movement sending cascades of golden sparks through your core. The electricity amplifies every sensation tenfold.<</if>> <<else>> <<if _npcHasPenis>>You push <<print _npcName>> down and straddle her, the electricity crackling between your bodies as you lower yourself onto her<<if _npcBigPenis>> impressive length<</if>>. The sensation is extraordinary — your inner walls pulse with electrical current. She arches beneath you, her hands gripping your <<if _hasLargeButt>><<print _playerButtDesc>> hips<<else>>hips<</if>>, overwhelmed, as you begin to move. Each roll of your <<if _hasLargeButt>><<print _playerButtDesc>> <</if>>hips sends a surge of lightning through your core, golden sparks showering from where your bodies connect.<<else>>You pull <<print _npcName>> close, guiding her hand between your thighs. The electricity in your body focuses there, pulsing, aching. As her fingers slide inside you, the current wraps around them, making her gasp. You moan, your <<if _hasLargeButt>><<print _playerButtDesc>> <</if>>hips rocking against her hand, each movement sending cascades of golden sparks through your core. The electricity amplifies every sensation tenfold — every curl of her fingers, every brush of her palm sends lightning bolting up your spine.<</if>> <</if>> <<elseif $raijuEncounterChoices[1] === "penetrate">> <<if _npcGender === "male">> You press <<print _npcName>> against the wall, electricity surging through your body as you push inside <<print _npcPronounObj>>. The current flows through your <<if _playerBigPenis>>thick <</if>>cock in pulsing waves, each thrust sending shockwaves of electrified pleasure through <<print _npcPronounPos>> body. <<print _npcPronoun.toUpperCase()>> cries out, <<if _npcHasBreasts>><<print _npcPronounPos>> <<print _npcChestDesc>> breasts pressed against your chest, <</if>>gripping your shoulders as the lightning-laced penetration overwhelms <<print _npcPronounPos>> senses. <<if _playerBigPenis>><<print _npcPronoun.toUpperCase()>> gasps at your size as golden arcs dance between your bodies with every deep stroke.<<else>>Golden arcs dance between your bodies with every deep stroke.<</if>> <<else>> You guide <<print _npcName>> onto her back, spreading her legs as electricity crackles along your <<if _playerBigPenis>>thick <</if>>length. As you push inside her, the current flows in pulsing waves, each thrust sending shockwaves through her body. She cries out, <<if _npcHasBreasts>>her <<print _npcChestDesc>> breasts bouncing with each thrust, <</if>>back arching off the surface, hands clawing at anything she can reach. The electricity makes every nerve ending sing, golden arcs dancing between your bodies as you <<if _playerBigPenis>>stretch her open and <</if>>drive deeper, the lightning amplifying every sensation to an almost unbearable intensity. <</if>> <<elseif $raijuEncounterChoices[1] === "hands">> <<if _npcGender === "male">> Your electrically charged hands explore <<print _npcName>>'s body, each fingertip leaving a trail of tingling golden sparks. <<if _npcHasPenis>>You wrap your hand around <<print _npcPronounPos>> <<if _npcBigPenis>>impressive <</if>>length, the current pulsing from your palm in rhythmic waves. <<print _npcPronoun.toUpperCase()>> groans, head falling back, as your charged grip sends jolts of pleasure through <<print _npcPronounPos>> most sensitive areas.<<else>>Your fingers slip between <<print _npcPronounPos>> thighs, the current pulsing from your fingertips in rhythmic waves. <<print _npcPronoun.toUpperCase()>> groans, head falling back, as your charged touch sends jolts of pleasure through <<print _npcPronounPos>> most sensitive areas.<</if>> Your other hand explores <<print _npcPronounPos>> <<if _npcHasBreasts>><<print _npcChestDesc>> breasts<<else>>chest<</if>>, <<print _npcPronounPos>> <<print _npcButtDesc>> ass, <<print _npcPronounPos>> thighs — everywhere you touch lights up with crackling golden energy. <<else>> Your electrically charged hands explore <<print _npcName>>'s body, each fingertip leaving a trail of tingling golden sparks across her skin. <<if _npcHasBreasts>>You cup her <<print _npcChestDesc>> breast with one hand while the other <<else>>One hand traces across her chest while the other <</if>><<if _npcHasVagina>>slides between her thighs, electric fingers finding her most sensitive spots.<<else>>wraps around her <<if _npcBigPenis>>impressive <</if>>length, electric fingers tingling along every inch.<</if>> She gasps, arching into your touch as the current pulses from your fingertips in rhythmic waves. Your other hand grabs her <<print _npcButtDesc>> ass, sparks jumping at every squeeze. Every caress sends jolts of pleasure through her body — your charged touch turning simple contact into something extraordinary. <</if>> <<elseif $raijuEncounterChoices[1] === "breasts">> <<if _npcGender === "male">> You press your <<print _playerChestDesc>> chest against <<print _npcName>>'s face, electricity crackling across your <<if _hasHugeBreasts>>massive <<elseif _hasLargeBreasts>>ample <</if>>breasts as you smother <<print _npcPronounObj>> in sparking warmth. <<print _npcPronoun.toUpperCase()>> groans into your <<if _hasHugeBreasts>>overwhelming <</if>>cleavage, the current tingling across <<print _npcPronounPos>> lips and tongue as <<print _npcPronoun>> worships your charged flesh. You moan, running your fingers through <<print _npcPronounPos>> hair, sending sparks cascading down <<print _npcPronounPos>> scalp. The electricity flows between your nipples and <<print _npcPronounPos>> mouth in golden arcs, each pulse of pleasure building on the last. <<else>> You guide <<print _npcName>>'s mouth to your <<print _playerChestDesc>> chest, electricity crackling across your <<if _hasHugeBreasts>>massive <<elseif _hasLargeBreasts>>ample <</if>>breasts as she takes your nipple between her lips. The current arcs from your skin to her tongue, making her moan against your flesh. She worships your charged breasts eagerly, hands kneading the sparking <<if _hasHugeBreasts>>heavy <</if>>mounds as golden light pulses with every touch. You gasp, arching into her mouth, the electric feedback loop between her lips and your tingling skin building to an almost unbearable intensity. <</if>> <<elseif $raijuEncounterChoices[1] === "boobjob">> <div style="text-align: center; margin: 0 auto 15px; max-width: 600px;"><img src="Images/Jobs/Prostitute/RaijuBoobJob.webp" alt="Raiju boob job" style="max-width: 100%; height: auto; border-radius: 12px; border: 2px solid #f1c40f; box-shadow: 0 0 25px rgba(241,196,15,0.4);" /></div> <<if _npcHasBreasts>>Forget the bed.<</if>> You guide <<print _npcName>> back against the wall and drop to your knees in front of <<print _npcPronounObj>>, golden static crackling around your <<print _playerChestDesc>> chest. <<print _npcPronoun.toUpperCase()>> looks down at you and forgets how to breathe, <<print _npcPronounPos>> <<if _npcBigPenis>>thick <</if>>cock already straining where you want it. You wrap your breasts around <<print _npcPronounObj>> without breaking eye contact, squeezing yourself tight, and the first contact lights up like a struck match. Sparks jump between your nipples and <<print _npcPronounPos>> stomach. <<print _npcPronoun.toUpperCase()>> groans a sound that has no shape to it.<br><br>You start with slow strokes, letting <<print _npcPronounObj>> feel every pulse of current pour from your skin into the most sensitive part of <<print _npcPronounObj>>. On the upstroke your tongue flicks out to catch the head, golden sparks dancing from the tip of it, and <<print _npcPronounPos>> hips jerk forward involuntarily. <<if _hasHugeBreasts>>Your massive breasts swallow <<print _npcPronounObj>> almost entirely, only the head visible on every pass.<<elseif _hasLargeBreasts>>Your ample breasts wrap around <<print _npcPronounObj>> perfectly, pillowing <<print _npcPronounPos>> length in soft, charged flesh.<<else>>You squeeze yourself together, creating a tight channel of electrified warmth that has <<print _npcPronounObj>> gasping.<</if>> "Watch," you murmur, voice low and crackling. <<print _npcPronoun.toUpperCase()>> cannot do anything else.<br><br>You can feel <<print _npcPronounPos>> heartbeat through your palms where you hold yourself pressed together. You sync the pulses of voltage to it, then start ramping faster, pulling <<print _npcPronounPos>> pulse up with the rhythm. The sparks between your bodies grow brighter, tiny visible lightning arcing where skin meets cock. The smell of ozone curls up around you both. <<print _npcPronoun.toUpperCase()>> tries to say your name and the word comes out shorted, vowels stretched, a sound more electric than human. <<print _npcPronounPos>> thighs are shaking. The voltage in your chest spikes hot. You squeeze tighter, and the current you have been feeding <<print _npcPronounObj>> snaps back through both your bodies in a feedback loop that has you both gasping. <<print _npcPronoun.toUpperCase()>> is gone. The only thing keeping <<print _npcPronounObj>> standing is your breasts and the wall. <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f1c40f;"> <h2 style="color: #f1c40f; margin: 0 0 15px 0;">Intensify the experience...</h2> <div style="display: grid; gap: 15px;"> <!-- Voltage Surge --> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ff6b6b;'>🔋 Voltage Surge</strong><br><span style='color: #aaa; font-size: 14px;'>Crank the power up — rough, overwhelming electric pleasure</span></div>">> <<set $raijuEncounterChoices.push("voltageSurge")>> <<set $raijuEncounterStage = 4>> <<goto "RaijuEncounter">> <</link>> <!-- Slow Discharge --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>⏳ Slow Discharge</strong><br><span style='color: #aaa; font-size: 14px;'>Sensual, drawn-out buildup — let the charge accumulate slowly</span></div>">> <<set $raijuEncounterChoices.push("slowDischarge")>> <<set $raijuEncounterStage = 4>> <<goto "RaijuEncounter">> <</link>> <!-- Lightning Domination --> <<link "<div style='background: #1a1a1a; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #ffc107;'>👑 Lightning Domination</strong><br><span style='color: #aaa; font-size: 14px;'>Take total control — command them with electric authority</span></div>">> <<set $raijuEncounterChoices.push("lightningDom")>> <<set $raijuEncounterStage = 4>> <<goto "RaijuEncounter">> <</link>> <!-- Shared Circuit --> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>🔄 Shared Circuit</strong><br><span style='color: #aaa; font-size: 14px;'>Synchronize your electricity — feel what they feel</span></div>">> <<set $raijuEncounterChoices.push("sharedCircuit")>> <<set $raijuEncounterStage = 4>> <<goto "RaijuEncounter">> <</link>> </div> </div> /* ======================== STAGE 4: CLIMAX ======================== */ <<elseif $raijuEncounterStage === 4>> <!-- Enhancement scene text --> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a0a 0%, #1a1a00 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f1c40f;"> <p style="color: #eee; font-size: 16px; line-height: 1.8; margin: 0;"> <<if $raijuEncounterChoices[2] === "voltageSurge">> <<if _npcGender === "male">> You crank your power up to dangerous levels. The electricity surging from your body doubles, triples in intensity. <<print _npcName>> cries out, <<print _npcPronounPos>> body arching against yours as the voltage overwhelms <<print _npcPronounPos>> senses. It's rough, raw, primal — the lightning stripping away everything except the pure, burning pleasure. Your movements become faster, harder, each surge of electricity tearing gasps and moans from both of you. The air crackles, ozone thick in your lungs, as the relentless current drives you both toward the edge. <<else>> You crank your power up to dangerous levels. The electricity surging from your body doubles, triples in intensity. <<print _npcName>> screams, her body convulsing against yours as the voltage overwhelms her senses. It's rough, raw, primal — the lightning stripping away everything except pure, burning pleasure. Your movements become faster, harder, each surge of electricity tearing gasps from her lips. The air crackles with ozone as the relentless current drives you both toward the edge. <</if>> <<elseif $raijuEncounterChoices[2] === "slowDischarge">> <<if _npcGender === "male">> You slow everything down, letting the charge accumulate between your bodies in agonizing waves. Each tiny movement sends a slow pulse of electricity through <<print _npcName>>, making <<print _npcPronounObj>> whimper with frustrated need. You hold <<print _npcPronounObj>> on the edge, building the charge higher and higher, your own body trembling with the effort of holding back. The golden light between you grows brighter with each passing minute, the accumulated electricity becoming a living thing that pulses in time with your synchronized heartbeats. <<else>> You slow everything down, letting the charge accumulate between your bodies in agonizing waves. Each tiny movement sends a slow pulse of electricity through <<print _npcName>>, making her whimper with frustrated need. You hold her on the edge, building the charge higher and higher, your own body trembling with the effort of holding back. The golden light between you grows brighter with each passing minute, the accumulated electricity becoming a living thing pulsing in time with your synchronized heartbeats. <</if>> <<elseif $raijuEncounterChoices[2] === "lightningDom">> <<if _npcGender === "male">> You seize control completely, your electric power pinning <<print _npcName>> in place. Lightning arcs from your hands to <<print _npcPronounPos>> wrists, holding <<print _npcPronounObj>> where you want <<print _npcPronounObj>>. "Don't move," you command, and the electricity enforces your will, tingling across <<print _npcPronounPos>> skin every time <<print _npcPronoun>> tries to shift. You control the pace, the intensity, everything — using your body and your electric power to reduce <<print _npcPronounObj>> to a trembling, moaning mess beneath you. <<else>> You seize control completely, your electric power pinning <<print _npcName>> in place. Lightning arcs from your hands to her wrists, holding her exactly where you want her. "Don't move," you command, and the electricity enforces your will, tingling across her skin every time she tries to shift. You control the pace, the intensity, everything — using your body and your electric power to reduce her to a trembling, whimpering mess beneath you, begging for release. <</if>> <<else>> <<if _npcGender === "male">> You open the circuit fully, letting the electricity flow freely between your bodies. Suddenly you can feel what <<print _npcName>> feels — <<print _npcPronounPos>> pleasure becomes yours, yours becomes <<print _npcPronounPos>>. Every sensation doubles, echoing back and forth through the electric link. <<print _npcPronoun.toUpperCase()>> gasps, overwhelmed by the sudden intimacy of it, feeling your pleasure layered on top of <<print _npcPronounPos>> own. You move together in perfect sync, each wave of ecstasy amplifying the next in an endless feedback loop. <<else>> You open the circuit fully, letting the electricity flow freely between your bodies. Suddenly you can feel what <<print _npcName>> feels — her pleasure becomes yours, yours becomes hers. Every sensation doubles, echoing back and forth through the electric link. She gasps, overwhelmed by the sudden intimacy, feeling your pleasure layered on her own. You move together in perfect sync, each wave of ecstasy amplifying the next in an endless feedback loop of shared sensation. <</if>> <</if>> </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f1c40f;"> <h2 style="color: #f1c40f; margin: 0 0 15px 0;">The finale...</h2> <div style="display: grid; gap: 15px;"> <!-- Full Discharge --> <<link "<div style='background: #1a1a1a; border: 2px solid #f1c40f; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #f1c40f;'>⚡ Full Discharge</strong><br><span style='color: #aaa; font-size: 14px;'>Release everything at once — one explosive, devastating electrical orgasm</span></div>">> <<set $raijuEncounterChoices.push("fullDischarge")>> <<goto "RaijuEncounterResult">> <</link>> <!-- Chain Lightning --> <<link "<div style='background: #1a1a1a; border: 2px solid #e91e63; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #e91e63;'>🔗 Chain Lightning</strong><br><span style='color: #aaa; font-size: 14px;'>Wave after wave — let the current bounce back and forth endlessly</span></div>">> <<set $raijuEncounterChoices.push("chainLightning")>> <<goto "RaijuEncounterResult">> <</link>> <!-- Simultaneous Overload --> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; padding: 15px; border-radius: 8px; cursor: pointer;'><strong style='color: #51cf66;'>💥 Simultaneous Overload</strong><br><span style='color: #aaa; font-size: 14px;'>Sync your circuits perfectly — climax together in a shower of sparks</span></div>">> <<set $raijuEncounterChoices.push("simultaneousOverload")>> <<goto "RaijuEncounterResult">> <</link>> </div> </div> <</if>> <!-- Cancel button --> <<if $raijuEncounterStage === 1>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: #444; color: #aaa; padding: 10px 25px; border-radius: 8px; cursor: pointer;'>← Cancel</div>">> <<set $raijuEncounterStage = 0>> <<set $raijuEncounterChoices = []>> <<goto "Abilities">> <</link>> </div> <</if>> </div> </div> <</nobr>>
<<nobr>><<constructionWork>><</nobr>>
<<nobr>> <<set _projId = $lastConstructionProject>> <<set _laborAdded = $lastConstructionLabor>> <<set _projectCompleted = $lastConstructionProjectCompleted>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #f39c12; text-align: center;">🏗️ Construction Work Complete</h1> <<if _projId !== "city" && _projId !== "">> <<set _proj = $constructionProjects[_projId]>> <<set _def = setup.constructionProjectDefs[_projId]>> <<set _pct = Math.round((_proj.progress / _proj.laborRequired) * 100)>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #f39c12;"> <h2 style="color: #f39c12; margin: 0 0 15px 0;"><<= _def.icon>> <<= _def.name>></h2> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #f39c12;"> <p style="color: #f39c12; margin: 0 0 10px 0; font-weight: bold; font-size: 16px;">🔨 Labor Added: <<= _laborAdded>> points</p> /* Progress bar */ <div style="background: #333; border-radius: 10px; overflow: hidden; height: 25px; margin-bottom: 8px;"> <div style="background: linear-gradient(90deg, #f39c12, #e67e22); height: 100%; width: <<= _pct>>%; border-radius: 10px;"></div> </div> <p style="color: #ccc; margin: 0; font-size: 14px;">Progress: <<= _proj.progress>> / <<= _proj.laborRequired>> (<<= _pct>>%)</p> </div> <<if _projectCompleted>> <div style="background: linear-gradient(135deg, #1b5e20 0%, #2e7d32 100%); padding: 20px; border-radius: 8px; border: 2px solid #4caf50;"> <p style="color: #4caf50; margin: 0; font-size: 22px; text-align: center; font-weight: bold;">🎉 PROJECT COMPLETE! 🎉</p> <p style="color: #ccc; margin: 10px 0 0 0; text-align: center; font-size: 16px;"><<= _def.name>> has been finished! The feature is now unlocked.</p> </div> <</if>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #28a745;"> <h2 style="color: #28a745; margin: 0 0 15px 0;">🏙️ City Construction</h2> <p style="color: #ccc; font-size: 16px;">You spent <<= $lastWorkHours>> hours working on city infrastructure projects.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #28a745; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>Continue →</div>">> <<goto "UniversalWorkComplete">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #f39c12; text-align: center;">🏗️ Sawtooth Construction</h1> <div style="padding: 20px; background: linear-gradient(135deg, #5D4037 0%, #795548 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f39c12;"> <p style="color: white; font-size: 18px; margin: 0;">A busy office filled with blueprints, hard hats, and the sound of ringing phones. A gruff foreman sits behind a desk covered in project plans.</p> </div> /* ========== ACTIVE PROJECTS ========== */ <<set _activeProjects = setup.construction.getActiveProjects()>> <<if _activeProjects.length > 0>> <h2 style="color: #f39c12; margin-bottom: 15px;">📋 Active Projects</h2> <<for _i = 0; _i < _activeProjects.length; _i++>> <<set _projId = _activeProjects[_i]>> <<set _proj = $constructionProjects[_projId]>> <<set _def = setup.constructionProjectDefs[_projId]>> <<set _pct = Math.round((_proj.progress / _proj.laborRequired) * 100)>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 10px; border: 2px solid #f39c12;"> <p style="color: #f39c12; margin: 0 0 8px 0; font-weight: bold; font-size: 16px;"><<= _def.icon>> <<= _def.name>></p> <p style="color: #aaa; margin: 0 0 8px 0; font-size: 14px;"><<= _def.description>></p> /* Progress bar */ <div style="background: #333; border-radius: 10px; overflow: hidden; height: 20px; margin-bottom: 8px;"> <div style="background: linear-gradient(90deg, #f39c12, #e67e22); height: 100%; width: <<= _pct>>%; border-radius: 10px;"></div> </div> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 13px;">Progress: <<= _proj.progress>> / <<= _proj.laborRequired>> (<<= _pct>>%)</p> /* Hired workers toggle */ <<if _proj.hiredWorkers>> <p style="color: #4caf50; margin: 0 0 8px 0; font-size: 14px;">👷 Workers Hired — $<<= _proj.hireCostPerDay>>/day (+<<= _proj.hiredLaborPerDay>> labor/day)</p> <<capture _projId>> <<link "<div style='background: #dc3545; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Fire Workers</div>">> <<run setup.construction.toggleHiredWorkers(_projId)>> <<goto "ConstructionOffice">> <</link>> <</capture>> <<else>> <p style="color: #aaa; margin: 0 0 8px 0; font-size: 14px;">No workers hired. Cost: $<<= _proj.hireCostPerDay>>/day for +<<= _proj.hiredLaborPerDay>> labor/day</p> <<capture _projId>> <<link "<div style='background: #4caf50; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Hire Workers ($<<= _proj.hireCostPerDay>>/day)</div>">> <<run setup.construction.toggleHiredWorkers(_projId)>> <<goto "ConstructionOffice">> <</link>> <</capture>> <</if>> </div> <</for>> <</if>> /* ========== DAILY COST NOTIFICATION ========== */ <<if $lastConstructionCost > 0>> <div style="background: #3a2a1a; padding: 10px 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #f39c12;"> <p style="color: #ffc107; margin: 0; font-size: 14px; text-align: center;">💰 Daily worker costs: $<<= $lastConstructionCost>></p> </div> <</if>> /* ========== AVAILABLE PROJECTS ========== */ <<set _availableProjects = setup.construction.getAvailableProjects()>> <<if _availableProjects.length > 0>> <h2 style="color: #28a745; margin-bottom: 15px;">🆕 Available Projects</h2> <<for _i = 0; _i < _availableProjects.length; _i++>> <<set _projId = _availableProjects[_i]>> <<set _def = setup.constructionProjectDefs[_projId]>> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; margin-bottom: 10px; border: 2px solid #28a745;"> <p style="color: #28a745; margin: 0 0 8px 0; font-weight: bold; font-size: 16px;"><<= _def.icon>> <<= _def.name>></p> <p style="color: #aaa; margin: 0 0 8px 0; font-size: 14px;"><<= _def.description>></p> <p style="color: #ccc; margin: 0 0 10px 0; font-size: 13px;">Labor Required: <<= _def.laborRequired>> points | Hire Workers: $<<= _def.hireCostPerDay>>/day</p> <<capture _projId>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Start Project</div>">> <<run setup.construction.startProject(_projId)>> <<goto "ConstructionOffice">> <</link>> <</capture>> </div> <</for>> <<else>> <<if _activeProjects.length === 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 8px; border: 2px solid #666;"> <p style="color: #aaa; margin: 0; text-align: center;">No construction projects available right now. Buy a home or open a bank account to unlock projects.</p> </div> <</if>> <</if>> /* ========== COMPLETED PROJECTS ========== */ <<set _completedProjects = setup.construction.getCompletedProjects()>> <<if _completedProjects.length > 0>> <h2 style="color: #4caf50; margin-bottom: 15px;">✅ Completed Projects</h2> <<for _i = 0; _i < _completedProjects.length; _i++>> <<set _projId = _completedProjects[_i]>> <<set _def = setup.constructionProjectDefs[_projId]>> <div style="background: #1a3d1a; padding: 10px 15px; border-radius: 8px; margin-bottom: 8px; border: 1px solid #4caf50;"> <p style="color: #4caf50; margin: 0; font-size: 14px;"><<= _def.icon>> <<= _def.name>> — Complete ✓</p> </div> <</for>> <</if>> /* ========== GARDEN PLOT EXPANSION ========== */ <<set _basePlots = setup.garden.getBasePlots()>> <<set _extraPlots = $gardenExtraPlots || 0>> <<set _maxExtra = setup.garden.getMaxExtraPlots()>> <<set _totalPlots = _basePlots + _extraPlots>> <<set _maxTotal = _basePlots * 2>> <<set _plotPrice = setup.garden.getPlotPrice()>> <h2 style="color: #4caf50; margin: 25px 0 15px 0;">🌱 Garden Plot Expansion</h2> <div style="background: #2a2a2a; padding: 15px; border-radius: 8px; border: 2px solid #4caf50;"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-bottom: 12px;"> <div> <span style="color: #aaa; font-size: 12px;">Current Plots:</span><br> <span style="color: #4caf50; font-weight: bold; font-size: 18px;"><<= _totalPlots>></span> </div> <div> <span style="color: #aaa; font-size: 12px;">Maximum:</span><br> <span style="color: #ffd700; font-weight: bold; font-size: 18px;"><<= _maxTotal>></span> </div> <div> <span style="color: #aaa; font-size: 12px;">Extra Purchased:</span><br> <span style="color: #ccc; font-weight: bold; font-size: 18px;"><<= _extraPlots>> / <<= _maxExtra>></span> </div> </div> <<if _extraPlots >= _maxExtra>> <p style="color: #ffd700; margin: 10px 0 0 0; text-align: center; font-weight: bold;">✅ Maximum garden plots reached for your home! Upgrade your home for more.</p> <<elseif $money < _plotPrice>> <p style="color: #aaa; margin: 10px 0 0 0; text-align: center;">Next plot costs <span style="color: #ff6b6b; font-weight: bold;">$<<= _plotPrice>></span> — You can't afford it right now.</p> <<else>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: #4caf50; color: white; padding: 12px 25px; border-radius: 8px; font-weight: bold; font-size: 15px; cursor: pointer;'>🌱 Buy Garden Plot — $<<= _plotPrice>></div>">> <<run setup.garden.buyPlot()>> <<goto "ConstructionOffice">> <</link>> </div> <</if>> </div> /* Back button */ <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #3498db; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; cursor: pointer;'>← Back to Business District</div>">> <<goto "BusinessDistrict">> <</link>> </div> </div> <</nobr>>
<<homeGarden>>
<<nobr>> <<if $houseLocation === "ResidentialStudioApartment">> <p style="color: #ff6b6b;">Your studio apartment doesn't have a backyard.</p> <<link "Go back">><<goto setup.getCurrentHome()>><</link>> <<else>> <<set $lastLocation = "PlayerBackyard">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <<if $houseLocation === "ResidentialMansions">> <h1 style="color: #27ae60; text-align: center;">🌳 Estate Grounds</h1> <div style="padding: 20px; background: linear-gradient(135deg, #27ae60 0%, #1a7a40 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #27ae60;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> You step out onto your estate grounds. Three acres of manicured gardens stretch before you, with a tennis court, outdoor kitchen, and helipad dotting the landscape. </p> </div> <<elseif $houseLocation === "ResidentialExpensiveHomes">> <h1 style="color: #1abc9c; text-align: center;">🌴 Backyard & Patio</h1> <div style="padding: 20px; background: linear-gradient(135deg, #1abc9c 0%, #16a085 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #1abc9c;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> You walk out to your lush backyard. The tropical landscaping sways in the warm breeze, surrounding the outdoor kitchen, fire pit, and covered lanai. </p> </div> <<else>> <h1 style="color: #27ae60; text-align: center;">🌴 Backyard</h1> <div style="padding: 20px; background: linear-gradient(135deg, #27ae60 0%, #1a7a40 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #27ae60;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> You step out into your fenced tropical backyard. Palm trees rustle overhead and the patio furniture beckons you to relax. </p> </div> <</if>> <h2 style="color: #27ae60;">What would you like to do?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Relax Outside --> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">☀️ Relax Outside</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Kick back and enjoy the warm tropical air. A great way to de-stress.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Relax (1 hr)</div>">> <<run advanceTime(60)>> <<goto "PlayerBackyard">> <</link>> </div> <!-- Sunbathe --> <div style="border: 3px solid #e67e22; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e67e22; margin: 0 0 10px 0;">🌞 Sunbathe</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Soak up some rays and work on your tan.</p> <<link "<div style='background: #e67e22; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Sunbathe (1 hr)</div>">> <<run advanceTime(60)>> <<goto "PlayerBackyard">> <</link>> </div> <!-- Garden --> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🌱 Garden</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Tend to your garden plots, plant seeds, and harvest your crops.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Visit Garden</div>">> <<goto "HomeGarden">> <</link>> </div> <!-- BBQ / Grill --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #e74c3c; margin: 0 0 10px 0;">🔥 BBQ Grill</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Fire up the grill and cook something tasty.</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: 10px;'>Work in Progress</div> </div> <!-- Pool (Expensive + Mansion) --> <<if $houseLocation === "ResidentialExpensiveHomes" || $houseLocation === "ResidentialMansions">> <div style="border: 3px solid #00bcd4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #00bcd4; margin: 0 0 10px 0;">🏊 Pool</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Take a refreshing swim in your private pool. Great for cooling off and clearing your mind.</p> <<link "<div style='background: #00bcd4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Swim (1 hr)</div>">> <<run advanceTime(60)>> <<run setup.addBuff("pool_refreshed", 300)>> <<goto "PlayerBackyard">> <</link>> </div> <</if>> <!-- Jacuzzi (Mansion only) --> <<if $houseLocation === "ResidentialMansions">> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">✨ Jacuzzi</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Soak in your luxurious outdoor jacuzzi. The jets melt away all your tension.</p> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Soak (1 hr)</div>">> <<run advanceTime(60)>> <<run setup.addBuff("jacuzzi_bliss", 360)>> <<goto "PlayerBackyard">> <</link>> </div> <!-- Mini Golf (Mansion only) --> <div style="border: 3px solid #4CAF50; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #4CAF50; margin: 0 0 10px 0;">⛳ Mini Golf</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Play a round on your private mini golf course. A fun way to unwind.</p> <<link "<div style='background: #4CAF50; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Play (1 hr)</div>">> <<run advanceTime(60)>> <<run setup.addBuff("minigolf_fun", 120)>> <<goto "PlayerBackyard">> <</link>> </div> <!-- Fire Pit (Mansion only) --> <div style="border: 3px solid #ff6347; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff6347; margin: 0 0 10px 0;">🔥 Fire Pit</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4;">Gather around the fire pit. Perfect for unwinding under the stars.</p> <<link "<div style='background: #ff6347; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Sit by Fire (1 hr)</div>">> <<run advanceTime(60)>> <<run setup.addBuff("firepit_social", 180)>> <<goto "PlayerBackyard">> <</link>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back Inside</div>">> <<goto setup.getCurrentHome()>> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <!-- $lastLocation is preserved from the city passage the player came from --> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #00b894; text-align: center;">🍫 Vending Machine</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d3436 0%, #1a1a2e 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #00b894;"> <p style="color: white; font-size: 18px; margin: 0; text-align: center; font-style: italic;"> A humming vending machine stocked with snacks and drinks. The glow of the display illuminates the options. </p> </div> <<vendingMachine>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Walk Away</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "GroceryStoreIngredients">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center;">🥬 Fresh Catch Grocery — Ingredients</h1> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #28a745; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin-bottom: 25px;"> <<for _ingId, _ingredient range setup.ingredients>> <<set _canAfford = $money >= setup.drifterDiscount(_ingredient.price)>> <<set _currentStock = ($kitchenInventory.ingredients[_ingId] || 0)>> <div style="border: 3px solid <<if _canAfford>>#51cf66<<else>>#666<</if>>; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #51cf66; margin: 0 0 10px 0;"><<print _ingredient.name>></h3> <p style="color: #888; font-size: 14px; margin: 0 0 5px 0;">Per <<print _ingredient.unit>></p> <p style="color: #ffd700; font-weight: bold; margin: 0 0 10px 0;">$<<print setup.drifterDiscount(_ingredient.price)>></p> <p style="color: #1e90ff; font-size: 14px; margin: 0 0 10px 0;">In pantry: <<print _currentStock>></p> <<if _canAfford>> <<capture _ingId, _ingredient>> <<link "<div style='background: #51cf66; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Buy 1 ($<<print setup.drifterDiscount(_ingredient.price)>>)</div>">> <<set $money -= setup.drifterDiscount(_ingredient.price)>> <<if !$kitchenInventory.ingredients[_ingId]>><<set $kitchenInventory.ingredients[_ingId] = 0>><</if>> <<set $kitchenInventory.ingredients[_ingId]++>> <<goto "GroceryStoreIngredients">> <</link>> <<if $money >= setup.drifterDiscount(_ingredient.price) * 5>> <div style="margin-top: 8px;"> <<link "<div style='background: #40c057; color: white; padding: 6px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px;'>Buy 5 ($<<print setup.drifterDiscount(_ingredient.price) * 5>>)</div>">> <<set $money -= setup.drifterDiscount(_ingredient.price) * 5>> <<if !$kitchenInventory.ingredients[_ingId]>><<set $kitchenInventory.ingredients[_ingId] = 0>><</if>> <<set $kitchenInventory.ingredients[_ingId] += 5>> <<goto "GroceryStoreIngredients">> <</link>> </div> <</if>> <</capture>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center;">Cannot afford</div> <</if>> </div> <</for>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #20c997; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Store</div>">> <<goto "GroceryStore">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "GroceryStoreSeeds">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #2ecc71; text-align: center;">🌱 Fresh Catch Grocery — Garden Seeds & Seedlings</h1> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #28a745; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 25px;"> <<for _seedKey, _seedDef range setup.seedDefs>> <<capture _seedKey, _seedDef>> <<set _canBuy = setup.canAffordTotal(setup.drifterDiscount(_seedDef.price))>> <<set _isTreeSeed = (_seedDef.plantType === "tree")>> <<set _canPlantHere = setup.garden.canPlantSeedType(_seedKey)>> <div style="border: 3px solid <<if !_canPlantHere>>#555<<elseif _canBuy>><<if _isTreeSeed>>#27ae60<<else>>#2ecc71<</if>><<else>>#666<</if>>; border-radius: 10px; padding: 12px; background: #2a2a2a; text-align: center;<<if !_canPlantHere>> opacity: 0.6;<</if>>"> <div style="font-size: 28px; margin-bottom: 5px;"><<if _isTreeSeed>>🌳 <</if>><<= _seedDef.icon>></div> <h4 style="color: <<if _isTreeSeed>>#27ae60<<else>>#2ecc71<</if>>; margin: 0 0 5px 0; font-size: 14px;"><<= _seedDef.name>></h4> <p style="color: #f39c12; margin: 0 0 3px 0; font-weight: bold;">$<<= setup.drifterDiscount(_seedDef.price)>></p> <<if _isTreeSeed>> <p style="color: #888; font-size: 12px; margin: 0 0 3px 0;">Matures: <<= _seedDef.maturityDays>> days | Fruit every <<= _seedDef.harvestInterval>>d</p> <<else>> <p style="color: #888; font-size: 12px; margin: 0 0 3px 0;">Growth: <<= _seedDef.growthDays>> days</p> <</if>> <p style="color: #888; font-size: 12px; margin: 0 0 8px 0;"><<if _seedDef.harvestType === "ingredient">>Yields: <<= _seedDef.harvestId>><<else>>Sell: $<<= _seedDef.sellPrice>><</if>></p> <<if !_canPlantHere>> <div style="background: #333; color: #e74c3c; padding: 6px 12px; border-radius: 6px; font-size: 12px;">🔒 Requires Expensive Home or Mansion</div> <<elseif _canBuy>> <<link "<div style='background: #2ecc71; color: white; padding: 6px 12px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 13px;'>Buy</div>">> <<set $money -= setup.drifterDiscount(_seedDef.price)>> <<if !$seedInventory>><<set $seedInventory = {}>><</if>> <<if !$seedInventory[_seedKey]>><<set $seedInventory[_seedKey] = 0>><</if>> <<set $seedInventory[_seedKey] += 1>> <<goto "GroceryStoreSeeds">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 6px 12px; border-radius: 6px; text-align: center; font-size: 13px;">Cannot afford</div> <</if>> </div> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #20c997; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px; box-shadow: 0 3px 6px rgba(0,0,0,0.3);'>← Back to Store</div>">> <<goto "GroceryStore">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<busDriverWork>> <</nobr>>
<<nobr>> <<donutsDelivererWork>> <</nobr>>
<<nobr>> <<cocktailWaitressWork>> <</nobr>>
<<nobr>> <<fitnessTrainerWork>> <</nobr>>
<<nobr>> <<streetPerformerWork>> <</nobr>>
<<nobr>> <<amateurMusicianWork>> <</nobr>>
<<nobr>> <<dancingInstructorWork>> <</nobr>>
<<nobr>> <<socialMediaInfluencerWork>> <</nobr>>
<<nobr>> <<blackMarketDealerWork>> <</nobr>>
<<nobr>> <<negotiatorWork>> <</nobr>>
<<nobr>> <<modelWork>> <</nobr>>
<<nobr>> <<pornStarWork>> <</nobr>>
<<nobr>> <<set $lastLocation = "BusDriverJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 16px; margin: 0;"> The bus depot manager looks over your application and nods. "We could use another driver on the routes. The pay is $15 an hour, and you can drive up to 8 hours a day. You'll need to choose your route each shift - longer routes pay the same hourly but you might run into some interesting passengers. Think you can handle it?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #28a745; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #28a745; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Bus Driver. $15 per hour, up to 8 hours/day.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #28a745; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Bus Driver"]>> <<set $homeless = false>> <<goto "BusDriverJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "BusStop">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BusDriverJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #28a745; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #28a745 0%, #20c997 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #28a745;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Welcome to the Sunfish City Transit Authority! Here are your keys and route maps. Report to the bus depot whenever you're ready for a shift. Drive safe out there!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Position:</strong> Bus Driver</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Pay:</strong> $15 per hour</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Hours:</strong> Anytime (24/7)</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #28a745;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #28a745; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "BusStop">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DonutsDelivererJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #d2691e; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #d2691e 0%, #a0522d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #d2691e;"> <p style="color: white; font-size: 16px; margin: 0;"> The bakery owner wipes flour from her hands and smiles. "I need someone reliable to deliver our donuts across the city. Pay is $12 an hour - morning shifts from 5 AM to 2 PM. You'll need to keep them fresh, so speed matters! Faster deliveries mean happier customers and better tips. Interested?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #d2691e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d2691e; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Donuts Deliverer. $12 per hour plus tips for fast delivery.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #d2691e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #d2691e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Donuts Deliverer"]>> <<set $homeless = false>> <<goto "DonutsDelivererJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "Bakery">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DonutsDelivererJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #d2691e; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #d2691e 0%, #a0522d 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #d2691e;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Wonderful! Here's your delivery bag - it's insulated to keep everything warm. Pick up your batch each morning and get them delivered before they go cold. The fresher the donuts, the bigger the tips!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #d2691e;">Position:</strong> Donuts Deliverer</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #d2691e;">Pay:</strong> $12 per hour + tips</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #d2691e;">Hours:</strong> 5 AM - 2 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #d2691e;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #d2691e; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "Bakery">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "CocktailWaitressJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e9e; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e91e9e 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e9e;"> <p style="color: white; font-size: 16px; margin: 0;"> The casino floor manager eyes you appraisingly. "We need cocktail servers who can work the room with style. Pay starts at $15 an hour, but the real money is in tips - charm the high rollers and you'll do very well. You'll need to keep the drinks flowing and the smiles coming. Up to 8 hours a day. Sound like your kind of gig?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #e91e9e; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e91e9e; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Cocktail Waitress. $15 per hour plus generous tips.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #e91e9e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #e91e9e; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Cocktail Waitress"]>> <<set $homeless = false>> <<goto "CocktailWaitressJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "Casino">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "CocktailWaitressJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e9e; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e91e9e 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e9e;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Perfect! Here's your uniform - make sure you look sharp out there. The casino floor is your stage. Keep the VIPs happy and the tips will follow. Welcome to the team!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e91e9e;">Position:</strong> Cocktail Waitress</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e91e9e;">Pay:</strong> $15 per hour + tips</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e91e9e;">Hours:</strong> Anytime (24/7)</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e91e9e;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #e91e9e; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "Casino">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "FitnessTrainerJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b35; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b35 0%, #e65100 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b35;"> <p style="color: white; font-size: 16px; margin: 0;"> The gym owner crosses his arms and looks you over. "I can see you've put in the work on yourself - that's what I like to see. We need trainers who can push our clients to their limits. $25 an hour, shifts from 6 AM to 8 PM. You'll run group fitness classes, personal training sessions, or boot camps. Think you're up for it?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #ff6b35; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff6b35; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Fitness Trainer. $25 per hour, up to 8 hours/day.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #ff6b35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #ff6b35; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Fitness Trainer"]>> <<set $homeless = false>> <<goto "FitnessTrainerJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "OpahFitness">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "FitnessTrainerJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b35; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b35 0%, #e65100 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b35;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Welcome to the team! The gym is your domain now. Push our clients hard but keep it safe. The better shape they get in, the more they'll keep coming back. Show them what dedication looks like!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b35;">Position:</strong> Fitness Trainer</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b35;">Pay:</strong> $25 per hour</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b35;">Hours:</strong> 6 AM - 8 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b35;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #ff6b35; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "OpahFitness">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DancingInstructorJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b9d; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b9d 0%, #e91e63 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b9d;"> <p style="color: white; font-size: 16px; margin: 0;"> The dance studio director watches you move and breaks into a smile. "I can tell you have the rhythm and discipline we need. We're looking for instructors to lead classes - group sessions, private lessons, even advanced workshops. $30 an hour, and our students range from beginners to competition dancers. Ready to share your talent?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #ff6b9d; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ff6b9d; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Dancing Instructor. $30 per hour, up to 8 hours/day.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #ff6b9d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #ff6b9d; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Dancing Instructor"]>> <<set $homeless = false>> <<goto "DancingInstructorJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "DanceStudio">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DancingInstructorJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b9d; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff6b9d 0%, #e91e63 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff6b9d;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Wonderful! The studio is yours during your shifts. We have classes from 10 AM to 8 PM. Pick your class type each shift and inspire our students. Welcome to the dance family!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b9d;">Position:</strong> Dancing Instructor</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b9d;">Pay:</strong> $30 per hour</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b9d;">Hours:</strong> 10 AM - 8 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #ff6b9d;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #ff6b9d; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "DanceStudio">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ModelJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #9c27b0 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 16px; margin: 0;"> The studio director adjusts her glasses and studies you carefully. "You have a certain look - the camera will love you. Luxe Studio is always looking for fresh faces. We start you at $75 an hour for catalog work, and as you build your portfolio, you'll climb the tiers to bigger shoots and brand deals. Sessions run from 8 AM to 8 PM. Interested in starting your modeling career?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Model. $75 per hour, with career tier progression.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Model"]>> <<set $homeless = false>> <<goto "ModelJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "ModelingStudio">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ModelJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #9c27b0 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Welcome to Luxe Studio! You'll start with catalog sessions and work your way up. Each tier unlocks higher-paying work. Head to the fashion department when you're ready for your first shoot!" </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Position:</strong> Model</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Pay:</strong> $75 per hour (base)</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Hours:</strong> 8 AM - 8 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #e83e8c; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "ModelingStudio">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PornStarJobOffer">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">💼 Job Opportunity</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #880e4f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 16px; margin: 0;"> The adult department director leans back in her chair. "So you want to work in adult entertainment. It's not for everyone, but the pay is excellent - $100 an hour. You'll choose your scene type each session, and quality matters. The better your performance, the bigger the bonuses. Sessions run from 8 AM to 8 PM. Are you sure you're ready for this?" </p> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Accept Job --> <div style="border: 3px solid #e83e8c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e83e8c; margin-top: 0;">✅ Accept Job</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Become a Porn Star. $100 per hour with quality bonuses.</p> <<if $jobs && $jobs.includes("Criminal")>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $arrestedAtStation = true>> <<set $arrestType = "jobApplication">> <<goto "CaughtByPolice">> <</link>> <<else>> <<link "<div style='background: #e83e8c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"I'll take it!\"</div>">> <<set $jobs = ["Porn Star"]>> <<set $homeless = false>> <<goto "PornStarJobAccepted">> <</link>> <</if>> </div> <!-- Decline Job --> <div style="border: 3px solid #e74c3c; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #e74c3c; margin-top: 0;">❌ Decline</h3> <p style="font-size: 14px; color: #aaa; flex-grow: 1;">Politely decline the offer.</p> <<link "<div style='background: #e74c3c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>\"Not right now\"</div>">> <<goto "ModelingStudioAdult">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "PornStarJobAccepted">> <!-- Achievement for getting hired --> <<run setup.achievements.unlock("get_hired")>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e83e8c; text-align: center;">✅ Job Accepted!</h1> <div style="padding: 20px; background: linear-gradient(135deg, #e83e8c 0%, #880e4f 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e83e8c;"> <p style="color: white; font-size: 18px; margin: 0 0 15px 0; text-align: center; font-weight: bold;"> Welcome aboard! </p> <p style="color: white; font-size: 16px; margin: 0;"> "Welcome to the team. Discretion and professionalism are everything here. Head to the adult department when you're ready to start filming. Pick your scenes carefully - your reputation will follow you." </p> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 3px solid #17a2b8; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #17a2b8; margin: 0 0 15px 0;">📋 Job Details</h3> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Position:</strong> Porn Star</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Pay:</strong> $100 per hour (base)</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Hours:</strong> 8 AM - 8 PM</p> <p style="color: #ccc; margin: 5px 0;"><strong style="color: #e83e8c;">Max Daily:</strong> 8 hours</p> </div> <<link "<div style='background: #e83e8c; color: white; padding: 15px 40px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 3px 6px rgba(0,0,0,0.3); margin: 0 auto; display: inline-block;'>Continue</div>">> <<goto "ModelingStudioAdult">> <</link>> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.initData()>> <<run setup.prostitute.injectCSS()>> <<set _previousLocation = $lastLocation || "Downtown">> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif;"> <div style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 30px; margin: 20px auto; max-width: 600px; border: 2px solid #c9a0dc; box-shadow: 0 0 30px rgba(201,160,220,0.4);"> <h2 style="color: #c9a0dc; text-align: center; margin-bottom: 15px; text-shadow: 0 0 10px rgba(201,160,220,0.4);">Quite Out of the Question</h2> <p class="prost-prose" style="text-align: center;">You take half a step into the alley, raise the folding fan to your face, and the entire idea collapses on its own. The thought of bartering yourself on a street corner is simply unthinkable to a woman in your dress. Whatever else has changed about you, that has not. You turn on your heel and leave the way you came.</p> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #c9a0dc, #6a0dad); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 12px rgba(0,0,0,0.4);'>Withdraw</div>">><<goto _previousLocation>><</link>> </div> </div> </div> <<else>> <<set _canWork = setup.prostitute.canSolicit(_previousLocation)>> /* Slut and Raiju recover via sex, not sleep — they bypass the exhaustion gate so prostitution can clear any lingering exhaustion debuff. */ <<set _slutBypass = $physicalTraits && ($physicalTraits.includes("Slut") || $physicalTraits.includes("Raiju"))>> <<set _isExhausted = typeof setup.hasDebuff === 'function' && setup.hasDebuff("exhaustion") && !_slutBypass>> <<if _isExhausted>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif;"> <div style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 30px; margin: 20px auto; max-width: 600px; border: 2px solid #dc3545; box-shadow: 0 0 30px rgba(220,53,69,0.3);"> <h2 style="color: #dc3545; text-align: center; margin-bottom: 15px; text-shadow: 0 0 10px rgba(220,53,69,0.4);">Too Exhausted</h2> <p class="prost-prose" style="text-align: center;">Your body aches, a deep weariness settling into your bones. Your legs feel like they belong to someone else. You need rest before you can work again.</p> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #dc3545, #c0392b); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 12px rgba(0,0,0,0.4);'>Head Back</div>">><<goto _previousLocation>><</link>> </div> </div> </div> <<elseif !_canWork.allowed>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif;"> <div style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 30px; margin: 20px auto; max-width: 600px; border: 2px solid #ff1493; box-shadow: 0 0 30px rgba(255,20,147,0.3);"> <h2 style="color: #ff1493; text-align: center; margin-bottom: 15px; text-shadow: 0 0 10px rgba(255,20,147,0.4);">Not the Right Time</h2> <p class="prost-prose" style="text-align: center;"><<= _canWork.reason>></p> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #9b59b6, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 12px rgba(0,0,0,0.4);'>Head Back</div>">><<goto _previousLocation>><</link>> </div> </div> </div> <<else>> <<set $prostReturnPassage = _previousLocation>> <<set $prostEncountersThisSession = 0>> <<set $prostituteData.encountersToday = 0>> <<set $prostituteData.biddingTriggered = false>> <<goto "ProstClientSelect">> <</if>> <</if>> <</nobr>>
<<nobr>> <<run setup.prostitute.initData()>> <<run setup.prostitute.injectCSS()>> <<set _repLevel = setup.prostitute.getRepLevel()>> <<set _repProgress = setup.prostitute.getRepProgress()>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <<set _transformMech = setup.prostitute.getTransformMechanics()>> /* Slut/Raiju recover via sex — they bypass the exhaustion gate. */ <<set _slutBypass = $physicalTraits && ($physicalTraits.includes("Slut") || $physicalTraits.includes("Raiju"))>> <<set _isExhausted = typeof setup.hasDebuff === "function" && setup.hasDebuff("exhaustion") && !_slutBypass>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <h1 style="text-align: center; color: #ff1493; text-shadow: 0 0 15px rgba(255,20,147,0.5); margin-bottom: 5px; font-size: 28px;" class="prost-glow">💋 Soliciting</h1> <p style="text-align: center; color: _repLevel.color; font-size: 14px; margin-bottom: 20px;"><<= _repLevel.name>> | Reputation: <<= $prostituteData.reputation>>/1000</p> /* Reputation Progress Bar */ <div style="max-width: 400px; margin: 0 auto 20px;"> <div style="width: 100%; height: 8px; background: #1a1a2e; border-radius: 4px; overflow: hidden;"> <div style="width: <<= _repProgress.percent>>%; height: 100%; background: linear-gradient(90deg, #9b59b6, <<= _repLevel.color>>); border-radius: 4px; transition: width 0.5s;"></div> </div> <p style="text-align: center; font-size: 12px; color: #888; margin-top: 4px;"><<= _repProgress.percent>>% to <<= _repProgress.nextName>></p> </div> /* Stats Card */ <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 20px; margin-bottom: 15px; border: 2px solid #9b59b6; box-shadow: 0 4px 15px rgba(0,0,0,0.5);"> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; text-align: center;"> <div><span style="color: #ff1493; font-size: 20px; font-weight: bold;"><<= $prostituteData.totalClients>></span><br><span style="color: #888; font-size: 12px;">Clients</span></div> <div><span style="color: #28a745; font-size: 20px; font-weight: bold;">$<<= $prostituteData.totalEarnings>></span><br><span style="color: #888; font-size: 12px;">Earned</span></div> <div><span style="color: #e67e22; font-size: 20px; font-weight: bold;"><<= $prostEncountersThisSession || 0>></span><br><span style="color: #888; font-size: 12px;">Tonight</span></div> </div> </div> /* Active Transformation Display */ <<if $activeTransformation>> <div class="prost-fade-delay1" style="background: rgba(26, 10, 46, 0.8); border-radius: 10px; padding: 12px; margin-bottom: 15px; border: 1px solid #c71585; text-align: center;"> <span style="color: #c71585; font-size: 14px;">✨ <<= $activeTransformation>> Active</span> <<if _transformMech.sceneTheme>> <span style="color: #888; font-size: 12px;"> | <<= _transformMech.sceneTheme>></span> <</if>> </div> <</if>> /* Legend Encounter Check */ <<if $prostituteData.reputation >= 900 && !$prostituteData.legendComplete>> <div class="prost-fade" style="background: linear-gradient(135deg, rgba(255,215,0,0.15), rgba(218,165,32,0.1)); border-radius: 15px; padding: 25px; border: 2px solid rgba(255,215,0,0.6); margin-bottom: 15px; box-shadow: 0 0 30px rgba(255,215,0,0.3); text-align: center;"> <h3 style="color: #ffd700; text-shadow: 0 0 15px rgba(255,215,0,0.5); margin-bottom: 10px;">👑 A Legend Emerges</h3> <p style="color: #e8d5b7; font-style: italic; font-size: 14px; margin-bottom: 15px;">A sleek black car pulls up. The window rolls down, and someone hands you a gold-embossed card. "You have been requested. Tonight is not like other nights."</p> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; border: none; padding: 16px 40px; border-radius: 12px; font-size: 18px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 20px rgba(255,215,0,0.5); animation: prostPulse 2s ease-in-out infinite;'>👑 Accept the Invitation</div>">> <<goto "ProstLegendEncounter">> <</link>> <p style="color: #888; font-size: 11px; margin-top: 10px;">Or scroll down to work your usual night instead.</p> </div> <</if>> /* Bidding Section */ <<if $prostituteData.reputation >= 600 && !$prostituteData.biddingTriggered && setup.prostitute.shouldTriggerBidding()>> <<set $prostituteData.biddingTriggered = true>> <<set _bidders = setup.prostitute.generateBidders()>> <div class="prost-fade-delay1" style="background: linear-gradient(135deg, rgba(218,165,32,0.15), rgba(255,69,0,0.1)); border-radius: 15px; padding: 20px; border: 2px solid rgba(218,165,32,0.5); margin-bottom: 15px; box-shadow: 0 4px 20px rgba(218,165,32,0.2);"> <h3 style="color: #daa520; text-align: center; margin-bottom: 5px; text-shadow: 0 0 10px rgba(218,165,32,0.5);">💰 Bidding War</h3> <p style="color: #b8a9c9; font-size: 13px; text-align: center; margin-bottom: 15px; font-style: italic;">Word of your reputation has spread. Multiple clients are competing for your attention tonight.</p> <div style="display: flex; flex-wrap: wrap; gap: 12px; justify-content: center;"> <<for _bidder range _bidders>> <<capture _bidder>> <<set _bidIcon = _bidder.gender === 'male' ? '👨💼' : '👩💼'>> <<set _tierColor = _bidder.tier === 'VIP' ? '#ffd700' : '#daa520'>> <<set _bidBtnHtml = "<div style='background: linear-gradient(135deg, rgba(218,165,32,0.2), rgba(139,69,19,0.15)); border: 2px solid " + _tierColor + "; border-radius: 12px; padding: 15px; cursor: pointer; text-align: center; min-width: 160px; max-width: 200px; transition: transform 0.2s;'><div style='font-size: 24px; margin-bottom: 5px;'>" + _bidIcon + "</div><div style='color: #e8d5b7; font-weight: bold; font-size: 16px;'>" + _bidder.name + "</div><div style='color: " + _tierColor + "; font-size: 11px; margin: 3px 0;'>" + _bidder.tier + " • " + _bidder.mood + "</div><div style='color: #28a745; font-size: 20px; font-weight: bold; margin: 8px 0 4px;'>$" + _bidder.bidAmount + "</div><div style='color: #888; font-size: 11px; font-style: italic;'>" + _bidder.bidFlavor + "</div></div>">> <<link _bidBtnHtml>> <<set $prostCurrentClient = _bidder>> <<set $prostSatisfaction = 20>> <<goto "ProstApproach">> <</link>> <</capture>> <</for>> </div> <p style="color: #888; font-size: 11px; text-align: center; margin-top: 10px;">Choose a bidder, or scroll down to find your own client instead.</p> </div> <</if>> /* Action Buttons */ <<if _isExhausted>> <div class="prost-fade-delay2" style="background: rgba(220,53,69,0.15); border-radius: 12px; padding: 20px; border: 2px solid #dc3545; text-align: center; margin-bottom: 15px;"> <p style="color: #dc3545; font-weight: bold; margin-bottom: 10px;">😫 You're Exhausted</p> <p class="prost-prose">Your body has had enough for tonight. Every muscle aches, and your legs threaten to give out beneath you. Time to call it a night.</p> </div> <<else>> <div class="prost-fade-delay2" style="text-align: center; margin-bottom: 15px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 16px 40px; border-radius: 12px; font-size: 18px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 15px rgba(255,20,147,0.4); animation: prostPulse 3s ease-in-out infinite;'>👁️ Look for a Client</div>">> <<set $prostCurrentClient = setup.prostitute.generateClient()>> <<goto "ProstApproach">> <</link>> </div> /* Regulars Section */ <<if $prostituteData.reputation >= 150 && $prostituteData.regulars && $prostituteData.regulars.length > 0>> <div class="prost-fade-delay2" style="background: rgba(218, 165, 32, 0.1); border-radius: 12px; padding: 15px; border: 1px solid rgba(218, 165, 32, 0.3); margin: 15px auto; max-width: 650px;"> <h4 style="color: #daa520; text-align: center; margin-bottom: 10px;">⭐ Your Regulars</h4> <p style="color: #b8a9c9; font-size: 12px; text-align: center; margin-bottom: 10px;">Returning clients who know and trust you. +15% pay, +10 satisfaction.</p> <div style="display: flex; flex-wrap: wrap; gap: 8px; justify-content: center;"> <<for _reg range $prostituteData.regulars>> <<capture _reg>> <<set _regIcon = _reg.gender === 'male' ? '👨' : '👩'>> <<set _regVisits = _reg.visits >= 5 ? '❤️' : _reg.visits >= 3 ? '🔥' : '✨'>> <<set _regBtnHtml = "<div style='background: linear-gradient(135deg, rgba(218,165,32,0.2), rgba(255,215,0,0.1)); border: 1px solid rgba(218,165,32,0.4); border-radius: 8px; padding: 10px 14px; cursor: pointer; text-align: center; min-width: 120px;'>" + _regIcon + " " + _reg.name + "<br><span style='font-size: 11px; color: #b8a9c9;'>" + _regVisits + " Visits: " + _reg.visits + "</span></div>">> <<link _regBtnHtml>> <<set $prostCurrentClient = setup.prostitute.getRegularClient(_reg)>> <<set $prostSatisfaction = 10>> <<goto "ProstApproach">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <</if>> /* Finish Button */ <div class="prost-fade-delay3" style="text-align: center;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #333, #555); color: #ccc; border: none; padding: 12px 30px; border-radius: 10px; font-size: 15px; cursor: pointer; display: inline-block; box-shadow: 0 3px 8px rgba(0,0,0,0.3);'>Finish for the Night</div>">> <<set $prostEncountersThisSession = 0>> <<set $prostituteData.encountersToday = 0>> <<goto $prostReturnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <<set _isPolice = setup.prostitute.checkPolice()>> <<set _isBadClient = setup.prostitute.checkBadClient()>> <<if _isPolice>> <<goto "ProstPoliceEncounter">> <<elseif _isBadClient>> <<goto "ProstBadClient">> <<else>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <<if _client.isRegular>><h2 style="text-align: center; color: #daa520; text-shadow: 0 0 10px rgba(218,165,32,0.4); margin-bottom: 20px;">⭐ A Familiar Face Returns</h2><<else>><h2 style="text-align: center; color: #ff1493; text-shadow: 0 0 10px rgba(255,20,147,0.4); margin-bottom: 20px;">A Client Approaches</h2><</if>> /* Client Info Card */ <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 20px; margin-bottom: 20px; border: 2px solid <<= setup.prostitute.moodColors[_client.mood] || '#9b59b6'>>; box-shadow: 0 4px 15px rgba(0,0,0,0.5);"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;"> <div> <span style="font-size: 22px; font-weight: bold; color: #e0d0f0;"><<= _client.name>></span> <span style="color: #888; font-size: 14px; margin-left: 8px;"><<= _client.gender === 'male' ? '♂️' : '♀️'>></span> </div> <span style="<<= setup.prostitute.css.moodBadge(_client.mood)>>"><<= setup.prostitute.moodIcons[_client.mood] || ''>> <<= _client.mood>></span> </div> /* Scene description based on mood */ <div class="prost-fade-delay1"> <<if _client.isRegular>><p class="prost-prose" id="approachScene"><<= _client.name>> approaches with a warm, familiar smile. Their eyes light up when they spot you — a returning client who remembers you well. They sought you out specifically tonight, and from the look on their face, they liked what they found last time.</p><<else>><p class="prost-prose" id="approachScene"><<= setup.prostitute.scenes.approach[_client.mood] ? setup.prostitute.scenes.approach[_client.mood].base : "A figure emerges from the neon-stained darkness, eyes finding you with purpose. They slow their stride, interest plain on their face.">></p><</if>> </div> /* Client Details */ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 15px; font-size: 13px;"> <div style="color: #b8a9c9;">💰 Tier: <span style="color: <<= _client.tier === 'VIP' ? '#ff1493' : _client.tier === 'Generous' ? '#28a745' : _client.tier === 'Normal' ? '#ffc107' : '#dc3545'>>;"><<= _client.tier>></span></div> <div style="color: #b8a9c9;">💡 Prefers: <span style="color: #e0d0f0;"><<= _client.preference>></span></div> <<if _traitEffects.availableChoices.indexOf('readVibe') !== -1>> <div style="color: #b8a9c9;">❤️ Kink: <span style="color: #e0d0f0;"><<= _client.kink>></span></div> <<else>> <div style="color: #666;">❤️ Kink: <span style="color: #666;">???</span></div> <</if>> <div style="color: #b8a9c9;">💵 Est. Pay: <span style="color: #28a745;">$<<= _client.basePay>>+</span></div> </div> </div> /* Choice Buttons */ <div class="prost-fade-delay2" style="display: flex; flex-direction: column; gap: 8px; max-width: 500px; margin: 0 auto;"> /* Always available */ <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>Take the Client</div>">> <<set $prostSatisfaction = 30>> <<goto "ProstForeplay">> <</link>> /* Negotiate (rep 100+) */ <<if $prostituteData.reputation >= 100>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #28a745, #20c997); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>💰 Negotiate Higher</div>">> <<goto "ProstNegotiate">> <</link>> <</if>> /* Read Vibe (Observant trait) */ <<if _traitEffects.availableChoices.indexOf('readVibe') === -1>> <<else>> /* Already shown - kink visible above */ <</if>> /* Trait-specific options */ <<if _traitEffects.availableChoices.indexOf('comfort') !== -1 && (_client.mood === 'Nervous' || _client.mood === 'Shy')>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #e91e63, #ad1457); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>💖 Comfort Them (Kind)</div>">> <<set $prostSatisfaction = 45>> <<goto "ProstForeplay">> <</link>> <</if>> <<if _traitEffects.availableChoices.indexOf('confident') !== -1>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #e67e22, #d35400); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>💪 Assert Your Price (Confident)</div>">> <<set $prostCurrentClient.basePay = Math.floor($prostCurrentClient.basePay * 1.15)>> <<set $prostSatisfaction = 30>> <<goto "ProstForeplay">> <</link>> <</if>> /* Transformation options */ <<if $activeTransformation === 'Kitsune'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #ff8c00, #ff6347); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>🦊 Fox Charm (Kitsune)</div>">> <<set $prostSatisfaction = 50>> <<set $prostCurrentClient.basePay = Math.floor($prostCurrentClient.basePay * 1.2)>> <<goto "ProstKitsuneScene">> <</link>> <</if>> <<if $activeTransformation === 'Succubus'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #8b0000, #dc143c); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>🔥 Lure with Dark Energy (Succubus)</div>">> <<set $prostSatisfaction = 45>> <<goto "ProstSuccubusScene">> <</link>> <</if>> <<if $activeTransformation === 'Siren'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #1a75ff, #00ced1); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>🎶 Siren Song</div>">> <<set $prostSatisfaction = 45>> <<goto "ProstSirenScene">> <</link>> <</if>> <<if $activeTransformation === 'Cupid'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #b76e79, #c71585); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>💘 Cupid's Touch</div>">> <<set $prostSatisfaction = 50>> <<goto "ProstCupidScene">> <</link>> <</if>> <<if $activeTransformation === 'TrophyWife'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #daa520, #ffd700); color: #1a0a2e; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>👑 Trophy Wife Elegance</div>">> <<set $prostSatisfaction = 45>> <<set $prostCurrentClient.basePay = Math.floor($prostCurrentClient.basePay * 1.5)>> <<goto "ProstTrophyWifeScene">> <</link>> <</if>> <<if $activeTransformation === 'Dominatrix'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #4b0082, #800080); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>⛓️ Dominate Them</div>">> <<set $prostSatisfaction = 50>> <<goto "ProstDominatrixScene">> <</link>> <</if>> <<if $activeTransformation === 'Slut'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #e91e63, #ff69b4); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>😋 Show Your Eagerness (Slut)</div>">> <<set $prostSatisfaction = 55>> <<goto "ProstSlutScene">> <</link>> <</if>> <<if $activeTransformation === 'Cerberus'>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #ffd700, #c93068); color: #1a0a2e; border: none; padding: 14px 24px; border-radius: 10px; font-size: 16px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>🐺 Three Mouths, One Hunger (Cerberus)</div>">> <<set $prostSatisfaction = 50>> <<goto "ProstCerberusScene">> <</link>> <</if>> /* Walk Away */ <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #333, #555); color: #ccc; border: none; padding: 12px 24px; border-radius: 10px; font-size: 14px; cursor: pointer; box-shadow: 0 3px 8px rgba(0,0,0,0.3); text-align: center;'>Walk Away</div>">> <<goto "ProstWalkAway">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _charisma = (typeof setup.getTotalStat === 'function') ? setup.getTotalStat('charisma') : ($charisma || 0)>> <<set _confidentBonus = setup.playerHasTrait('Confident') ? 15 : 0>> <<set _roll = Math.floor(Math.random() * 100) + (_charisma * 0.5) + _confidentBonus>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <<if _roll >= 60>> <<set $prostCurrentClient.basePay = Math.floor($prostCurrentClient.basePay * 1.25)>> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; border: 2px solid #28a745; box-shadow: 0 4px 15px rgba(40,167,69,0.3);"> <h3 style="color: #28a745; text-align: center; margin-bottom: 15px;">💰 Negotiation Successful</h3> <p class="prost-prose">You name your price with the kind of certainty that doesn't invite haggling. <<= _client.name>> hesitates for only a moment before nodding. They know quality when they see it.</p> <p style="color: #28a745; text-align: center; font-weight: bold; font-size: 18px;">New rate: $<<= $prostCurrentClient.basePay>></p> </div> <<else>> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; border: 2px solid #dc3545; box-shadow: 0 4px 15px rgba(220,53,69,0.3);"> <h3 style="color: #dc3545; text-align: center; margin-bottom: 15px;">😕 They're Not Convinced</h3> <p class="prost-prose"><<= _client.name>> raises an eyebrow at your asking price. "That's a bit steep for what I had in mind," they say, unmoved. You'll have to take the original rate or walk.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Continue with Client</div>">> <<set $prostSatisfaction = 30>> <<goto "ProstForeplay">> <</link>> <<link "<div class='prost-btn' style='background: #333; color: #ccc; border: none; padding: 12px 24px; border-radius: 10px; font-size: 14px; cursor: pointer; display: inline-block;'>Walk Away</div>">> <<goto "ProstWalkAway">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<goto "ProstApproach">> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<run advanceTime(30)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 600px; margin: 40px auto; border: 2px solid #666; box-shadow: 0 4px 15px rgba(0,0,0,0.5);"> <p class="prost-prose" style="text-align: center;">You shake your head slightly and keep walking. Not every client is worth the trouble. The neon haze swallows them as you move on, scanning the streets for better prospects.</p> <p style="text-align: center; color: #888; font-size: 13px; margin-top: 10px;">30 minutes pass...</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Keep Looking</div>">> <<goto "ProstClientSelect">> <</link>> <<link "<div class='prost-btn' style='background: #333; color: #ccc; border: none; padding: 12px 24px; border-radius: 10px; font-size: 14px; cursor: pointer; display: inline-block;'>Call It a Night</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <<set _rep = $prostituteData.reputation || 0>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <h2 style="text-align: center; color: #c71585; text-shadow: 0 0 10px rgba(199,21,133,0.4); margin-bottom: 20px;">Setting the Mood</h2> /* Satisfaction hint */ <div class="prost-fade" style="text-align: center; margin-bottom: 20px;"> <p class="prost-prose"><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> /* Foreplay choices */ <div class="prost-fade-delay1" style="display: flex; flex-direction: column; gap: 8px; max-width: 500px; margin: 0 auto;"> <p style="color: #b8a9c9; text-align: center; font-size: 14px; margin-bottom: 5px;">Choose how to warm them up...</p> /* Always available */ <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #e91e63, #ad1457); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>💋 Kiss</div>">> <<set $prostLastForeplay = 'kiss'>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('kiss', _client.preference) + setup.prostitute.getMoodMatch('kiss', _client.mood)>> <<goto "ProstKiss">> <</link>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #9b59b6, #8e44ad); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>😏 Tease</div>">> <<set $prostLastForeplay = 'tease'>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('tease', _client.preference) + setup.prostitute.getMoodMatch('tease', _client.mood)>> <<goto "ProstTease">> <</link>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #e67e22, #d35400); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>✋ Touch</div>">> <<set $prostLastForeplay = 'touch'>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('touch', _client.preference) + setup.prostitute.getMoodMatch('touch', _client.mood)>> <<goto "ProstTouch">> <</link>> /* Strip: available at rep 100+ */ <<if _rep >= 100>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>💃 Strip Tease</div>">> <<set $prostLastForeplay = 'strip'>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('strip', _client.preference) + setup.prostitute.getMoodMatch('strip', _client.mood)>> <<goto "ProstStrip">> <</link>> <</if>> /* Flirty trait extra option */ <<if _traitEffects.availableChoices.indexOf('extraFlirt') !== -1>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #ff69b4, #ff1493); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>😘 Playful Flirting (Flirty)</div>">> <<set $prostLastForeplay = 'flirt'>> <<set $prostSatisfaction += 15 + setup.prostitute.getMoodMatch('flirt', _client.mood)>> <<goto "ProstKiss">> <</link>> <</if>> /* Skip to service */ <div style="margin-top: 15px; border-top: 1px solid #333; padding-top: 15px;"> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #555, #333); color: #ddd; border: none; padding: 12px 24px; border-radius: 10px; font-size: 14px; cursor: pointer; box-shadow: 0 3px 8px rgba(0,0,0,0.3); text-align: center;'>Skip to the Main Event ➡️</div>">> <<goto "ProstServiceSelect">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<run $prostituteData.actionCounts.kiss++>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_foreplay", "Kiss", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e91e63; box-shadow: 0 0 20px rgba(233,30,99,0.3);"> <p class="prost-prose"><<= setup.prostitute.getSceneText(setup.prostitute.scenes.foreplay.kiss, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.foreplay.kiss, _client.mood, _client.gender) : "You close the distance between you, tilting your head as your lips find theirs. The kiss starts tentative, testing, then deepens as " + _client.name + " responds. Their hand finds the back of your neck, pulling you closer. You taste their desire before you feel it.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #c71585, #9b59b6); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Continue...</div>">> <<goto "ProstServiceSelect">> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #e91e63, #ad1457); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; cursor: pointer; display: inline-block;'>More Foreplay</div>">> <<goto "ProstForeplay">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<run $prostituteData.actionCounts.tease++>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_foreplay", "Tease", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #9b59b6; box-shadow: 0 0 20px rgba(155,89,182,0.3);"> <p class="prost-prose"><<= setup.prostitute.getSceneText(setup.prostitute.scenes.foreplay.tease, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.foreplay.tease, _client.mood, _client.gender) : "You let your fingers trail along " + _client.name + "'s arm, feather-light, never quite giving them what they want. A slow smile plays on your lips as you watch their breathing change. You lean close enough for them to feel your warmth, then pull back. Making them wait. Making them want.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #c71585, #9b59b6); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Continue...</div>">> <<goto "ProstServiceSelect">> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #e91e63, #ad1457); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; cursor: pointer; display: inline-block;'>More Foreplay</div>">> <<goto "ProstForeplay">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<run $prostituteData.actionCounts.touch++>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_foreplay", "Touch", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e67e22; box-shadow: 0 0 20px rgba(230,126,34,0.3);"> <p class="prost-prose"><<= setup.prostitute.getSceneText(setup.prostitute.scenes.foreplay.touch, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.foreplay.touch, _client.mood, _client.gender) : "Your hand finds " + _client.name + "'s chest, palm flat, feeling the rapid beat beneath their ribs. Your fingers spread, exploring, and you feel them stiffen then relax into your touch. The heat of their skin bleeds through the fabric as you trace lower, following the line of their body with practiced confidence.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #c71585, #9b59b6); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Continue...</div>">> <<goto "ProstServiceSelect">> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #e91e63, #ad1457); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; cursor: pointer; display: inline-block;'>More Foreplay</div>">> <<goto "ProstForeplay">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<run $prostituteData.actionCounts.strip++>> <<set _chestDesc = setup.prostitute.getChestDescription()>> <<set _buttDesc = setup.prostitute.getButtDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_foreplay", "Strip", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #ff1493; box-shadow: 0 0 20px rgba(255,20,147,0.3);"> <p class="prost-prose">You hold <<= _client.name>>'s gaze as you begin, slow and deliberate. Each piece of clothing is a promise, each reveal another step deeper into their desire. <<= _chestDesc>> catches the low light as fabric falls away, and you hear their breath catch. You turn, letting them see <<= _buttDesc>>, hips swaying with a rhythm that belongs to the neon-stained night. By the time you're done, <<= _client.name>> can't look away. They don't want to.</p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #c71585, #9b59b6); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Continue...</div>">> <<goto "ProstServiceSelect">> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #e91e63, #ad1457); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; cursor: pointer; display: inline-block;'>More Foreplay</div>">> <<goto "ProstForeplay">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _available = setup.prostitute.getAvailableServices()>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <h2 style="text-align: center; color: #ff1493; text-shadow: 0 0 10px rgba(255,20,147,0.4); margin-bottom: 10px;">What Are They Looking For?</h2> <div class="prost-fade" style="text-align: center; margin-bottom: 15px;"> <p class="prost-prose"><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay1" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 10px; max-width: 650px; margin: 0 auto;"> /* All available services */ <<for _sIdx = 0; _sIdx < _available.length; _sIdx++>> <<set _svc = _available[_sIdx]>> <<capture _svc>> <<set _svcBtnHtml = "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #9b59b6, #c71585); color: white; border: none; padding: 14px 20px; border-radius: 10px; font-size: 15px; cursor: pointer; box-shadow: 0 4px 12px rgba(0,0,0,0.4); text-align: center;'>" + _svc.data.icon + " " + _svc.data.name + " ($" + _svc.data.basePay + "+)</div>">> <<link _svcBtnHtml>> <<set $prostSelectedService = _svc>> <<if _svc.key === 'handjob'>><<goto "ProstHandjob">> <<elseif _svc.key === 'oral'>><<goto "ProstOral">> <<elseif _svc.key === 'vaginal'>><<goto "ProstVaginal">> <<elseif _svc.key === 'stripTease'>><<goto "ProstStripTease">> <<elseif _svc.key === 'anal'>><<goto "ProstAnal">> <<elseif _svc.key === 'titfuck'>><<goto "ProstTitfuck">> <<elseif _svc.key === 'sixtynine'>><<goto "ProstSixtyNine">> <<elseif _svc.key === 'roleplay'>><<goto "ProstRoleplay">> <<elseif _svc.key === 'domination'>><<goto "ProstDomination">> <<elseif _svc.key === 'submission'>><<goto "ProstSubmission">> <<elseif _svc.key === 'gfe'>><<goto "ProstGFE">> <<elseif _svc.key === 'fetish'>><<goto "ProstFetish">> <</if>> <</link>> <</capture>> <</for>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.handjob>> <<run $prostituteData.actionCounts.handjob++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('handjob', _client.preference) + 5>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Handjob", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #c71585; box-shadow: 0 0 20px rgba(199,21,133,0.3);"> <h3 style="color: #c71585; text-align: center; margin-bottom: 15px;">✋ Handjob</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.handjob, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.handjob, _client.mood, _client.gender) : "Your fingers wrap around " + _client.name + " with practiced ease, finding the rhythm that makes their breath stutter. You watch their face — the micro-expressions that tell you everything. Faster here. Slower there. A twist of the wrist that makes them gasp. This is a conversation spoken in touch, and you're fluent.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'handjob'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.oral>> <<run $prostituteData.actionCounts.oral++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('oral', _client.preference) + 8>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _genDesc = setup.prostitute.getGenitalDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Oral", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e91e63; box-shadow: 0 0 20px rgba(233,30,99,0.3);"> <h3 style="color: #e91e63; text-align: center; margin-bottom: 15px;">👄 Oral</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.oral, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.oral, _client.mood, _client.gender) : "You sink to your knees with a grace that makes " + _client.name + " inhale sharply. Your eyes hold theirs as your mouth finds them — slow at first, exploratory, learning what they like. The taste of their skin, the salt and heat, fills your senses. You feel their hand tangle in your hair as you find the pace that unravels them.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'oral'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.vaginal>> <<run $prostituteData.actionCounts.vaginal++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('vaginal', _client.preference) + 10>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _genDesc = setup.prostitute.getGenitalDescription()>> <<set _chestDesc = setup.prostitute.getChestDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Vaginal", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #ff1493; box-shadow: 0 0 20px rgba(255,20,147,0.4);"> <h3 style="color: #ff1493; text-align: center; margin-bottom: 15px;">🔥 Vaginal</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.vaginal, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.vaginal, _client.mood, _client.gender) : _client.name + " presses against you, and you guide them in. The first thrust draws a gasp from both of you — yours calculated, theirs genuine. You set the pace, hips rolling in that practiced rhythm that makes their eyes flutter shut. <<= _chestDesc>> presses against their chest as you pull them closer. Deeper. The sound of skin on skin fills the narrow space between moans.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'vaginal'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.resetOjouRefinement()>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <<set $prostSatisfaction += _traitEffects.satisfactionBonus>> <<set $prostSatisfaction = Math.min(100, Math.max(0, $prostSatisfaction))>> <<set _rating = setup.prostitute.getSatisfactionRating($prostSatisfaction)>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_climax", "Climax", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <<if $prostSatisfaction >= 76>> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #28a745; box-shadow: 0 0 25px rgba(40,167,69,0.4);"> <h3 style="color: #28a745; text-align: center; margin-bottom: 15px; text-shadow: 0 0 10px rgba(40,167,69,0.5);">✨ Outstanding</h3> <p class="prost-prose"><<= _client.name>> comes apart beneath you with a cry that echoes off the walls. Their whole body tenses, trembles, then releases in waves that you can feel rippling through them. You hold them through it, steady and sure, as the world narrows to this single shattering moment. When their eyes finally open, they look at you like you've shown them something sacred.</p> </div> <<elseif $prostSatisfaction >= 51>> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #ffc107; box-shadow: 0 0 25px rgba(255,193,7,0.3);"> <h3 style="color: #ffc107; text-align: center; margin-bottom: 15px;">Good</h3> <p class="prost-prose"><<= _client.name>> finishes with a deep groan, their body going rigid then soft against you. They breathe hard for a long moment, a satisfied smile spreading across their face. Not life-changing, but damn good. They know they got their money's worth.</p> </div> <<elseif $prostSatisfaction >= 26>> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e67e22; box-shadow: 0 0 25px rgba(230,126,34,0.3);"> <h3 style="color: #e67e22; text-align: center; margin-bottom: 15px;">Mediocre</h3> <p class="prost-prose"><<= _client.name>> finishes quietly, more a sigh of completion than any kind of crescendo. They pull away after, already reaching for their clothes. The silence that follows says enough — functional, but forgettable.</p> </div> <<else>> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #dc3545; box-shadow: 0 0 25px rgba(220,53,69,0.3);"> <h3 style="color: #dc3545; text-align: center; margin-bottom: 15px;">Poor</h3> <p class="prost-prose"><<= _client.name>> pulls away before either of you really gets anywhere. Their expression is flat — disappointed, maybe. They dress in silence, avoiding your eyes. Not your best work.</p> </div> <</if>> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>The Aftermath...</div>">> <<goto "ProstAftermath">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svcKey = $prostSelectedServiceKey || 'handjob'>> <<set _svc = setup.prostitute.services[_svcKey]>> <<set _satisfaction = Math.min(100, Math.max(0, $prostSatisfaction))>> <<set _rating = setup.prostitute.getSatisfactionRating(_satisfaction)>> /* Calculate pay */ <<set _pay = setup.prostitute.calculatePay(_client, _svc, _satisfaction)>> /* Award XP */ <<run setup.prostitute.awardSexualXP(_svcKey)>> /* Satisfy sexual needs (Slut/Raiju, Cheshire Cat) */ <<if typeof setup.satisfySlutSexualNeeds === "function">><<run setup.satisfySlutSexualNeeds()>><</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">><<run setup.satisfyCheshireCatSexualNeeds()>><</if>> /* Update tracking */ <<set $prostituteData.totalClients++>> <<set $prostituteData.totalEarnings += _pay>> <<set $prostituteData.sexualEncounters++>> <<set $prostEncountersThisSession = ($prostEncountersThisSession || 0) + 1>> <<set $prostituteData.encountersToday = ($prostituteData.encountersToday || 0) + 1>> /* Reputation gain (scaled by performance) */ <<set _repGain = _satisfaction >= 76 ? 8 : _satisfaction >= 51 ? 5 : _satisfaction >= 26 ? 2 : 0>> <<run setup.prostitute.addReputation(_repGain)>> /* Regulars check */ <<set _regularResult = setup.prostitute.checkRegular($prostCurrentClient, _satisfaction)>> <<if _regularResult === "new">> <<set _regMsg = "<div style='color: #daa520; margin-top: 8px; font-style: italic;'>⭐ " + $prostCurrentClient.name + " has become a regular! They'll seek you out again.</div>">> <<elseif _regularResult === "updated">> <<set _regMsg = "<div style='color: #b8a9c9; margin-top: 5px; font-size: 12px; font-style: italic;'>" + $prostCurrentClient.name + " enjoyed returning to you.</div>">> <<else>> <<set _regMsg = "">> <</if>> /* Add earnings to wallet */ <<set $money = ($money || 0) + _pay>> /* Heat gain */ <<run setup.prostitute.addHeat(2)>> /* Advance time */ <<run advanceTime(60)>> /* Check trait gains */ <<set _traitGains = setup.prostitute.checkTraitGains()>> /* Cupid relationship boost */ <<if $activeTransformation === 'Cupid' && _client.isNPC && _client.npcName>> <<set _npcIdx = -1>> <<for _ni = 0; _ni < $npcs.length; _ni++>> <<if $npcs[_ni] && $npcs[_ni].name === _client.npcName>> <<set _npcIdx = _ni>> <</if>> <</for>> <<if _npcIdx >= 0>> <<set $npcs[_npcIdx].relationship = Math.min(100, ($npcs[_npcIdx].relationship || 0) + 15)>> <</if>> <</if>> /* Honeybee honey */ <<if $activeTransformation === 'Honeybee'>> <<set $honey = ($honey || 0) + 1>> <</if>> /* Exhaustion check - apply debuff if threshold reached */ <<run setup.prostitute.applyExhaustionIfNeeded()>> <<set _nowExhausted = typeof setup.hasDebuff === "function" && setup.hasDebuff("exhaustion")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <h2 style="text-align: center; color: #ff1493; text-shadow: 0 0 10px rgba(255,20,147,0.4); margin-bottom: 20px;">Encounter Complete</h2> /* Earnings Reveal */ <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 550px; margin: 0 auto 15px; border: 2px solid <<= _rating.color>>; box-shadow: 0 0 20px <<= _rating.color>>44;"> <div style="text-align: center; margin-bottom: 15px;"> <span style="color: <<= _rating.color>>; font-size: 14px; font-weight: bold;"><<= _rating.label>> Performance</span> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 15px;"> <div style="text-align: center;"> <span style="color: #888; font-size: 12px;">Client</span><br> <span style="color: #e0d0f0; font-size: 16px;"><<= _client.name>></span> </div> <div style="text-align: center;"> <span style="color: #888; font-size: 12px;">Service</span><br> <span style="color: #e0d0f0; font-size: 16px;"><<= _svc ? _svc.name : 'Unknown'>></span> </div> </div> <div class="prost-fade-delay1" style="text-align: center; padding: 15px; background: rgba(0,0,0,0.3); border-radius: 10px; margin-bottom: 15px;"> <span style="color: #888; font-size: 12px;">You Earned</span><br> <span style="color: #28a745; font-size: 32px; font-weight: bold; text-shadow: 0 0 10px rgba(40,167,69,0.5);">$<<= _pay>></span> </div> <div class="prost-fade-delay2" style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; font-size: 13px;"> <div style="color: #b8a9c9;">⭐ Rep: +<<= _repGain>> (<<= $prostituteData.reputation>>)</div> <<= _regMsg>> <div style="color: #b8a9c9;">📊 <<= _svc ? _svc.xpType : ''>> XP: +<<= _svc ? _svc.xpAmount : 0>></div> <<if $currentArtifact === "The Basking Charm" || ($physicalTraits && $physicalTraits.includes("Naiad"))>><div style="color: #ffb300;">☀️ Basking Charm: 3x pay</div><</if>> <<if $activeTransformation === 'Salamander'>> <div style="color: #ff8c00;">🚨 +1 Police Heat (Salamander)</div> <<else>> <div style="color: #ff8c00;">🚨 +2 Police Heat</div> <</if>> <<if _traitGains.length > 0>> <div style="color: #ff1493; grid-column: 1 / -1;">✨ New Trait<<= _traitGains.length > 1 ? 's' : ''>>: <<= _traitGains.join(', ')>></div> <</if>> <<if $activeTransformation === 'Honeybee'>> <div style="color: #ffc107;">🍯 +1 Honey</div> <</if>> </div> </div> /* Next Actions */ <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"> <<if _nowExhausted>> <p style="color: #dc3545; font-style: italic; margin-bottom: 15px;">You're exhausted. Your body has had enough for tonight.</p> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #333, #555); color: #ccc; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Head Home</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> <<else>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Look for Another Client</div>">> <<goto "ProstClientSelect">> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #333, #555); color: #ccc; border: none; padding: 12px 24px; border-radius: 10px; font-size: 14px; cursor: pointer; display: inline-block;'>Call It a Night</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <<run setup.prostitute.addHeat(5)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 600px; margin: 20px auto; border: 2px solid #4dabf7; box-shadow: 0 0 25px rgba(77,171,247,0.3);"> <h3 style="color: #4dabf7; text-align: center; margin-bottom: 15px;">🚨 Police Patrol</h3> <p class="prost-prose">The flash of blue and red cuts through the neon haze. A patrol car crawls past, spotlight sweeping the sidewalk. Your heart hammers as the beam slides over you, pauses, then moves on. Too close. You press yourself deeper into the shadows, barely breathing, until the engine noise fades into the city's constant hum.</p> <p style="color: #dc3545; text-align: center; font-size: 13px; margin-top: 10px;">+5 Heat</p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Wait It Out, Then Keep Looking</div>">> <<run advanceTime(15)>> <<goto "ProstClientSelect">> <</link>> <<link "<div class='prost-btn' style='background: #333; color: #ccc; border: none; padding: 12px 24px; border-radius: 10px; font-size: 14px; cursor: pointer; display: inline-block;'>Too Risky - Head Home</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 600px; margin: 20px auto; border: 2px solid #dc3545; box-shadow: 0 0 25px rgba(220,53,69,0.3);"> <h3 style="color: #dc3545; text-align: center; margin-bottom: 15px;">⚠️ Bad Feeling</h3> <p class="prost-prose">Something's off about this one. The way they're looking at you — too intense, too hungry, and not in the paying kind of way. Your instincts scream danger. The smart move is to walk away. Now.</p> </div> <div class="prost-fade-delay1" style="display: flex; flex-direction: column; gap: 8px; max-width: 400px; margin: 20px auto;"> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #333, #555); color: #ccc; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; text-align: center;'>Walk Away Quickly</div>">> <<run advanceTime(15)>> <<goto "ProstClientSelect">> <</link>> <<if _traitEffects.availableChoices.indexOf('threaten') !== -1>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #dc3545, #c0392b); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; text-align: center;'>💪 Intimidate Them (Aggressive)</div>">> <<run setup.prostitute.addReputation(3)>> <<run advanceTime(10)>> <<goto "ProstClientSelect">> <</link>> <</if>> <<if _traitEffects.availableChoices.indexOf('standGround') !== -1>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #e67e22, #d35400); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; text-align: center;'>🛡️ Stand Your Ground (Brave)</div>">> <<run setup.prostitute.addReputation(2)>> <<run advanceTime(10)>> <<goto "ProstClientSelect">> <</link>> <</if>> <<if _traitEffects.availableChoices.indexOf('deescalate') !== -1>> <<link "<div class='prost-btn prost-choice' style='background: linear-gradient(135deg, #17a2b8, #138496); color: white; border: none; padding: 14px 24px; border-radius: 10px; font-size: 15px; cursor: pointer; text-align: center;'>✋ De-escalate (Calm)</div>">> <<run advanceTime(10)>> <<goto "ProstClientSelect">> <</link>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "Succubus")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #200010 50%, #3d0020 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(40, 0, 20, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #dc143c; box-shadow: 0 0 30px rgba(220,20,60,0.4);"> <h3 style="color: #dc143c; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(220,20,60,0.6);">🔥 Succubus: The Hunt</h3> <p class="prost-prose">Something shifts behind your eyes — something old and hungry. Your pupils catch the light wrong, reflecting crimson for a heartbeat. <<= _client.name>> doesn't notice. They wouldn't. They're already caught in the gravity of your presence, drawn forward like a moth to something far more dangerous than flame.</p> <p class="prost-prose prost-fade-delay1">You don't reach for them. You don't have to. They come to you, pulled by an ache they can't name, a need that started the moment your eyes met. Your skin hums with dark energy as their hand touches your arm, and you feel it — their vitality, warm and sweet, already beginning to flow.</p> <p class="prost-prose prost-fade-delay2">"Come with me," you whisper, and the words carry weight that has nothing to do with volume. <<= _client.name>> follows. They all follow.</p> </div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #dc143c, #8b0000); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(220,20,60,0.4);'>Feed...</div>">> <<set $prostSatisfaction += 20>> <<goto "ProstServiceSelect">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "Slut")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #2a0020 50%, #4d0035 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(40, 0, 30, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #ff69b4; box-shadow: 0 0 30px rgba(255,105,180,0.4);"> <h3 style="color: #ff69b4; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(255,105,180,0.6);">😋 Slut: Uninhibited</h3> <p class="prost-prose">You don't pretend. You don't perform. The hunger is real and you let it show in every look, every smile, every deliberate movement of your body. <<= _client.name>> sees it — the genuine craving in your eyes — and their own desire doubles in response.</p> <p class="prost-prose prost-fade-delay1">"I want you," you say, and mean it. No act, no professional distance. Just raw, honest need. You close the space between you and press your body against theirs, already breathing harder, already impatient for more. <<= _client.name>>'s hands find your hips and you moan at the contact — soft, eager, real.</p> <p class="prost-prose prost-fade-delay2">This isn't work. This is appetite. And tonight, <<= _client.name>> is exactly what you're hungry for.</p> </div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff69b4, #ff1493); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(255,105,180,0.4);'>Take What You Want...</div>">> <<set $prostSatisfaction += 25>> <<goto "ProstServiceSelect">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.stripTease>> <<run $prostituteData.actionCounts.stripTease++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('stripTease', _client.preference) + 4>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _chestDesc = setup.prostitute.getChestDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "StripTease", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e91e63; box-shadow: 0 0 20px rgba(233,30,99,0.3);"> <h3 style="color: #e91e63; text-align: center; margin-bottom: 15px;">💃 Strip Tease</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.stripTease, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.stripTease, _client.mood, _client.gender) : "You begin to move, slow and deliberate, letting your body tell a story. Each piece of clothing becomes a chapter — the shrug of a shoulder, the slide of fabric down your hip. " + _client.name + " watches with darkening eyes as more skin comes into view, their breath going shallow. You turn, showing the curve of your back, the line of your waist. By the time the last piece falls, the air between you is electric.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'stripTease'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.anal>> <<run $prostituteData.actionCounts.anal++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('anal', _client.preference) + 10>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _genDesc = setup.prostitute.getGenitalDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Anal", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #ff6b35; box-shadow: 0 0 20px rgba(255,107,53,0.3);"> <h3 style="color: #ff6b35; text-align: center; margin-bottom: 15px;">⚡ Anal</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.anal, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.anal, _client.mood, _client.gender) : "The intensity catches you both off guard. There is a moment of adjustment, of breath held and slowly released, and then " + _client.name + " finds a rhythm that makes thought impossible. The sensation is overwhelming — tight, forbidden, electric. Every nerve ending screams. You grip the sheets, the headboard, anything solid as the pleasure builds to something almost unbearable.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'anal'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.titfuck>> <<run $prostituteData.actionCounts.titfuck++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('titfuck', _client.preference) + 7>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _chestDesc = setup.prostitute.getChestDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<set _isRaijuTitfuck = $physicalTraits && $physicalTraits.includes("Raiju")>> <<if _isRaijuTitfuck>> <div style="text-align: center; margin: 0 auto 15px; max-width: 650px;"><img src="Images/Jobs/Prostitute/RaijuBoobJob.webp" alt="Raiju boob job" style="max-width: 100%; height: auto; border-radius: 12px; border: 2px solid #f1c40f; box-shadow: 0 0 25px rgba(241,196,15,0.4);" /></div> <<else>> <<= setup.sceneImage("prost_service", "Titfuck", _imgGender)>> <</if>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e91e63; box-shadow: 0 0 20px rgba(233,30,99,0.3);"> <h3 style="color: #e91e63; text-align: center; margin-bottom: 15px;"><<if _isRaijuTitfuck>>⚡ Electric Titfuck<<else>>🍑 Titfuck<</if>></h3> <<if _isRaijuTitfuck>> <p class="prost-prose">You guide <<= _client.name>> down onto the cushions and straddle their chest, static already crackling between your fingers. Their eyes drop to your breasts and stay there, pupils blown wide. Good. You like a client who pays attention. You press your breasts around them and squeeze, and the contact lights up gold where your skin meets theirs. Tiny arcs of lightning jump between your nipples and the stomach beneath you. They make a sound that is half groan, half nervous laugh, and then forget how to make either.</p> <p class="prost-prose">You start slow. The first downstroke pours current straight into the most sensitive part of them, and you feel their whole body jerk between your thighs. The voltage is yours to control. You ramp it up with every pass, the slide of skin on skin generating its own charge that the Raiju in you amplifies and feeds back through every point of contact. On the upstroke your tongue extends to catch the head, sparks dancing from the tip of it, and they swear in a language you do not recognize. By the third pass the sounds they are making have no language at all.</p> <p class="prost-prose">You can feel their heartbeat through your palms where you hold yourself pressed together. You tune the pulses of electricity to it, then start running them slightly faster, pulling their pulse up with the rhythm. Their hips buck helplessly into your chest. Their hands fist in the cushions. The sparks have become visible now, tiny lightning leaping between your skin and theirs, and the smell of ozone is mixing with sweat and want. They cannot look away from what you are doing to them. They cannot speak. They cannot do anything except shake under you and try to remember how to breathe.</p> <<else>> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.titfuck, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.titfuck, _client.mood, _client.gender) : "You press your breasts together around " + _client.name + " and watch their eyes go glassy. The slide of skin on skin, the visual of their cock disappearing between your curves, it undoes them faster than either of you expected. You set the pace, squeezing, shifting your angle, watching their face for the tells that say you have found the perfect rhythm.">></p> <</if>> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'titfuck'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.sixtynine>> <<run $prostituteData.actionCounts.sixtynine++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('sixtynine', _client.preference) + 9>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _genDesc = setup.prostitute.getGenitalDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "SixtyNine", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #9b59b6; box-shadow: 0 0 20px rgba(155,89,182,0.3);"> <h3 style="color: #9b59b6; text-align: center; margin-bottom: 15px;">♾️ 69</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.sixtynine, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.sixtynine, _client.mood, _client.gender) : "The position is intimate in a way that catches you off guard — your mouth on " + _client.name + " while they return the favor, both of you giving and receiving simultaneously. Concentration becomes impossible when their tongue does that thing, and your rhythm falters. They moan against you and the vibration sends sparks up your spine. It becomes a feedback loop of pleasure, each of you driving the other higher.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'sixtynine'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.roleplay>> <<run $prostituteData.actionCounts.roleplay++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('roleplay', _client.preference) + 8>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Roleplay", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e67e22; box-shadow: 0 0 20px rgba(230,126,34,0.3);"> <h3 style="color: #e67e22; text-align: center; margin-bottom: 15px;">🎭 Roleplay</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.roleplay, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.roleplay, _client.mood, _client.gender) : "You slip into the character like a second skin. The scenario " + _client.name + " wants unfolds between you — part improv, part fantasy, entirely convincing. You match their energy, feed their imagination, become exactly what they need you to be. The line between performance and reality blurs until neither of you is sure where the act ends and the desire begins.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'roleplay'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.domination>> <<run $prostituteData.actionCounts.domination++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('domination', _client.preference) + 10>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Domination", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #dc3545; box-shadow: 0 0 20px rgba(220,53,69,0.3);"> <h3 style="color: #dc3545; text-align: center; margin-bottom: 15px;">🔗 Domination</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.domination, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.domination, _client.mood, _client.gender) : "You take control and " + _client.name + " yields like they have been waiting their whole life for someone to give them permission to let go. Your voice drops low, commanding, and you watch the shiver run through them. Every instruction is obeyed instantly. Every touch is a reward. You push their boundaries exactly as far as they want to go, reading the line between ecstasy and too-much with practiced precision.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'domination'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.submission>> <<run $prostituteData.actionCounts.submission++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('submission', _client.preference) + 9>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Submission", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #8e44ad; box-shadow: 0 0 20px rgba(142,68,173,0.3);"> <h3 style="color: #8e44ad; text-align: center; margin-bottom: 15px;">🫦 Submission</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.submission, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.submission, _client.mood, _client.gender) : "You surrender, and it feels like freedom. " + _client.name + " takes the lead with a confidence that makes your pulse quicken. Their hands position you, their voice tells you what to do, and you obey — not because you have to but because the giving-up-of-control sends liquid heat through your veins. Every command is a gift. Every act of obedience draws a sound from your throat that surprises even you.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'submission'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.gfe>> <<run $prostituteData.actionCounts.gfe++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('gfe', _client.preference) + 12>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _genDesc = setup.prostitute.getGenitalDescription()>> <<set _chestDesc = setup.prostitute.getChestDescription()>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "GFE", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #e91e90; box-shadow: 0 0 20px rgba(233,30,144,0.3);"> <h3 style="color: #e91e90; text-align: center; margin-bottom: 15px;">💞 Girlfriend Experience</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.gfe, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.gfe, _client.mood, _client.gender) : "This is not a transaction — or at least, for the next hour, you both pretend it is not. " + _client.name + " holds your hand. Laughs at your jokes. Tells you about their day while you curl against them on hotel sheets. The sex, when it comes, is unhurried and tender, full of eye contact and murmured names and the kind of touching that exists purely to make the other person feel cherished.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'gfe'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _svc = setup.prostitute.services.fetish>> <<run $prostituteData.actionCounts.fetish++>> <<set $prostSatisfaction += setup.prostitute.getPreferenceMatch('fetish', _client.preference) + 8>> <<set _voiceEffects = setup.prostitute.getVoiceEffects()>> <<set $prostSatisfaction += _voiceEffects.satisfactionBonus>> <<set _imgGender = setup.getScenePairing($bodyParts.gender, $prostCurrentClient.gender)>> <<= setup.sceneImage("prost_service", "Fetish", _imgGender)>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a2e 50%, #2d1b4e 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #6c5ce7; box-shadow: 0 0 20px rgba(108,92,231,0.3);"> <h3 style="color: #6c5ce7; text-align: center; margin-bottom: 15px;">🪄 Fetish</h3> <p class="prost-prose"><<= setup.prostitute.scenes.service && setup.prostitute.getSceneText(setup.prostitute.scenes.service.fetish, _client.mood, _client.gender) ? setup.prostitute.getSceneText(setup.prostitute.scenes.service.fetish, _client.mood, _client.gender) : "Everyone has a thing. " + _client.name + " shares theirs with a mix of shame and excitement, and you meet it without flinching. You have done this before, or something close enough. Your hands are steady, your voice reassuring, and you give them exactly what they need — the specific, particular thing that no vanilla encounter ever touches. Their gratitude is physical, trembling, unmistakable.">></p> </div> <div class="prost-fade-delay1" style="text-align: center; margin-top: 15px; color: #888; font-size: 13px;"> <p><<= setup.prostitute.getSatisfactionHint($prostSatisfaction, _client.name)>></p> </div> <div class="prost-fade-delay2" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff1493, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Bring Them to the Edge...</div>">> <<set $prostSelectedServiceKey = 'fetish'>> <<goto "ProstClimax">> <</link>> </div> </div> <</nobr>>
<<nobr>><<run setup.prostitute.injectCSS()>><<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "Siren")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #001a33 50%, #002244 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #1a75ff; box-shadow: 0 0 30px rgba(26,117,255,0.4);"><h3 style="color: #1a75ff; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(26,117,255,0.6);">🎶 Siren: The Song</h3><p class="prost-prose">The melody begins before you realize you are singing — a low hum that rises from your chest and wraps around <<= _client.name>> like invisible hands. Their eyes glaze. Their body sways toward you, drawn by a sound that bypasses their ears entirely and speaks directly to the wanting at the center of their nervous system.</p><p class="prost-prose prost-fade-delay1">You lean close and let the song become words — their name, their desires, the secret rhythms of their heartbeat echoed back to them in a melody only they can hear. <<= _client.name>> shivers, mouth falling open, lost in the music of your voice. Every syllable is a hook sunk deep. Every pause is exquisite torture.</p><p class="prost-prose prost-fade-delay2">"Let me sing you open," you whisper, and the words carry a harmony that vibrates in their spine. They nod, unable to refuse, unable to want to refuse. The song has them. You have them. What follows will be conducted entirely by your voice.</p></div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #1a75ff, #00ced1); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(26,117,255,0.4);'>Let the Song Build...</div>">> <<set $prostSatisfaction += 20>> <<goto "ProstServiceSelect">> <</link>></div> </div><</nobr>>
<<nobr>><<run setup.prostitute.injectCSS()>><<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "Cupid")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0020 50%, #330025 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #b76e79; box-shadow: 0 0 30px rgba(183,110,121,0.4);"><h3 style="color: #b76e79; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(183,110,121,0.6);">💘 Cupid: Connection</h3><p class="prost-prose">You take <<= _client.name>>'s hand and the golden warmth flows between you like a current. Not desire — something deeper, older, more dangerous. Connection. They look into your eyes and for a vertiginous second they see themselves reflected back with perfect, terrifying clarity. Seen. Known. Wanted anyway.</p><p class="prost-prose prost-fade-delay1">The tenderness is not a technique. You could not fake this if you tried — the genuine ache of compassion that moves through your chest when you touch them, the sincere desire to give them something real in a world of transactions. <<= _client.name>> feels it and their armor cracks. A breath they have been holding for months escapes their lungs.</p><p class="prost-prose prost-fade-delay2">"You are safe with me," you say, and the words carry weight because they are true. Tonight, in this room, with you, they are. The golden thread between you pulses with warmth. They lean into it. What follows will feel like love. It is not. But it is close enough to heal.</p></div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #b76e79, #c71585); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(183,110,121,0.4);'>Open Your Heart...</div>">> <<set $prostSatisfaction += 25>> <<goto "ProstServiceSelect">> <</link>></div> </div><</nobr>>
<<nobr>><<run setup.prostitute.injectCSS()>><<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "TrophyWife")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a1500 50%, #2d2200 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #daa520; box-shadow: 0 0 30px rgba(218,165,32,0.4);"><h3 style="color: #daa520; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(218,165,32,0.6);">👑 Trophy Wife: Luxury</h3><p class="prost-prose">You sweep into the room like you own it — because in every way that matters, you do. The silk of your dress catches the light. The diamonds at your throat flash fire. <<= _client.name>> stares, and you watch them recalibrate their entire evening upward. Whatever they expected, it was not this. Not you. Not this level of exquisite, untouchable beauty.</p><p class="prost-prose prost-fade-delay1">"Champagne?" you offer, producing a bottle that costs more than the room. The gesture is effortless, as natural as breathing. You pour with the practiced grace of someone who has never served themselves, and the crystal flute catches the light like a prism. <<= _client.name>> takes the glass with hands that tremble slightly. They are upgrading. They can feel it.</p><p class="prost-prose prost-fade-delay2">You touch their cheek with one perfectly manicured fingertip. "Tonight," you murmur, "you deserve the best." They believe you. They believe you because you are the best, and your presence makes that impossible to doubt. What follows will be the finest experience money can buy.</p></div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #daa520, #ffd700); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(218,165,32,0.4);'>The VIP Treatment...</div>">> <<set $prostSatisfaction += 15>> <<goto "ProstServiceSelect">> <</link>></div> </div><</nobr>>
<<nobr>><<run setup.prostitute.injectCSS()>><<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "Dominatrix")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #0d0020 50%, #1a0030 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #800080; box-shadow: 0 0 30px rgba(128,0,128,0.4);"><h3 style="color: #800080; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(128,0,128,0.6);">⛓️ Dominatrix: Command</h3><p class="prost-prose">The room contracts when you enter it. The air tightens. <<= _client.name>> looks up at you and you watch the submission happen in real time — shoulders dropping, chin lowering, eyes widening with a mix of terror and desperate hope. They did not book a service. They booked a surrender. You are here to accept it.</p><p class="prost-prose prost-fade-delay1">"Kneel," you say. The word is not loud. It does not need to be. Authority does not shout — it commands, and commands are obeyed. <<= _client.name>> sinks to the floor with a reverence that borders on religious. You circle them slowly, boots clicking on tile, one gloved hand trailing across their shoulder. The leather is warm. Their skin prickles.</p><p class="prost-prose prost-fade-delay2">"Tonight," you continue, your voice silk over steel, "you do not think. You do not decide. You do not resist." You tilt their chin up with one finger. Their eyes are glassy, already floating. "You simply obey. And if you are very, very good…" A smile. Cool. Devastating. "I will reward you."</p></div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #800080, #4b0082); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(128,0,128,0.4);'>Take Control...</div>">> <<set $prostSatisfaction += 20>> <<goto "ProstServiceSelect">> <</link>></div> </div><</nobr>>
<<nobr>><<run setup.prostitute.injectCSS()>><<set _client = $prostCurrentClient>> <<= setup.sceneImage("prost_transform", "Kitsune")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a1000 50%, #2d1a00 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #ff8c00; box-shadow: 0 0 30px rgba(255,140,0,0.4);"><h3 style="color: #ff8c00; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(255,140,0,0.6);">🦊 Kitsune: Fox Charm</h3><p class="prost-prose">Your smile sharpens and the foxfire blooms behind your eyes — golden, flickering, ancient. <<= _client.name>> blinks and for a moment they see something impossible: shadows behind you shaped like nine tails, fanning out and folding away like a dream they cannot quite catch. The charm settles over them like warm honey, sweet and inescapable.</p><p class="prost-prose prost-fade-delay1">"Come closer," you purr, and the words carry an enchantment that has been refined over centuries. <<= _client.name>> moves toward you as if pulled by invisible strings, their face slack with wonder. You trace a claw-tipped finger down their cheek — gently, playfully — and they shiver as the fox magic seeps through their skin, turning every nerve ending up to eleven.</p><p class="prost-prose prost-fade-delay2">You circle them, trailing your hand across their back, around their waist, letting the enchantment build. "Shall we play?" you ask, and the mischief in your voice is ancient and utterly irresistible. They nod. They would agree to anything. The fox grins. Tonight will be delicious.</p></div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ff8c00, #ff6347); color: white; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 0 15px rgba(255,140,0,0.4);'>Let the Charm Work...</div>">> <<set $prostSatisfaction += 20>> <<goto "ProstServiceSelect">> <</link>></div> </div><</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _legendPay = 0>> <<set _legendSat = 50>> <<set _traitEffects = setup.prostitute.getTraitEffects()>> <div style="background: linear-gradient(135deg, #0a0014 0%, #1a0a2e 30%, #2d1520 60%, #0a0014 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <!-- PHASE 1: THE ARRIVAL --> <div class="prost-fade" style="background: rgba(26, 10, 46, 0.9); border-radius: 15px; padding: 30px; max-width: 700px; margin: 20px auto; border: 2px solid #ffd700; box-shadow: 0 0 40px rgba(255,215,0,0.3);"> <h2 style="color: #ffd700; text-align: center; margin-bottom: 20px; text-shadow: 0 0 20px rgba(255,215,0,0.6); font-size: 28px;">👑 The Legend Encounter</h2> <p class="prost-prose">The car is a Rolls-Royce — black as a moonless sky, gleaming under the streetlights like polished obsidian. The driver opens the door for you without a word, and you slide into a leather interior that smells of sandalwood and old money. The city falls away behind tinted glass as you are driven to a part of Sunfish City you have never seen: a private tower overlooking the harbor, lit from within by warm amber light.</p> <p class="prost-prose prost-fade-delay1">The elevator opens directly into a penthouse suite. Floor-to-ceiling windows frame the entire coastline, city lights scattered like fallen stars across the dark water. A grand piano sits in one corner, a fully stocked bar in another. Everything is tasteful, understated, impossibly expensive. And there, standing at the window with a glass of something amber, is your client.</p> <p class="prost-prose prost-fade-delay2">They turn to face you, and you understand immediately why they sent a car. This is not someone who walks the streets. This is someone who owns them. Tall, composed, ageless in the way that immense wealth can make a person — somewhere between forty and eternity. Their eyes find yours with an intensity that makes your skin prickle.</p> <p class="prost-prose prost-fade-delay2" style="color: #ffd700; font-style: italic;">"So you are the one everyone has been talking about," they say, and their voice is silk over steel. "I had to see for myself."</p> </div> <!-- PHASE 2: THE CHOICE --> <div class="prost-fade-delay3" style="background: rgba(26, 10, 46, 0.8); border-radius: 15px; padding: 25px; max-width: 700px; margin: 15px auto; border: 1px solid rgba(255,215,0,0.3);"> <p style="color: #b8a9c9; text-align: center; margin-bottom: 15px; font-size: 14px;">How do you present yourself to the most powerful client you have ever encountered?</p> <div style="display: flex; flex-direction: column; gap: 10px; max-width: 500px; margin: 0 auto;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, rgba(255,215,0,0.2), rgba(218,165,32,0.1)); border: 1px solid #daa520; color: #ffd700; padding: 14px 20px; border-radius: 10px; font-size: 14px; cursor: pointer; text-align: left;'>👑 <b>Match their energy</b> — You belong in rooms like this. Show them you are not intimidated.</div>">> <<set _legendSat += 15>> <<replace "#legend-scene">><p class="prost-prose">You meet their gaze without flinching, letting the corner of your mouth curl into something between a smile and a challenge. "Everyone talks," you say, crossing the marble floor with measured confidence. "I prefer to demonstrate." Something shifts in their expression — surprise, then delight. They lift their glass in a silent toast. You have passed the first test.</p> <p class="prost-prose">They gesture to the bar. "Drink?" It is not really a question. You pour yourself something aged and amber, letting the silence stretch. In rooms like this, silence is currency, and you spend it well. When you finally turn back to them, the distance between you has somehow closed to inches.</p> <span id="legend-continue"></span><</replace>> <<replace "#legend-continue">><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 12px 30px; border-radius: 10px; font-size: 15px; font-weight: bold; cursor: pointer; display: inline-block; margin-top: 15px; text-align: center;'>Continue...</div>">><<replace "#legend-phase3">> <div style="background: rgba(26,10,46,0.8); border-radius: 15px; padding: 25px; max-width: 700px; margin: 15px auto; border: 1px solid rgba(255,215,0,0.3);"> <p class="prost-prose">What follows is unlike anything you have experienced. There is no rush, no awkwardness, no transaction. They move with you like a conversation between equals — each touch a question, each response an answer. The penthouse becomes a world unto itself, the city below forgotten.</p> <p class="prost-prose">They know what they want, but more importantly, they know how to make you feel wanted. Not as a service provider. As a person who has earned their attention through sheer, undeniable skill and presence. Hours pass like minutes. The sheets are Egyptian cotton. The champagne is vintage. And the pleasure — the pleasure is mutual, genuine, and extraordinary.</p> <p class="prost-prose" style="color: #ffd700; font-style: italic;">"They were right about you," they murmur afterward, tracing a line down your shoulder. "You really are something else."</p> <span id="legend-finale"></span> </div><</replace>> <<replace "#legend-finale">><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 12px 30px; border-radius: 10px; font-size: 15px; font-weight: bold; cursor: pointer; display: inline-block; margin-top: 15px; text-align: center;'>The Aftermath...</div>">> <<set _legendPay = Math.floor((100 + Math.floor(Math.random() * 51)) * 10)>> <<set $money += _legendPay>> <<set $prostituteData.totalEarnings += _legendPay>> <<set $prostituteData.totalClients++>> <<set $prostituteData.sexualEncounters++>> <<set $prostituteData.legendComplete = true>> <<set $prostituteData.legendPayBonus = 0.05>> <<run setup.prostitute.addReputation(50)>> <<replace "#legend-phase3">> <div style="background: rgba(26,10,46,0.9); border-radius: 15px; padding: 30px; max-width: 700px; margin: 15px auto; border: 2px solid #ffd700; box-shadow: 0 0 30px rgba(255,215,0,0.4);"> <h3 style="color: #ffd700; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(255,215,0,0.5);">👑 A Legend is Born</h3> <p class="prost-prose">As dawn begins to paint the harbor in shades of rose and gold, they press an envelope into your hand. Inside is more money than you have ever seen from a single encounter — crisp bills, neatly stacked, accompanied by a handwritten note on cream-colored stationery.</p> <p class="prost-prose" style="color: #ffd700; font-style: italic; text-align: center; font-size: 16px; margin: 20px 0;">"Worth every penny. My people will speak your name. — V."</p> <div style="background: rgba(255,215,0,0.1); border-radius: 12px; padding: 20px; border: 1px solid rgba(255,215,0,0.3); margin: 15px 0;"> <p style="color: #28a745; font-size: 24px; font-weight: bold; text-align: center; margin-bottom: 10px;">$<<= _legendPay>> earned</p> <p style="color: #ffd700; text-align: center; font-size: 14px; margin-bottom: 5px;">⭐ +50 Reputation</p> <p style="color: #ff1493; text-align: center; font-size: 14px; font-weight: bold;">👑 Legendary Status Achieved! Permanent +5% pay bonus on all encounters.</p> </div> <p class="prost-prose" style="font-style: italic; color: #b8a9c9;">The car takes you home as the sun rises. You lean back against the leather seat and watch Sunfish City wake up around you, knowing that nothing will be quite the same. Word travels fast in these circles. You are no longer just good at what you do. You are legendary.</p> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 14px 30px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 20px rgba(255,215,0,0.4);'>Return Home</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> </div> </div><</replace>> <</link>><</replace>> <</link>><</replace>> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, rgba(199,21,133,0.3), rgba(255,20,147,0.2)); border: 1px solid #c71585; color: #ff69b4; padding: 14px 20px; border-radius: 10px; font-size: 14px; cursor: pointer; text-align: left;'>💃 <b>Seduce them slowly</b> — Let the anticipation build. Make them come to you.</div>">> <<set _legendSat += 20>> <<replace "#legend-scene">><p class="prost-prose">You do not cross the room. You let the room come to you. You settle onto the velvet chaise by the window, crossing your legs with deliberate slowness, and watch the city lights reflect in the glass. You can feel their eyes on you like a physical weight — measuring, appreciating. You give them nothing for free. Every glance is earned.</p> <p class="prost-prose">"May I?" they ask, gesturing to the space beside you, and the fact that someone this powerful is asking your permission sends a thrill through you. You nod, just once, and they sit. Close, but not touching. The air between you hums with potential energy. You lean in — not to kiss, just to breathe them in — and they shiver.</p> <span id="legend-continue"></span><</replace>> <<replace "#legend-continue">><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 12px 30px; border-radius: 10px; font-size: 15px; font-weight: bold; cursor: pointer; display: inline-block; margin-top: 15px; text-align: center;'>Continue...</div>">><<replace "#legend-phase3">> <div style="background: rgba(26,10,46,0.8); border-radius: 15px; padding: 25px; max-width: 700px; margin: 15px auto; border: 1px solid rgba(255,215,0,0.3);"> <p class="prost-prose">You make them wait. And wait. And when they finally cannot bear another second and close the distance, you reward them with everything — every skill you have honed, every technique you have mastered, every instinct sharpened through hundreds of encounters. But this time, it is art. Not performance. Art.</p> <p class="prost-prose">The night unfolds like a symphony, each movement building on the last. They gasp and you drink it in. They whisper your name and it sounds like a prayer. By the time the first hint of dawn touches the horizon, they are lying beside you, breathless, undone, looking at you with something dangerously close to reverence.</p> <p class="prost-prose" style="color: #ffd700; font-style: italic;">"I have never..." they start, then laugh softly. "I was going to say I have never experienced anything like that, but that feels insufficient. You have ruined me for anyone else."</p> <span id="legend-finale"></span> </div><</replace>> <<replace "#legend-finale">><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 12px 30px; border-radius: 10px; font-size: 15px; font-weight: bold; cursor: pointer; display: inline-block; margin-top: 15px; text-align: center;'>The Aftermath...</div>">> <<set _legendPay = Math.floor((100 + Math.floor(Math.random() * 51)) * 10)>> <<set $money += _legendPay>> <<set $prostituteData.totalEarnings += _legendPay>> <<set $prostituteData.totalClients++>> <<set $prostituteData.sexualEncounters++>> <<set $prostituteData.legendComplete = true>> <<set $prostituteData.legendPayBonus = 0.05>> <<run setup.prostitute.addReputation(50)>> <<replace "#legend-phase3">> <div style="background: rgba(26,10,46,0.9); border-radius: 15px; padding: 30px; max-width: 700px; margin: 15px auto; border: 2px solid #ffd700; box-shadow: 0 0 30px rgba(255,215,0,0.4);"> <h3 style="color: #ffd700; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(255,215,0,0.5);">👑 A Legend is Born</h3> <p class="prost-prose">They call you a car before the sun is fully up. But first, the envelope. Heavy, cream-colored, sealed with actual wax. Inside, more money than most people earn in a month — and a card with a single letter embossed in gold.</p> <p class="prost-prose" style="color: #ffd700; font-style: italic; text-align: center; font-size: 16px; margin: 20px 0;">"For the finest night of my life. The world will know your name. — V."</p> <div style="background: rgba(255,215,0,0.1); border-radius: 12px; padding: 20px; border: 1px solid rgba(255,215,0,0.3); margin: 15px 0;"> <p style="color: #28a745; font-size: 24px; font-weight: bold; text-align: center; margin-bottom: 10px;">$<<= _legendPay>> earned</p> <p style="color: #ffd700; text-align: center; font-size: 14px; margin-bottom: 5px;">⭐ +50 Reputation</p> <p style="color: #ff1493; text-align: center; font-size: 14px; font-weight: bold;">👑 Legendary Status Achieved! Permanent +5% pay bonus on all encounters.</p> </div> <p class="prost-prose" style="font-style: italic; color: #b8a9c9;">In the car, you press your forehead against the cool glass and smile. The city stretches out before you, and for the first time, it feels small. You have climbed to the very top. Word of tonight will spread through whispers and knowing glances, through exclusive circles you did not even know existed. You are a legend now.</p> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 14px 30px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 20px rgba(255,215,0,0.4);'>Return Home</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> </div> </div><</replace>> <</link>><</replace>> <</link>><</replace>> <</link>> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, rgba(128,0,128,0.3), rgba(75,0,130,0.2)); border: 1px solid #9b59b6; color: #dda0dd; padding: 14px 20px; border-radius: 10px; font-size: 14px; cursor: pointer; text-align: left;'>✨ <b>Be yourself</b> — No act, no persona. Let them see the real you.</div>">> <<set _legendSat += 25>> <<replace "#legend-scene">><p class="prost-prose">You take a breath. And then you do the most dangerous thing you can do in a room this expensive: you drop the act entirely. No studied confidence, no calculated seduction. You walk over to the window, stand beside them, and look out at the city you both call home.</p> <p class="prost-prose">"Nice view," you say, and it comes out genuine, almost casual. They blink. Then they laugh — a real laugh, surprised and warm, and the mask they were wearing cracks too. "You are not what I expected," they admit, and there is something almost vulnerable in it. "Good," you reply, and mean it.</p> <span id="legend-continue"></span><</replace>> <<replace "#legend-continue">><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 12px 30px; border-radius: 10px; font-size: 15px; font-weight: bold; cursor: pointer; display: inline-block; margin-top: 15px; text-align: center;'>Continue...</div>">><<replace "#legend-phase3">> <div style="background: rgba(26,10,46,0.8); border-radius: 15px; padding: 25px; max-width: 700px; margin: 15px auto; border: 1px solid rgba(255,215,0,0.3);"> <p class="prost-prose">What happens next is not a performance. It is a connection. Two people, stripped of pretense, finding each other in the dark. You bring everything you know — every technique, every instinct — but you also bring yourself, unguarded and real. And it transforms the encounter into something neither of you expected.</p> <p class="prost-prose">They hold you afterward, and for once it does not feel like part of the job. The silence between you is comfortable, warm, full of unspoken things. You watch the stars through the ceiling-high windows and feel, for just a moment, that this is what all those nights on the street were building toward.</p> <p class="prost-prose" style="color: #ffd700; font-style: italic;">"Stay for breakfast?" they ask, and their voice is softer than before. "Not as a client. Just... stay."</p> <span id="legend-finale"></span> </div><</replace>> <<replace "#legend-finale">><<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 12px 30px; border-radius: 10px; font-size: 15px; font-weight: bold; cursor: pointer; display: inline-block; margin-top: 15px; text-align: center;'>The Aftermath...</div>">> <<set _legendPay = Math.floor((100 + Math.floor(Math.random() * 51)) * 10)>> <<set $money += _legendPay>> <<set $prostituteData.totalEarnings += _legendPay>> <<set $prostituteData.totalClients++>> <<set $prostituteData.sexualEncounters++>> <<set $prostituteData.legendComplete = true>> <<set $prostituteData.legendPayBonus = 0.05>> <<run setup.prostitute.addReputation(50)>> <<replace "#legend-phase3">> <div style="background: rgba(26,10,46,0.9); border-radius: 15px; padding: 30px; max-width: 700px; margin: 15px auto; border: 2px solid #ffd700; box-shadow: 0 0 30px rgba(255,215,0,0.4);"> <h3 style="color: #ffd700; text-align: center; margin-bottom: 15px; text-shadow: 0 0 15px rgba(255,215,0,0.5);">👑 A Legend is Born</h3> <p class="prost-prose">You stay for breakfast. Eggs Benedict, fresh orange juice, coffee that costs more per cup than you used to make in an entire night. And when it is finally time to go, they walk you to the elevator themselves. No envelope this time. Instead, they press a folded check into your hand and close your fingers around it.</p> <p class="prost-prose" style="color: #ffd700; font-style: italic; text-align: center; font-size: 16px; margin: 20px 0;">"You gave me something money cannot buy. This is the best I can do in return. — V."</p> <div style="background: rgba(255,215,0,0.1); border-radius: 12px; padding: 20px; border: 1px solid rgba(255,215,0,0.3); margin: 15px 0;"> <p style="color: #28a745; font-size: 24px; font-weight: bold; text-align: center; margin-bottom: 10px;">$<<= _legendPay>> earned</p> <p style="color: #ffd700; text-align: center; font-size: 14px; margin-bottom: 5px;">⭐ +50 Reputation</p> <p style="color: #ff1493; text-align: center; font-size: 14px; font-weight: bold;">👑 Legendary Status Achieved! Permanent +5% pay bonus on all encounters.</p> </div> <p class="prost-prose" style="font-style: italic; color: #b8a9c9;">You walk home. Not because you have to, but because you want to feel the morning air on your skin and watch Sunfish City come alive. People pass you on the sidewalk, oblivious. They have no idea that the person walking beside them just had the most extraordinary night of their life. But you know. And soon, everyone who matters will know too.</p> <div style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #ffd700, #daa520); color: #1a0a2e; padding: 14px 30px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 20px rgba(255,215,0,0.4);'>Return Home</div>">> <<set $prostEncountersThisSession = 0>> <<goto $prostReturnPassage>> <</link>> </div> </div><</replace>> <</link>><</replace>> <</link>><</replace>> <</link>> </div> </div> <!-- Scene display area --> <div id="legend-scene"></div> <!-- Phase 3 display area --> <div id="legend-phase3"></div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _targets = setup.npcSocial.getSocialTargets(_npc, $currentTopic)>> <div style="max-width: 600px; margin: 0 auto;"> <h2 style="color: #26c6da; text-align: center;">Choose Someone</h2> <p style="color: #aaa; text-align: center; margin-bottom: 20px;"><<= $currentTopicData.label>></p> <<if _targets.length === 0>> <p style="color: #888; text-align: center; font-style: italic;">You haven't met anyone else yet.</p> <<else>> <div style="display: grid; gap: 8px;"> <<for _tIdx = 0; _tIdx < _targets.length; _tIdx++>> <<capture _tIdx>> <<set _targetName = _targets[_tIdx]>> <<set _relKey = setup.getNpcRelationshipKey(_npc.name, _targetName)>> <<set _relData = State.variables.npcToNpcRelationships[_relKey]>> <<if _relData && _relData.type !== "strangers">> <<set _relLabel = _relData.typeName>> <<set _relColor = _relData.color || "#26c6da">> <<elseif setup.npcSocial.shareWorkplace(_npc.name, _targetName)>> <<set _workLabel = setup.npcSocial.getWorkplaceLabel(_npc.name, _targetName)>> <<set _relLabel = _workLabel>> <<set _relColor = "#66bb6a">> <<else>> <<set _relLabel = "">> <<set _relColor = "#666">> <</if>> <div style="background: #1a1a1a; padding: 12px 15px; border-radius: 8px; border: 2px solid #26c6da; cursor: pointer;"> <<if _relLabel>> <<link `'<span style="color: #26c6da; font-weight: bold;">' + _targetName + '</span> <span style="color: ' + _relColor + '; font-size: 12px;">(' + _relLabel + ')</span>'`>> <<set $socialTarget = _targets[_tIdx]>> <<goto "NPCTalkResponse">> <</link>> <<else>> <<link `'<span style="color: #26c6da; font-weight: bold;">' + _targetName + '</span>'`>> <<set $socialTarget = _targets[_tIdx]>> <<goto "NPCTalkResponse">> <</link>> <</if>> </div> <</capture>> <</for>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<span style='color: #888;'>Go Back</span>">><<goto "NPCTalk">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _sPers = setup.romance.getSexualPersonality(_npc)>> <<set _romLevel = setup.romance.getRomanceLevel(_npc.name)>> <<set _chemistry = setup.romance.getChemistry(_npc)>> <<set _opts = setup.romance.getApproachOptions(_npc)>> <<set _isFirst = setup.romance.isFirstTime(_npc.name)>> <<set _npcName = _npc.name>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 30px;"> <div style="font-size: 28px; color: #e91e63; text-shadow: 0 0 15px rgba(233,30,99,0.5);">❤ Intimate Moment</div> <div style="font-size: 18px; color: #f48fb1; margin-top: 8px;">with <<= _npcName>></div> </div> <<if _isFirst>> <div style="background: rgba(233,30,99,0.15); border: 1px solid #e91e63; border-radius: 8px; padding: 15px; margin-bottom: 20px; text-align: center; font-style: italic; color: #f8bbd0;"> ✨ This will be your first time together... </div> <</if>> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 20px; margin-bottom: 25px;"> <div style="font-size: 16px; color: #ce93d8; margin-bottom: 15px;">How do you want this moment to feel?</div> <<for _opt range _opts>> <<capture _opt>> <<set _apLabel = _opt.approach.charAt(0).toUpperCase() + _opt.approach.slice(1)>> <<set _apIcon = _opt.approach === "gentle" ? "🌸" : (_opt.approach === "passionate" ? "🔥" : (_opt.approach === "playful" ? "✨" : "⚡"))>> <<set _apColor = _opt.approach === "gentle" ? "#f8bbd0" : (_opt.approach === "passionate" ? "#ef5350" : (_opt.approach === "playful" ? "#ce93d8" : "#ff7043"))>> <<set _hintText = _opt.hint ? " <span style='font-size: 12px; color: #aaa; font-style: italic;'>(" + _opt.hint + ")</span>" : "">> <<set _btnHtml = "<div style='background: rgba(255,255,255,0.08); border: 1px solid " + _apColor + "; border-radius: 8px; padding: 12px 18px; margin: 8px 0; cursor: pointer; transition: all 0.3s;'><span style='font-size: 18px;'>" + _apIcon + "</span> <span style='color: " + _apColor + "; font-weight: bold;'>" + _apLabel + "</span>" + _hintText + "</div>">> <<link _btnHtml>> <<set $romanceApproach = _opt.approach>> <<if _romLevel === "dating">> <<goto "RomanceKiss">> <<elseif _romLevel === "exclusive">> <<goto "RomanceMakeOut">> <<else>> <<goto "RomanceBuildUp">> <</if>> <</link>> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='color: #999; padding: 10px; cursor: pointer;'>Maybe another time...</div>">> <<goto "NPCTalk">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _sceneText = setup.romance.getSceneText("kissing", setup.romance.getSexualPersonality(_npc), $romanceApproach, null, _npc.bodyParts.gender)>> <<set _sat = setup.romance.calculateSatisfaction(_npc, $romanceApproach, "emotional")>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #f48fb1;">💋 A Kiss with <<= _npc.name>></div> </div> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 25px; margin-bottom: 25px; line-height: 1.8; font-size: 15px;"> <<= _sceneText>> </div> <<set _result = setup.romance.processScene(_npc.name, "kissing", $romanceApproach, _sat, "emotional")>> <<set _tier = _result.tier>> <div style="background: rgba(233,30,99,0.1); border: 1px solid #e91e63; border-radius: 8px; padding: 15px; margin-bottom: 20px; text-align: center;"> <div style="color: #f48fb1; font-size: 14px;"><<= _tier.label>> kiss — +<<= _result.pointsGained>> relationship</div> <<if _result.newLevel>> <div style="color: #e91e63; font-size: 16px; font-weight: bold; margin-top: 8px;">❤ Your relationship has grown: <<= _result.newLevel.charAt(0).toUpperCase() + _result.newLevel.slice(1)>>!</div> <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: rgba(233,30,99,0.2); border: 1px solid #e91e63; border-radius: 8px; padding: 12px 30px; display: inline-block; color: #f8bbd0; cursor: pointer;'>Continue...</div>">> <<goto "NPCTalk">> <</link>> <<if setup.slime.isPlayerSlimeBodied() && _npc && setup.slimePossession.canPossess(_npc).ok>><<link "<div style='display:inline-block;background:linear-gradient(135deg,#2bb583,#6effc0);color:#06281e;padding:10px 22px;border-radius:8px;font-weight:bold;cursor:pointer;margin:6px;'>🫧 Slither inside them</div>">><<set $slimeTargetName = (_npc.originalName || _npc.name)>><<goto "SlimePossessEntry">><</link>><</if>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _sPers = setup.romance.getSexualPersonality(_npc)>> <<set _sceneText = setup.romance.getSceneText("makeOut", _sPers, $romanceApproach, null, _npc.bodyParts.gender)>> <<set _sat = setup.romance.calculateSatisfaction(_npc, $romanceApproach, "mutual")>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #f48fb1;">🔥 Making Out with <<= _npc.name>></div> </div> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 25px; margin-bottom: 25px; line-height: 1.8; font-size: 15px;"> <<= _sceneText>> </div> <<set _result = setup.romance.processScene(_npc.name, "makeOut", $romanceApproach, _sat, "mutual")>> <<set _tier = _result.tier>> <div style="background: rgba(233,30,99,0.1); border: 1px solid #e91e63; border-radius: 8px; padding: 15px; margin-bottom: 20px; text-align: center;"> <div style="color: #f48fb1; font-size: 14px;"><<= _tier.label>> session — +<<= _result.pointsGained>> relationship</div> <<if _result.newLevel>> <div style="color: #e91e63; font-size: 16px; font-weight: bold; margin-top: 8px;">❤ Your relationship has grown: <<= _result.newLevel.charAt(0).toUpperCase() + _result.newLevel.slice(1)>>!</div> <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: rgba(233,30,99,0.2); border: 1px solid #e91e63; border-radius: 8px; padding: 12px 30px; display: inline-block; color: #f8bbd0; cursor: pointer;'>Continue...</div>">> <<goto "NPCTalk">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _sPers = setup.romance.getSexualPersonality(_npc)>> <<set _fpText = setup.romance.getSceneText("foreplay", _sPers, $romanceApproach, null, _npc.bodyParts.gender)>> <<set _isFirst = setup.romance.isFirstTime(_npc.name)>> <<set _ftText = _isFirst ? setup.romance.getSceneText("firstTime", _sPers, "any", null, _npc.bodyParts.gender) : "">> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #f48fb1;">🔥 Things are heating up...</div> </div> <<if _isFirst && _ftText>> <div style="background: rgba(233,30,99,0.15); border: 1px solid #e91e63; border-radius: 12px; padding: 25px; margin-bottom: 20px; line-height: 1.8; font-size: 15px; font-style: italic;"> <<= _ftText>> </div> <</if>> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 25px; margin-bottom: 25px; line-height: 1.8; font-size: 15px;"> <<= _fpText>> <<if setup.getFutaVariant()>> <div style="margin-top: 15px; color: #f0daf5; font-style: italic;"><<= setup.getFutaFlavorText("npc_known_comfortable")>></div> <</if>> </div> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 20px; margin-bottom: 25px;"> <div style="font-size: 16px; color: #ce93d8; margin-bottom: 15px;">What do you focus on?</div> <<if setup.witchSpells && setup.witchSpells.knows("Tendril Conjury") && setup.witchSpells.isSpellcaster()>> <<if $tendrilCast>> <div style="color: #a78bfa; font-size: 13px; margin: 4px 0 10px 0;">🐙 Violet tendrils coil lazily at your fingertips, waiting.</div> <<elseif ($witchMana || 0) >= 30>> <<link "<div style='background: rgba(167,140,250,0.12); border: 1px solid #a78bfa; border-radius: 8px; padding: 10px 16px; margin: 4px 0 10px 0; cursor: pointer; color: #a78bfa; font-size: 13px;'>🐙 Conjure tendrils for this encounter (30 mana)</div>">> <<if setup.witchSpells.canTap()>> <<run setup.witchSpells.spendMana(30)>> <<set $tendrilCast = true>> <<goto "RomanceBuildUp">> <</if>> <</link>> <</if>> <</if>> <<link "<div style='background: rgba(255,255,255,0.08); border: 1px solid #f48fb1; border-radius: 8px; padding: 12px 18px; margin: 8px 0; cursor: pointer;'>💕 <span style='color: #f48fb1; font-weight: bold;'>Emotional Connection</span> <span style='font-size: 12px; color: #aaa;'>(+relationship)</span></div>">> <<set $romanceFocus = "emotional">> <<goto "RomanceIntimacy">> <</link>> <<link "<div style='background: rgba(255,255,255,0.08); border: 1px solid #ef5350; border-radius: 8px; padding: 12px 18px; margin: 8px 0; cursor: pointer;'>🔥 <span style='color: #ef5350; font-weight: bold;'>Physical Pleasure</span> <span style='font-size: 12px; color: #aaa;'>(+sexual XP)</span></div>">> <<set $romanceFocus = "physical">> <<goto "RomanceIntimacy">> <</link>> <<link "<div style='background: rgba(255,255,255,0.08); border: 1px solid #ce93d8; border-radius: 8px; padding: 12px 18px; margin: 8px 0; cursor: pointer;'>✨ <span style='color: #ce93d8; font-weight: bold;'>Mutual Exploration</span> <span style='font-size: 12px; color: #aaa;'>(+both moderate)</span></div>">> <<set $romanceFocus = "mutual">> <<goto "RomanceIntimacy">> <</link>> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='color: #999; padding: 10px; cursor: pointer;'>Pull back...</div>">> <<goto "NPCTalk">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _cidCheck = setup.cid.checkSpecialIntimacy(_npc, $romanceApproach)>> <<if !_cidCheck && setup.mochiIntimacy>> <<set _cidCheck = setup.mochiIntimacy.checkSpecialIntimacy(_npc, $romanceApproach)>> <</if>> <<if !_cidCheck && setup.xantriaIntimacy>> <<set _cidCheck = setup.xantriaIntimacy.checkSpecialIntimacy(_npc, $romanceApproach)>> <</if>> <<if !_cidCheck && setup.tendrilIntimacy>> <<set _cidCheck = setup.tendrilIntimacy.checkSpecialIntimacy(_npc, $romanceApproach)>> <</if>> <<if _cidCheck>> <<set _assembled = _cidCheck>> <<set $cidSatisfactionBonus = _cidCheck.satisfactionBonus>> <<else>> <<set _assembled = setup.romance.assembleScene(_npc, "sex", $romanceApproach)>> <<set $cidSatisfactionBonus = 0>> <</if>> <<set $tendrilCast = false>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #e91e63; text-shadow: 0 0 15px rgba(233,30,99,0.5);">❤️ <<= _npc.name>></div> </div> <<set _npcGender = setup.getScenePairing($bodyParts.gender, _npc.gender)>> <<set _imgScene = $romanceApproach === "gentle" ? "GentleSex" : ($romanceApproach === "rough" ? "RoughSex" : "PassionateSex")>> <<if _assembled.image && $showExplicitImages !== false>> <div style="text-align: center; margin-bottom: 20px;"> <<print '<img src="' + _assembled.image + '" style="max-width: 100%; width: 500px; border-radius: 12px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" />'>> </div> <<else>> <<= setup.sceneImage("relationship", _imgScene, _npcGender)>> <</if>> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 25px; margin-bottom: 25px; line-height: 1.9; font-size: 15px;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p style="color: #d4a5d4; font-style: italic; margin: 0 0 16px 0;">You let them undress you with the practised care that this dress demands, ribbon by ribbon, hook by hook. The fan goes onto the nightstand. The pearls stay on. Behind your refined smile your composure is already thinning, and by the time their mouth finds yours you are no longer entirely in charge of yourself, which is exactly the part you wanted.</p> <</if>> <<= _assembled.mainText>> </div> <div style="text-align: center;"> <<link "<div style='background: rgba(233,30,99,0.2); border: 1px solid #e91e63; border-radius: 8px; padding: 12px 30px; display: inline-block; color: #f8bbd0; cursor: pointer;'>Continue...</div>">> <<goto "RomanceClimax">> <</link>> <<if setup.slime.isPlayerSlimeBodied() && _npc && setup.slimePossession.canPossess(_npc).ok>><<link "<div style='display:inline-block;background:linear-gradient(135deg,#2bb583,#6effc0);color:#06281e;padding:10px 22px;border-radius:8px;font-weight:bold;cursor:pointer;margin:6px;'>🫧 Slither inside them</div>">><<set $slimeTargetName = (_npc.originalName || _npc.name)>><<goto "SlimePossessEntry">><</link>><</if>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _sat = setup.romance.calculateSatisfaction(_npc, $romanceApproach, $romanceFocus)>> <<if $cidSatisfactionBonus && $cidSatisfactionBonus > 0>><<set _sat = Math.min(100, _sat + $cidSatisfactionBonus)>><<set $cidSatisfactionBonus = 0>><</if>> <<set _result = setup.romance.processScene(_npc.name, "sex", $romanceApproach, _sat, $romanceFocus)>> <<if typeof setup.satisfySlutSexualNeeds === "function">><<run setup.satisfySlutSexualNeeds()>><</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">><<run setup.satisfyCheshireCatSexualNeeds()>><</if>> <<if $playerTransformation === "Honeybee">><<set $honeyInventory = ($honeyInventory || 0) + 1>><</if>> <<set _tier = _result.tier>> <<set _satPct = _sat>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #e91e63;">✨ Afterglow</div> </div> <div style="background: rgba(233,30,99,0.1); border: 1px solid rgba(233,30,99,0.3); border-radius: 12px; padding: 20px; margin-bottom: 25px; text-align: center;"> <div style="font-size: 20px; color: #f48fb1; margin-bottom: 10px;"><<= _tier.label>></div> <div style="background: rgba(0,0,0,0.3); border-radius: 8px; height: 12px; margin: 10px auto; max-width: 300px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #e91e63, #f48fb1); height: 100%; width: <<= _satPct>>%; border-radius: 8px; transition: width 1s;"></div> </div> <div style="font-size: 13px; color: #ce93d8;">Satisfaction: <<= _satPct>>%</div> <div style="font-size: 14px; color: #f8bbd0; margin-top: 8px;">+<<= _result.pointsGained>> relationship points</div> <<if _result.newLevel>> <div style="color: #e91e63; font-size: 18px; font-weight: bold; margin-top: 12px; text-shadow: 0 0 10px rgba(233,30,99,0.5);">❤ Your bond deepens: <<= _result.newLevel.charAt(0).toUpperCase() + _result.newLevel.slice(1)>>!</div> <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: rgba(233,30,99,0.2); border: 1px solid #e91e63; border-radius: 8px; padding: 12px 30px; display: inline-block; color: #f8bbd0; cursor: pointer;'>Lie together...</div>">> <<goto "RomanceAftermath">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _i = 0; _i < State.variables.npcs.length; _i++>> <<if State.variables.npcs[_i].name === $romanceTarget>><<set _npc = State.variables.npcs[_i]>><</if>> <</for>> <<if !_npc>><<goto "NPCTalk">><</if>> <<set _rom = $npcRomance[$romanceTarget]>> <<set _lastSat = _rom && _rom.satisfaction.length > 0 ? _rom.satisfaction[_rom.satisfaction.length - 1] : 50>> <<set _agText = setup.romance.getAfterglowText(_npc, _lastSat)>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #f48fb1;">🌙 Quiet Moments</div> </div> <<if _agText>> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 25px; margin-bottom: 25px; line-height: 1.8; font-size: 15px;"> <<= _agText>> </div> <</if>> <<if setup.getFutaVariant()>> <div style="background: rgba(232,67,147,0.1); border: 1px solid rgba(232,67,147,0.3); border-radius: 8px; padding: 15px; margin-bottom: 15px; font-style: italic; color: #f8bbd0; text-align: center;"> Your <<print setup.getFutaDisplayName()>> body hums with lingering dual pleasure — both parts of you thoroughly satisfied, each sensation echoing through the other. </div> <</if>> <div style="background: rgba(255,255,255,0.03); border-radius: 8px; padding: 15px; margin-bottom: 20px; text-align: center; font-style: italic; color: #ce93d8;"> <<if _lastSat >= 80>> You lie together in perfect, blissful silence. Everything feels right. <<elseif _lastSat >= 50>> You rest together, comfortable in each other's warmth. It was a good moment. <<else>> The silence between you feels a little heavy. Maybe next time will be different. <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: rgba(233,30,99,0.2); border: 1px solid #e91e63; border-radius: 8px; padding: 12px 30px; display: inline-block; color: #f8bbd0; cursor: pointer;'>Return</div>">> <<goto "NPCTalk">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _eligible = setup.homeVisit.getEligibleNPCs()>> <<set _homeName = setup.homeVisit.getPlayerHomePassage()>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 28px; color: #51cf66;">🏠 Invite Someone Over</div> <div style="font-size: 14px; color: #aaa; margin-top: 8px;">Choose someone you know well enough</div> </div> <<if _eligible.length === 0>> <div style="background: #2a2a2a; padding: 20px; border-radius: 10px; text-align: center; color: #888;"> You don't have any friends or partners close enough for a home visit yet. Build stronger relationships first! </div> <<else>> <div style="display: grid; gap: 10px;"> <<for _entry range _eligible>> <<capture _entry>> <<set _rel = $relationships[_entry.npc.name]>> <<set _relLevel = _rel ? setup.calculateRelationshipLevel(_rel.points) : 0>> <<set _relData = setup.getRelationshipLevelData(_relLevel)>> <<set _typeIcon = _entry.type === "romantic" ? "💕" : "👋">> <<set _typeLabel = _entry.type === "romantic" ? "Romantic" : "Friend">> <<set _borderColor = _entry.type === "romantic" ? "#e91e63" : "#51cf66">> <<set _displayLevel = _entry.type === "romantic" && setup.romance.getRomanceLevel(_entry.npc.name) ? setup.romance.getRomanceLevel(_entry.npc.name).charAt(0).toUpperCase() + setup.romance.getRomanceLevel(_entry.npc.name).slice(1) : _relData.name>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid <<= _borderColor>>; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 22px;"><<= _typeIcon>></span> <span style="color: #eee; font-weight: bold; font-size: 16px; margin-left: 8px;"><<= _entry.npc.name>></span> <div style="color: <<= _borderColor>>; font-size: 13px; margin-top: 4px; margin-left: 34px;"><<= _typeLabel>> · <<= _displayLevel>></div> </div> <<if _entry.type === "romantic">><<link "<div style='background: #e91e63; color: white; padding: 8px 18px; border-radius: 8px; font-weight: bold; cursor: pointer;'>Invite Over</div>">> <<run setup.homeVisit.invite(_entry.npc.name)>> <<run advanceTime(15)>> <<goto _homeName>> <</link>><<else>><<link "<div style='background: #51cf66; color: white; padding: 8px 18px; border-radius: 8px; font-weight: bold; cursor: pointer;'>Invite Over</div>">> <<run setup.homeVisit.invite(_entry.npc.name)>> <<run advanceTime(15)>> <<goto _homeName>> <</link>><</if>> </div> <</capture>> <</for>> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold;'>← Back Home</div>">> <<goto _homeName>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = setup.homeVisit.getVisitorNPC()>> <<if !_npc || !$homeVisitor || $homeVisitor.type !== "romantic">><<goto setup.homeVisit.getPlayerHomePassage()>><</if>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 30px;"> <div style="font-size: 28px; color: #e91e63; text-shadow: 0 0 15px rgba(233,30,99,0.5);">❤️ Intimate Moment</div> <div style="font-size: 18px; color: #f48fb1; margin-top: 8px;">with <<= _npc.name>></div> </div> <div style="font-size: 16px; color: #ce93d8; text-align: center; margin-bottom: 20px;">Where do you want this moment?</div> <div style="display: grid; gap: 12px;"> <<link "<div style='background: rgba(255,255,255,0.08); border: 1px solid #f8bbd0; border-radius: 10px; padding: 18px; cursor: pointer;'><div style='font-size: 22px; margin-bottom: 5px;'>🛏️ Bedroom</div><div style='color: #ce93d8; font-size: 14px;'>Soft sheets, dim light, unhurried intimacy...</div></div>">> <<set $homeIntimateLocation = "bedroom">> <<goto "HomeIntimateApproach">> <</link>> <<link "<div style='background: rgba(255,255,255,0.08); border: 1px solid #ce93d8; border-radius: 10px; padding: 18px; cursor: pointer;'><div style='font-size: 22px; margin-bottom: 5px;'>🛋️ Living Room</div><div style='color: #ce93d8; font-size: 14px;'>The couch, spontaneous, pulled close...</div></div>">> <<set $homeIntimateLocation = "livingRoom">> <<goto "HomeIntimateApproach">> <</link>> <<link "<div style='background: rgba(255,255,255,0.08); border: 1px solid #ba68c8; border-radius: 10px; padding: 18px; cursor: pointer;'><div style='font-size: 22px; margin-bottom: 5px;'>🚿 Shower</div><div style='color: #ce93d8; font-size: 14px;'>Steam, hot water, slippery skin, standing close...</div></div>">> <<set $homeIntimateLocation = "shower">> <<goto "HomeIntimateApproach">> <</link>> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='color: #999; padding: 10px; cursor: pointer;'>Maybe another time...</div>">> <<goto setup.homeVisit.getPlayerHomePassage()>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = setup.homeVisit.getVisitorNPC()>> <<if !_npc>><<goto setup.homeVisit.getPlayerHomePassage()>><</if>> <<set _opts = setup.romance.getApproachOptions(_npc)>> <<set _locLabel = $homeIntimateLocation === "bedroom" ? "Bedroom" : ($homeIntimateLocation === "livingRoom" ? "Living Room" : "Shower")>> <<set _locIcon = $homeIntimateLocation === "bedroom" ? "🛏️" : ($homeIntimateLocation === "livingRoom" ? "🛋️" : "🚿")>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 25px;"> <div style="font-size: 24px; color: #e91e63;"><<= _locIcon>> <<= _locLabel>></div> <div style="font-size: 16px; color: #f48fb1; margin-top: 8px;">with <<= _npc.name>></div> </div> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 20px; margin-bottom: 25px;"> <div style="font-size: 16px; color: #ce93d8; margin-bottom: 15px;">How do you want this moment?</div> <<for _opt range _opts>> <<capture _opt>> <<set _apLabel = _opt.approach.charAt(0).toUpperCase() + _opt.approach.slice(1)>> <<set _apIcon = _opt.approach === "gentle" ? "🌸" : (_opt.approach === "passionate" ? "🔥" : (_opt.approach === "playful" ? "✨" : "⚡"))>> <<set _apColor = _opt.approach === "gentle" ? "#f8bbd0" : (_opt.approach === "passionate" ? "#ef5350" : (_opt.approach === "playful" ? "#ce93d8" : "#ff7043"))>> <<set _hintText = _opt.hint ? " <span style='font-size: 12px; color: #aaa; font-style: italic;'>(" + _opt.hint + ")</span>" : "">> <<set _btnHtml = "<div style='background: rgba(255,255,255,0.08); border: 1px solid " + _apColor + "; border-radius: 8px; padding: 12px 18px; margin: 8px 0; cursor: pointer;'><span style='font-size: 18px;'>" + _apIcon + "</span> <span style='color: " + _apColor + "; font-weight: bold;'>" + _apLabel + "</span>" + _hintText + "</div>">> <<link _btnHtml>> <<set $romanceApproach = _opt.approach>> <<goto "HomeIntimateScene">> <</link>> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='color: #999; padding: 10px; cursor: pointer;'>← Choose a different spot</div>">> <<goto "HomeIntimateSelect">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npc = setup.homeVisit.getVisitorNPC()>> <<if !_npc>><<goto setup.homeVisit.getPlayerHomePassage()>><</if>> <<set _sPers = setup.romance.getSexualPersonality(_npc)>> <<set _sceneText = setup.homeVisit.getSceneText($homeIntimateLocation, _sPers, $romanceApproach)>> <<set _sat = setup.romance.calculateSatisfaction(_npc, $romanceApproach, "mutual")>> <<set _result = setup.romance.processScene(_npc.name, "sex", $romanceApproach, _sat, "mutual")>> <<set $homeVisitor.homeIntimateUsed = true>> <<if $npcRomance && $npcRomance[_npc.name]>><<set $npcRomance[_npc.name].lastIntimateDay = $dayNumber>><</if>> <<run advanceTime(60)>> <<if typeof setup.satisfySlutSexualNeeds === "function">><<run setup.satisfySlutSexualNeeds()>><</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">><<run setup.satisfyCheshireCatSexualNeeds()>><</if>> <<if $playerTransformation === "Honeybee">><<set $honeyInventory = ($honeyInventory || 0) + 1>><</if>> <<set _tier = _result.tier>> <<set _locLabel = $homeIntimateLocation === "bedroom" ? "Bedroom" : ($homeIntimateLocation === "livingRoom" ? "Living Room" : "Shower")>> <div style="background: linear-gradient(135deg, #1a0a1e 0%, #2d1535 50%, #1e0a2a 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0daf5;"> <div style="max-width: 700px; margin: 0 auto;"> <<set _npcGender = setup.getScenePairing($bodyParts.gender, _npc.gender)>> <<set _imgScene = $romanceApproach === "gentle" ? "GentleSex" : ($romanceApproach === "rough" ? "RoughSex" : "PassionateSex")>> <<= setup.sceneImage("relationship", _imgScene, _npcGender)>> <!-- Scene Text --> <div style="background: rgba(255,255,255,0.05); border-radius: 12px; padding: 25px; margin-bottom: 25px; line-height: 1.8; font-size: 15px;"> <<if $physicalTraits && $physicalTraits.includes("Ojou")>> <p style="color: #d4a5d4; font-style: italic; margin: 0 0 16px 0;">You receive them in your own home like a hostess receives a guest, except the guest is going to spend the next hour with their hands inside your dress. You enjoy the way they look at the bodice before they touch it. You enjoy the way they touch it more.</p> <</if>> <<= _sceneText>> </div> <<if setup.getFutaVariant()>> <div style="background: rgba(232,67,147,0.1); border: 1px solid rgba(232,67,147,0.3); border-radius: 8px; padding: 15px; margin-bottom: 15px; font-style: italic; color: #f8bbd0; text-align: center;"> Being home makes your <<print setup.getFutaDisplayName()>> body feel even more alive — the comfort of your own space amplifying every dual sensation. </div> <</if>> <!-- Satisfaction Display --> <div style="background: rgba(233,30,99,0.1); border: 1px solid rgba(233,30,99,0.3); border-radius: 12px; padding: 20px; margin-bottom: 25px; text-align: center;"> <div style="font-size: 20px; color: #f48fb1; margin-bottom: 10px;"><<= _tier.label>></div> <div style="background: rgba(0,0,0,0.3); border-radius: 8px; height: 12px; margin: 10px auto; max-width: 300px; overflow: hidden;"> <div style="background: linear-gradient(90deg, #e91e63, #f48fb1); height: 100%; width: <<= _sat>>%; border-radius: 8px;"></div> </div> <div style="font-size: 13px; color: #ce93d8;">Satisfaction: <<= _sat>>%</div> <div style="font-size: 14px; color: #f8bbd0; margin-top: 8px;">+<<= _result.pointsGained>> relationship points</div> <<if _result.newLevel>> <div style="color: #e91e63; font-size: 18px; font-weight: bold; margin-top: 12px; text-shadow: 0 0 10px rgba(233,30,99,0.5);">❤ Your bond deepens: <<= _result.newLevel.charAt(0).toUpperCase() + _result.newLevel.slice(1)>>!</div> <</if>> </div> <!-- Afterglow --> <<set _agText = setup.romance.getAfterglowText(_npc, _sat)>> <<if _agText>> <div style="background: rgba(255,255,255,0.03); border-radius: 8px; padding: 20px; margin-bottom: 20px; font-style: italic; color: #ce93d8; line-height: 1.8;"> <<= _agText>> </div> <</if>> <div style="background: rgba(255,255,255,0.03); border-radius: 8px; padding: 15px; margin-bottom: 20px; text-align: center; font-style: italic; color: #ce93d8;"> <<if _sat >= 80>> You lie together in your own space, wrapped in warmth and comfort. Being home makes everything feel more real. <<elseif _sat >= 50>> The familiar surroundings make the moment feel natural, comfortable. A good memory for these walls. <<else>> The silence in your home feels a little heavy. Maybe next time will be different. <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: rgba(81,207,102,0.2); border: 1px solid #51cf66; border-radius: 8px; padding: 12px 30px; display: inline-block; color: #51cf66; cursor: pointer; font-weight: bold;'>🏠 Return Home</div>">> <<goto setup.homeVisit.getPlayerHomePassage()>> <</link>> <<if setup.slime.isPlayerSlimeBodied() && _npc && setup.slimePossession.canPossess(_npc).ok>><<link "<div style='display:inline-block;background:linear-gradient(135deg,#2bb583,#6effc0);color:#06281e;padding:10px 22px;border-radius:8px;font-weight:bold;cursor:pointer;margin:6px;'>🫧 Slither inside them</div>">><<set $slimeTargetName = (_npc.originalName || _npc.name)>><<goto "SlimePossessEntry">><</link>><</if>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "FlowerShop">> <<run setup.tickOjouRefinement("flowerShop", 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff69b4; text-align: center;">🌸 Petal & Stem</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a1942 0%, #2d1028 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff69b4;"> <p style="color: white; font-size: 18px; margin: 0;"> A charming little flower shop bursting with color. Tropical blooms fill every surface, their sweet fragrance hanging in the warm air. Hanging baskets sway gently from the ceiling. </p> </div> <h2 style="color: #ff69b4;">🌹 Flowers for Sale</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _shopItems = [ {id: "single_rose", name: "Single Rose", price: 5, icon: "🌹", desc: "A single red rose"}, {id: "bouquet_mixed", name: "Bouquet", price: 12, icon: "💐", desc: "A colorful mixed bouquet"}, {id: "potted_plant", name: "Potted Plant", price: 15, icon: "🪴", desc: "A lush tropical houseplant"}, {id: "exotic_bouquet", name: "Exotic Bouquet", price: 25, icon: "🌺", desc: "Rare tropical flowers in an elegant arrangement"} ]>> <<for _item range _shopItems>> <<capture _item>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #ff69b4; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #ff69b4; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> </div> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #ff69b4; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<goto "FlowerShop">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Leave Shop</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "JewelryStore">> <<run setup.tickOjouRefinement("jewelryStore", 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💎 Starfish Jewelers</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4a1038 0%, #2d0a22 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Glass display cases sparkle under soft lighting, showcasing rings, necklaces, and bracelets. The faint scent of perfume samples drifts through the air. Everything gleams. </p> </div> <span id="jewelers-dynamic"><<include "_JewelersInteractive">></span> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back</div>">> <<goto "MallFloor2">> <</link>> </div> </div> <</nobr>>
<<nobr>> <h2 style="color: #e91e63;">💍 Jewelry & Accessories</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _shopItems = [ {id: "hair_clip", name: "Hair Clip", price: 8, icon: "💇", desc: "A decorative hair clip"}, {id: "bracelet", name: "Bracelet", price: 15, icon: "📿", desc: "A stylish bracelet"}, {id: "perfume", name: "Perfume", price: 20, icon: "🧴", desc: "A bottle of tropical perfume"}, {id: "necklace", name: "Necklace", price: 25, icon: "📿", desc: "An elegant necklace"}, {id: "watch", name: "Watch", price: 50, icon: "⌚", desc: "A sleek designer watch"}, {id: "ring", name: "Ring", price: 75, icon: "💍", desc: "A beautiful gemstone ring"} ]>> <<for _item range _shopItems>> <<capture _item>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #e91e63; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #e91e63; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> </div> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #e91e63; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <</capture>> <</for>> </div> <!-- Custom Order: gem cutting + jewelry crafting from mining materials --> <<run setup.mining.ensureState()>> <<set _hasGems = Object.keys($gemInventory || {}).some(function(k){ return ($gemInventory[k] || 0) > 0; })>> <<set _hasCutGems = Object.keys($cutGemInventory || {}).some(function(k){ return ($cutGemInventory[k] || 0) > 0; })>> <<if _hasGems || _hasCutGems || $craftingSkill.level >= 2>> <h2 style="color: #e91e63;">✨ Custom Order</h2> <p style="color: #aaa; font-size: 13px; margin: 0 0 12px 0;">Cut raw gems and craft jewelry from your own mined materials. Crafted pieces go straight to your gift inventory. Crafting Lvl <<= $craftingSkill.level>>.</p> <div style="background: #2a1a2a; border: 2px solid #80a0ff; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #80a0ff; margin: 0 0 10px 0;">💎 Cut Raw Gems</h3> <<set _anyGem = false>> <<for _g range setup.jewelers.CUTTABLE_GEMS>> <<capture _g>> <<set _gqty = ($gemInventory[_g] || 0)>> <<if _gqty > 0>> <<set _anyGem = true>> <div style="display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid #3a2a4a;"> <span style="color: #d4c4a0;"><<= setup.mining._prettyName(_g)>>: <strong style="color: #a0d0ff;"><<= _gqty>></strong></span> <span style="font-size: 13px;"> <<link "Cut 1">><<run setup.jewelers.cutGem(_g, 1)>><<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>><</link>> <<if _gqty >= 5>> | <<link "Cut 5">><<run setup.jewelers.cutGem(_g, 5)>><<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>><</link>><</if>> <<if _gqty >= 1>> | <<link "Cut all">><<run setup.jewelers.cutGem(_g, ($gemInventory[_g] || 0))>><<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>><</link>><</if>> </span> </div> <</if>> <</capture>> <</for>> <<if !_anyGem>> <p style="color: #888; font-style: italic; font-size: 13px;">No raw gems to cut. Bring some from the mines.</p> <</if>> <<set _cutKeys = Object.keys($cutGemInventory || {}).filter(function(k){ return ($cutGemInventory[k] || 0) > 0; })>> <<if _cutKeys.length>> <p style="color: #888; font-size: 12px; margin-top: 10px;"><strong>Cut gem stock:</strong> <<for _k range _cutKeys>><<= $cutGemInventory[_k]>> <<= setup.mining._prettyName(_k)>>; <</for>> </p> <</if>> </div> <div style="background: #2a1a2a; border: 2px solid #e91e63; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #e91e63; margin: 0 0 10px 0;">💍 Craft Jewelry</h3> <<for _id range ["craftRing", "craftNecklace", "craftPendant"]>> <<capture _id>> <<set _r = setup.jewelers.recipes[_id]>> <<set _can = setup.jewelers.canCraft(_id)>> <<set _adj = setup.forge._adjustedMats(_r)>> <div style="background: #1a1a1a; border: 1px solid #555; border-radius: 6px; padding: 10px; margin-bottom: 8px;"> <div style="display: flex; justify-content: space-between; align-items: center; gap: 10px;"> <div style="flex: 1;"> <strong style="color: #f48fb1;"><<= _r.label>></strong> <span style="color: #888; font-size: 11px;"> (Crafting Lvl <<= _r.levelReq>>+, gifts as luxury)</span> <br><span style="color: #888; font-size: 11px;">Cost: <<set _ingotsJ = Object.keys(_adj.ingots)>> <<for _k range _ingotsJ>><<= _adj.ingots[_k]>> <<= setup.mining._prettyName(_k)>> ingot<<if _adj.ingots[_k] > 1>>s<</if>>; <</for>> <<set _cgsJ = Object.keys(_adj.cutGems)>> <<for _k range _cgsJ>><<= _adj.cutGems[_k]>> <<if _k === "any">>cut gem<<if _adj.cutGems[_k] > 1>>s<</if>> (any)<<else>><<= setup.mining._prettyName(_k)>><</if>>; <</for>> </span> </div> <div style="text-align: right; min-width: 80px;"> <<if _can.ok>> <<link "<div style='background: #4a1038; border: 2px solid #e91e63; color: #f8bbd0; padding: 6px 14px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Craft</div>">><<run setup.jewelers.craft(_id)>><<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>><</link>> <<else>> <span style="color: #888; font-size: 10px; font-style: italic;"><<= _can.reason>></span> <</if>> </div> </div> </div> <</capture>> <</for>> </div> <</if>> <!-- Sell Raw Gems: Pharaoh ×1.5 + Pearl of Abundance / Naiad ×1.5 stack multiplicatively --> <<set _hasRaw = Object.keys($gemInventory || {}).some(function(k){ return ($gemInventory[k] || 0) > 0 && setup.mining.GEM_BASE_PRICES[k] !== undefined; })>> <<if _hasRaw>> <<set _sellBuffs = setup.mining.getActiveTfBuffs()>> <<set _pharaohMult = (_sellBuffs.gemSalePriceMult && _sellBuffs.gemSalePriceMult > 0) ? _sellBuffs.gemSalePriceMult : 1>> <<set _hasPearlSell = ($currentArtifact === "The Pearl of Abundance") || ($physicalTraits && $physicalTraits.indexOf("Naiad") !== -1)>> <<set _pearlMultSell = _hasPearlSell ? 1.5 : 1>> <<set _sellMult = _pharaohMult * _pearlMultSell>> <h2 style="color: #e91e63;">💰 Sell Raw Gems</h2> <p style="color: #aaa; font-size: 13px; margin: 0 0 12px 0;">The shop will buy uncut gems straight from your bag.<<if _pharaohMult > 1>> <span style="color: #ffd080;">👑 Royal Treatment ×<<= _pharaohMult>>.</span><</if>><<if _pearlMultSell > 1>> <span style="color: #ffd700;">🔮 Pearl of Abundance ×<<= _pearlMultSell>>.</span><</if>></p> <div style="background: #2a1a2a; border: 2px solid #e91e63; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <<for _gid range Object.keys(setup.mining.GEM_BASE_PRICES)>> <<capture _gid>> <<set _gqty = ($gemInventory[_gid] || 0)>> <<if _gqty > 0>> <<set _baseP = setup.mining.GEM_BASE_PRICES[_gid]>> <<set _eachP = Math.floor(_baseP * _sellMult)>> <div style="display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid #3a2a4a;"> <span style="color: #d4c4a0;"><<= setup.mining._prettyName(_gid)>>: <strong style="color: #f8bbd0;"><<= _gqty>></strong> <span style="color: #51cf66;">($<<= _eachP>> each)</span></span> <span style="font-size: 13px;"> <<link "Sell 1">><<run setup.mining.sellRawGem(_gid, 1)>><<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>><</link>> <<if _gqty >= 1>> | <<link "Sell all">><<run setup.mining.sellRawGem(_gid, ($gemInventory[_gid] || 0))>><<replace "#jewelers-dynamic">><<include "_JewelersInteractive">><</replace>><</link>><</if>> </span> </div> <</if>> <</capture>> <</for>> </div> <</if>> <div style="background:#2a1a2a; border:2px solid #e91e63; border-radius:10px; padding:15px; margin-bottom:15px;"> <h2 style="color:#e91e63;">Sell Gems and Relics</h2> <p style="color:#aaa; font-size:13px; margin:0 0 10px 0;">The shop also buys cut gems, flawless gems, and relics.</p> <<include "_GemRelicSell">> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9c27b0; text-align: center;">🏠 Household Items</h1> <!-- Containers Section --> <h2 style="color: #9c27b0;">📦 Containers</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #9c27b0; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;">🍶</span> <span style="color: #9c27b0; font-weight: bold; font-size: 18px; margin-left: 10px;">Empty Bottles</span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;">For bottling milk</div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$2 each | Owned: <<print $emptyBottles || 0>></div> </div> <<if $money >= 2>> <<link "<span style='background: #9c27b0; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= 2>> <<set $emptyBottles = ($emptyBottles || 0) + 1>> <<goto "GroceryStoreHousehold">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #9c27b0; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;">🫙</span> <span style="color: #9c27b0; font-weight: bold; font-size: 18px; margin-left: 10px;">Empty Jars</span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;">For jarring honey</div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$2 each | Owned: <<print $emptyJars || 0>></div> </div> <<if $money >= 2>> <<link "<span style='background: #9c27b0; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= 2>> <<set $emptyJars = ($emptyJars || 0) + 1>> <<goto "GroceryStoreHousehold">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> </div> <!-- Appliances Section --> <h2 style="color: #9c27b0;">🏠 Appliances</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #9c27b0; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;">❄️</span> <span style="color: #9c27b0; font-weight: bold; font-size: 18px; margin-left: 10px;">Refrigerator</span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;">Keeps cooked food fresh for 14 days instead of 3</div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<= setup.drifterDiscount(350)>></div> </div> <<if $hasRefrigerator>> <span style="color: #51cf66; padding: 8px 18px; font-weight: bold;">✓ Owned</span> <<elseif !($ownsHouse || $ownsApartment || $rentingApartment)>> <span style="color: #ff6b6b; padding: 8px 18px; font-size: 12px;">Requires a home</span> <<elseif $money >= setup.drifterDiscount(350)>> <<link "<span style='background: #9c27b0; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(350)>> <<set $hasRefrigerator = true>> <<goto "GroceryStoreHousehold">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> </div> <!-- Snacks & Sweets Section --> <h2 style="color: #9c27b0;">🍬 Snacks & Sweets</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _snackItems = [ {id: "snack_chips", name: "Chips", price: 3, icon: "🥨", desc: "A bag of crunchy snacks"}, {id: "snack_trail_mix", name: "Trail Mix", price: 5, icon: "🥜", desc: "A healthy trail mix bag"}, {id: "chocolate_gift", name: "Chocolate", price: 6, icon: "🍫", desc: "A bar of fine chocolate"}, {id: "candy_box", name: "Candy Box", price: 8, icon: "🍭", desc: "An assorted candy box"} ]>> <<for _item range _snackItems>> <<capture _item>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #9c27b0; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #9c27b0; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> </div> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #9c27b0; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<goto "GroceryStoreHousehold">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #28a745; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Grocery Store</div>">> <<goto "GroceryStore">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #f8bbd0; text-align: center;">🥛 Milk Bottling</h1> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 25px; border: 2px solid #f8bbd0;"> <p style="color: #ccc; font-size: 16px;">You have <span style="color: #f8bbd0; font-weight: bold;"><<print $emptyBottles || 0>></span> empty bottles.</p> <p style="color: #ccc; font-size: 16px;">Bottled Milk: <span style="color: #f8bbd0; font-weight: bold;"><<print $milkInventory || 0>></span></p> </div> <<set _hasHucow = $physicalTraits && $physicalTraits.includes("Hucow")>> <<set _hasLactating = $physicalTraits && $physicalTraits.includes("Lactating")>> <<set _bottles = $emptyBottles || 0>> <<if !_hasHucow && !_hasLactating>> <div style="color: #888; text-align: center; font-style: italic; padding: 20px;">You need the Hucow or Lactating trait to produce milk.</div> <<elseif _bottles <= 0>> <div style="color: #888; text-align: center; font-style: italic; padding: 20px;">You need empty bottles. Buy them at the Grocery Store.</div> <<elseif $milkedToday && !_hasHucow>> <div style="color: #888; text-align: center; font-style: italic; padding: 20px;">You've already expressed milk today. Come back tomorrow.</div> <<else>> <<if _hasHucow>> <!-- Breast Pump option (Hucow only) --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 15px; border: 2px solid #e91e63;"> <h3 style="color: #e91e63;">🔮 Use the Breast Pump</h3> <p style="color: #aaa;">Take your time and enjoy the process. Produces 2 bottles of milk.</p> <p style="color: #888; font-size: 13px;">⏰ 30 minutes | 🥛 2 bottles | ✨ Sensual XP</p> <<if _bottles >= 2>> <<link "<div style='background: #e91e63; color: white; padding: 10px 20px; border-radius: 8px; font-weight: bold; display: inline-block;'>Use Breast Pump</div>">> <<set $emptyBottles -= 2>> <<set $milkInventory = ($milkInventory || 0) + 2>> <<set $milkedToday = true>> <<run advanceTime(30)>> <<if typeof setup.addSexualSkillExp === 'function'>><<run setup.addSexualSkillExp("sensual", 3)>><</if>> <<goto "MilkBottling">> <</link>> <<else>> <span style="color: #666;">Need 2 empty bottles</span> <</if>> </div> <</if>> <!-- Quick Express option --> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; margin-bottom: 15px; border: 2px solid #f8bbd0;"> <h3 style="color: #f8bbd0;">🥛 Quick Express</h3> <p style="color: #aaa;">Get it done quickly. Produces 1 bottle of milk.</p> <p style="color: #888; font-size: 13px;">⏰ 10 minutes | 🥛 1 bottle</p> <<link "<div style='background: #f8bbd0; color: #1a1a1a; padding: 10px 20px; border-radius: 8px; font-weight: bold; display: inline-block;'>Quick Express</div>">> <<set $emptyBottles -= 1>> <<set $milkInventory = ($milkInventory || 0) + 1>> <<set $milkedToday = true>> <<run advanceTime(10)>> <<goto "MilkBottling">> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back Home</div>">> <<goto setup.homeVisit.getPlayerHomePassage()>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BookStore">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #8B4513; text-align: center;">📚 Ink & Anchor</h1> <div style="padding: 20px; background: linear-gradient(135deg, #3e2723 0%, #1b0f0a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8B4513;"> <p style="color: white; font-size: 18px; margin: 0;"> Floor-to-ceiling shelves packed with books line every wall. The smell of old paper and fresh coffee fills the cozy space. A ship's anchor hangs above the counter, wrapped in string lights. </p> </div> <h2 style="color: #8B4513;">📖 Books for Sale</h2> <div style="display: grid; gap: 12px; margin-bottom: 25px;"> <<set _shopItems = [ {id: "book_comic", name: "Comic Book", price: 3, icon: "📰", desc: "A colorful comic book"}, {id: "book_paperback", name: "Used Paperback", price: 5, icon: "📖", desc: "A well-loved secondhand novel"}, {id: "book_novel", name: "Novel", price: 8, icon: "📕", desc: "A bestselling novel"}, {id: "book_artbook", name: "Art Book", price: 15, icon: "🎨", desc: "A beautiful book of artwork and illustrations"}, {id: "book_coffeetable", name: "Coffee Table Book", price: 25, icon: "📚", desc: "A gorgeous oversized photography book"}, {id: "book_first_edition", name: "Rare First Edition", price: 10000, icon: "📜", desc: "An extremely rare collector's first edition"} ]>> <<for _item range _shopItems>> <<capture _item>> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; border: 2px solid #8B4513; display: flex; justify-content: space-between; align-items: center;"> <div> <span style="font-size: 24px;"><<print _item.icon>></span> <span style="color: #8B4513; font-weight: bold; font-size: 18px; margin-left: 10px;"><<print _item.name>></span> <div style="color: #aaa; font-size: 13px; margin-left: 40px;"><<print _item.desc>></div> <<if setup.drifterDiscount(_item.price) >= 1000>> <div style="color: #ffd700; font-size: 14px; margin-left: 40px; font-weight: bold;">$<<print setup.drifterDiscount(_item.price).toLocaleString()>></div> <<else>> <div style="color: #51cf66; font-size: 14px; margin-left: 40px;">$<<print setup.drifterDiscount(_item.price)>></div> <</if>> </div> <<if $money >= setup.drifterDiscount(_item.price)>> <<link "<span style='background: #8B4513; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold;'>Buy</span>">> <<set $money -= setup.drifterDiscount(_item.price)>> <<if !$giftInventory>><<set $giftInventory = {}>><</if>> <<set $giftInventory[_item.id] = ($giftInventory[_item.id] || 0) + 1>> <<goto "BookStore">> <</link>> <<else>> <span style="color: #666; padding: 8px 18px;">Can't Afford</span> <</if>> </div> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Leave Shop</div>">> <<goto "CommercialDistrict">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="max-width: 700px; margin: 0 auto; font-family: Arial, sans-serif;"> /* Header */ <div style="text-align: center; margin-bottom: 20px;"> <h2 style="color: #e84393; margin: 0;">💉 Cosmetic Surgery Center</h2> <p style="color: #999; font-size: 14px; margin-top: 5px;">Welcome to Sunfish City General Hospital's cosmetic surgery wing. Our board-certified surgeons can help you achieve the look you've always wanted.</p> </div> /* Current Status Card */ <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 8px; padding: 15px; margin-bottom: 20px;"> <div style="color: #e84393; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">Your Current Body</div> <div style="display: flex; flex-wrap: wrap; gap: 15px;"> <div style="flex: 1; min-width: 120px;"><span style="color: #888;">Chest:</span> <span style="color: #ccc;"><<print $bodyParts.chest.toUpperFirst()>></span></div> <div style="flex: 1; min-width: 120px;"><span style="color: #888;">Butt:</span> <span style="color: #ccc;"><<print $bodyParts.butt.toUpperFirst()>></span></div> <div style="flex: 1; min-width: 120px;"><span style="color: #888;">Genitals:</span> <span style="color: #ccc;"><<print $bodyParts.genitals.toUpperFirst()>></span></div> <div style="flex: 1; min-width: 120px;"><span style="color: #888;">Age:</span> <span style="color: #ccc;"><<print $appearance.age>></span></div> </div> <div style="margin-top: 10px; color: #4CAF50; font-weight: bold;">💰 $<<print $money>></div> </div> /* ==================== BREAST SURGERY ==================== */ <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 8px; padding: 15px; margin-bottom: 20px;"> <div style="color: #e84393; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">🌸 Breast Surgery</div> <div style="color: #ccc; margin-bottom: 12px;">Current size: <strong><<print $bodyParts.chest.toUpperFirst()>></strong></div> /* Augmentation options */ <div style="color: #aaa; font-size: 13px; margin-bottom: 8px;">Augmentation:</div> <<if setup.cosmeticSurgery.canAugment("chest", "small")>> <<if $money >= 5000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Small - $5,000</div>">><<run setup.cosmeticSurgery.augment("chest", "small")>><<set $podProcedure = "chest_augment_small">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Small - $5,000</div> <</if>> <</if>> <<if setup.cosmeticSurgery.canAugment("chest", "medium")>> <<if $money >= 10000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Medium - $10,000</div>">><<run setup.cosmeticSurgery.augment("chest", "medium")>><<set $podProcedure = "chest_augment_medium">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Medium - $10,000</div> <</if>> <</if>> <<if setup.cosmeticSurgery.canAugment("chest", "large")>> <<if $money >= 20000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Large - $20,000</div>">><<run setup.cosmeticSurgery.augment("chest", "large")>><<set $podProcedure = "chest_augment_large">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Large - $20,000</div> <</if>> <</if>> <<if setup.cosmeticSurgery.canAugment("chest", "huge")>> <<if $money >= 40000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Huge - $40,000</div>">><<run setup.cosmeticSurgery.augment("chest", "huge")>><<set $podProcedure = "chest_augment_huge">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Huge - $40,000</div> <</if>> <</if>> /* Reduction */ <<if setup.cosmeticSurgery.canReduce("chest")>> <div style="margin-top: 10px;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 8px;">Reduction:</div> <<if $money >= 5000>> <<link "<div style='display:inline-block;background:#6c5ce7;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Reduce One Size - $5,000</div>">><<run setup.cosmeticSurgery.reduce("chest")>><<set $podProcedure = "chest_reduce">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Reduce One Size - $5,000</div> <</if>> </div> <</if>> </div> /* ==================== BUTT SURGERY ==================== */ <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 8px; padding: 15px; margin-bottom: 20px;"> <div style="color: #e84393; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">🍑 Butt Surgery</div> <div style="color: #ccc; margin-bottom: 12px;">Current size: <strong><<print $bodyParts.butt.toUpperFirst()>></strong></div> /* Augmentation options */ <div style="color: #aaa; font-size: 13px; margin-bottom: 8px;">Augmentation:</div> <<if setup.cosmeticSurgery.canAugment("butt", "small")>> <<if $money >= 5000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Small - $5,000</div>">><<run setup.cosmeticSurgery.augment("butt", "small")>><<set $podProcedure = "butt_augment_small">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Small - $5,000</div> <</if>> <</if>> <<if setup.cosmeticSurgery.canAugment("butt", "medium")>> <<if $money >= 10000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Medium - $10,000</div>">><<run setup.cosmeticSurgery.augment("butt", "medium")>><<set $podProcedure = "butt_augment_medium">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Medium - $10,000</div> <</if>> <</if>> <<if setup.cosmeticSurgery.canAugment("butt", "large")>> <<if $money >= 20000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Large - $20,000</div>">><<run setup.cosmeticSurgery.augment("butt", "large")>><<set $podProcedure = "butt_augment_large">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Large - $20,000</div> <</if>> <</if>> <<if setup.cosmeticSurgery.canAugment("butt", "huge")>> <<if $money >= 40000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Huge - $40,000</div>">><<run setup.cosmeticSurgery.augment("butt", "huge")>><<set $podProcedure = "butt_augment_huge">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Huge - $40,000</div> <</if>> <</if>> /* Reduction */ <<if setup.cosmeticSurgery.canReduce("butt")>> <div style="margin-top: 10px;"> <div style="color: #aaa; font-size: 13px; margin-bottom: 8px;">Reduction:</div> <<if $money >= 5000>> <<link "<div style='display:inline-block;background:#6c5ce7;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Reduce One Size - $5,000</div>">><<run setup.cosmeticSurgery.reduce("butt")>><<set $podProcedure = "butt_reduce">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Reduce One Size - $5,000</div> <</if>> </div> <</if>> </div> /* ==================== GENITAL SURGERY ==================== */ <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 8px; padding: 15px; margin-bottom: 20px;"> <div style="color: #e84393; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">⚕️ Genital Surgery</div> <div style="color: #ccc; margin-bottom: 12px;">Current: <strong><<print $bodyParts.genitals.toUpperFirst()>></strong></div> <<set _genitals to $bodyParts.genitals>> /* Vaginoplasty - available if has penis type and not Futanari */ <<if (_genitals === "penis" || _genitals === "big penis" || _genitals === "small penis") && !$physicalTraits.includes("Futanari")>> <<if $money >= 20000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Vaginoplasty - $20,000</div>">><<run setup.cosmeticSurgery.genitalSurgery("vaginoplasty")>><<set $podProcedure = "vaginoplasty">><<set $podTime = 60>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Vaginoplasty - $20,000</div> <</if>> <</if>> /* Phalloplasty - available if has vagina type and not Futanari */ <<if (_genitals === "vagina" || _genitals === "tight vagina" || _genitals === "loose vagina") && !$physicalTraits.includes("Futanari")>> <<if setup.futanariBlockedTransformations[$activeTransformation]>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Phalloplasty - $20,000</div> <div style="color: #e84393; font-style: italic; font-size: 12px; margin-left: 4px;">Incompatible with your <<print $activeTransformation>> transformation.</div> <<elseif $money >= 20000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Phalloplasty - $20,000</div>">><<run setup.cosmeticSurgery.genitalSurgery("phalloplasty")>><<set $podProcedure = "phalloplasty">><<set $podTime = 60>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Phalloplasty - $20,000</div> <</if>> <</if>> /* Futanari Surgery - available if not already both/Futanari */ <<if _genitals !== "both" && !$physicalTraits.includes("Futanari")>> <<if setup.futanariBlockedTransformations[$activeTransformation]>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Futanari Surgery - $50,000</div> <div style="color: #e84393; font-style: italic; font-size: 12px; margin-left: 4px;">Incompatible with your <<print $activeTransformation>> transformation.</div> <<elseif $money >= 50000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Futanari Surgery - $50,000</div>">><<run setup.cosmeticSurgery.genitalSurgery("futanari")>><<set $podProcedure = "futanari">><<set $podTime = 90>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Futanari Surgery - $50,000</div> <</if>> <</if>> /* If nothing is available */ <<if (_genitals === "both" || $physicalTraits.includes("Futanari")) && _genitals !== "penis" && _genitals !== "big penis" && _genitals !== "small penis" && _genitals !== "vagina" && _genitals !== "tight vagina" && _genitals !== "loose vagina">> <div style="color: #666; font-style: italic; font-size: 13px;">No genital procedures currently available.</div> <<if $physicalTraits.includes("Futanari")>> <div style="color: #e84393; font-style: italic; font-size: 13px; margin-top: 8px;">Your <<print setup.getFutaDisplayName()>> body cannot undergo further genital surgery. Trade the trait away first.</div> <</if>> <</if>> </div> /* ==================== OTHER PROCEDURES ==================== */ <<set _hasOther to false>> <<if $appearance.age === "Mature Adult" || $appearance.age === "Adult" || $physicalTraits.includes("Scarred") || $physicalTraits.includes("Burnt") || $physicalTraits.includes("Tattooed")>> <<set _hasOther to true>> <</if>> <<if _hasOther>> <div style="background: #2a2a2a; border: 1px solid #444; border-radius: 8px; padding: 15px; margin-bottom: 20px;"> <div style="color: #e84393; font-weight: bold; font-size: 16px; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px;">✨ Other Procedures</div> /* Anti-Aging */ <<if $appearance.age === "Mature Adult">> <<if $money >= 50000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Anti-Aging Treatment - $50,000</div>">><<run setup.cosmeticSurgery.antiAging()>><<set $podProcedure = "anti_aging">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Anti-Aging Treatment - $50,000</div> <</if>> <br> <</if>> /* Aging */ <<if $appearance.age === "Adult">> <<if $money >= 50000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Aging Treatment - $50,000</div>">><<run setup.cosmeticSurgery.aging()>><<set $podProcedure = "aging">><<set $podTime = 30>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Aging Treatment - $50,000</div> <</if>> <br> <</if>> /* Scar Removal */ <<if $physicalTraits.includes("Scarred")>> <<if $money >= 10000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Scar Removal - $10,000</div>">><<run setup.cosmeticSurgery.removeScar("Scarred")>><<set $podProcedure = "scar_removal">><<set $podTime = 15>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Scar Removal - $10,000</div> <</if>> <br> <</if>> /* Burn Scar Removal */ <<if $physicalTraits.includes("Burnt")>> <<if $money >= 10000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Burn Scar Removal - $10,000</div>">><<run setup.cosmeticSurgery.removeScar("Burnt")>><<set $podProcedure = "scar_removal">><<set $podTime = 15>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Burn Scar Removal - $10,000</div> <</if>> <br> <</if>> /* Tattoo Removal */ <<if $physicalTraits.includes("Tattooed")>> <<if $money >= 5000>> <<link "<div style='display:inline-block;background:#e84393;color:#fff;padding:8px 16px;border-radius:6px;margin:4px;cursor:pointer;font-size:14px;'>Tattoo Removal - $5,000</div>">><<run setup.cosmeticSurgery.removeTattoo()>><<set $podProcedure = "tattoo_removal">><<set $podTime = 15>><<goto "HospitalPodScene">><</link>> <<else>> <div style="display:inline-block;background:#555;color:#888;padding:8px 16px;border-radius:6px;margin:4px;font-size:14px;">Tattoo Removal - $5,000</div> <</if>> <</if>> </div> <</if>> /* Back button */ <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display:inline-block;background:#444;color:#fff;padding:10px 24px;border-radius:6px;cursor:pointer;font-size:14px;'>⬅️ Back to Hospital</div>">><<goto "Hospital">><</link>> </div> </div> <</nobr>>
<<nobr>> <div style="max-width: 700px; margin: 0 auto; font-family: Arial, sans-serif;"> <div style="text-align: center; margin-bottom: 20px;"> <h2 style="color: #e84393; margin: 0;">💉 Transformation Pod</h2> </div> /* Intro */ <<print setup.cosmeticSurgery.scenes.getIntro()>> /* Scene-specific transformation text */ <<print setup.cosmeticSurgery.scenes[$podProcedure]()>> /* Result image */ <<print setup.cosmeticSurgery.scenes.getImageHTML($podProcedure)>> /* Outro */ <<print setup.cosmeticSurgery.scenes.getOutro()>> /* Advance time */ <<run advanceTime($podTime)>> /* Return button */ <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: #e84393; color: white; padding: 12px 30px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px;'>Step Out of the Pod</div>">> <<goto "HospitalCosmeticSurgery">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<set _questTarget = $xanitharQuestTarget || "">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <div style="background: #2a2a2a; padding: 15px 20px; border-radius: 12px; margin-bottom: 15px; border: 2px solid #ffd700; box-shadow: 0 0 20px #ffd70044;"> <div style="color: #ffd700; font-size: 22px; font-weight: bold; text-align: center;">🔮 Xanithar Galdenentri</div> </div> <<if _questTarget === "xanithar_paranoid">> <<if $questData.active["xanithar_paranoid"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "Still here? Good good good the eyes are EVERYWHERE today. Bring me Calm. Calm quiet still like a lake. Take my Paranoia, I don't WANT it, it tastes like copper and screaming." </div> </div> <<set _hasCalm = ($mentalTraits && $mentalTraits.includes("Calm"))>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _hasCalm>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasCalm>>✓<<else>>✗<</if>> Calm (Mental Trait) </div> <div style="color: #e91e63; font-size: 14px; margin-top: 10px; font-weight: bold;">You will receive: Paranoid (Mental Trait)</div> <div style="color: #7dd3fc; font-size: 14px; margin-top: 5px; font-weight: bold;">Reward: +3 Charisma</div> </div> <<if _hasCalm>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Give Calm to Xanithar</div>">> <<set _midx = $mentalTraits.indexOf("Calm")>><<if _midx !== -1>><<run $mentalTraits.splice(_midx, 1)>><</if>> <<if _npc.mentalTraits.indexOf("Calm") === -1>><<run _npc.mentalTraits.push("Calm")>><</if>> <<set _pidx = _npc.mentalTraits.indexOf("Paranoid")>><<if _pidx !== -1>><<run _npc.mentalTraits.splice(_pidx, 1)>><</if>> <<if $mentalTraits.indexOf("Paranoid") === -1>><<run $mentalTraits.push("Paranoid")>><</if>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need the Calm trait to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar's eyes dart wildly before locking onto you. "Shh they're listening, the walls have teeth, but YOU yes, you you you can see the cracks, can't you? The spiderweb fractures going crack crack crack through my skull!" He slaps the side of his head twice. "First it's the watching eyes, always the watching eyes, paranoia eating holes in my thoughts like moths in wool. Then the jittering, thoughts bouncing like rubber balls in a box! Then the NEED, the obsessive need to count every grain of sand..." He suddenly grabs your arm, his grip surprisingly strong. "Help me. Trade me something... something CALM. Drown the watching eyes first. Then we fix the rest. Then... then maybe I can remember what quiet sounds like." </div> </div> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_paranoid")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_erratic">> <<if $questData.active["xanithar_erratic"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "The watching eyes are gone! Gone gone but now my thoughts won't squirrel! No. Focus. I need FOCUS. My brain keeps did you know fish can't blink? FOCUS. Bring me that. Take this jittering erratic nonsense OUT of my head." </div> </div> <<set _hasFocused = ($mentalTraits && $mentalTraits.includes("Focused"))>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _hasFocused>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasFocused>>✓<<else>>✗<</if>> Focused (Mental Trait) </div> <div style="color: #e91e63; font-size: 14px; margin-top: 10px; font-weight: bold;">You will receive: Erratic (Mental Trait)</div> <div style="color: #7dd3fc; font-size: 14px; margin-top: 5px; font-weight: bold;">Reward: +3 Charisma</div> </div> <<if _hasFocused>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Give Focused to Xanithar</div>">> <<set _midx = $mentalTraits.indexOf("Focused")>><<if _midx !== -1>><<run $mentalTraits.splice(_midx, 1)>><</if>> <<if _npc.mentalTraits.indexOf("Focused") === -1>><<run _npc.mentalTraits.push("Focused")>><</if>> <<set _pidx = _npc.mentalTraits.indexOf("Erratic")>><<if _pidx !== -1>><<run _npc.mentalTraits.splice(_pidx, 1)>><</if>> <<if $mentalTraits.indexOf("Erratic") === -1>><<run $mentalTraits.push("Erratic")>><</if>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need the Focused trait to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "The watching eyes are gone! Gone gone but now my thoughts won't squirrel! No. Focus. I need FOCUS. My brain keeps did you know fish can't blink? FOCUS. Bring me that. Take this jittering erratic nonsense OUT of my head." </div> </div> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_erratic")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_obsessive">> <<if $questData.active["xanithar_obsessive"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "Better... better... but I can't stop COUNTING. Seventeen tiles on that wall. Forty three cracks in the ceiling. I've counted them nine hundred and twelve times. Bring me Discipline. Structure without the CHAINS." </div> </div> <<set _hasDisciplined = ($mentalTraits && $mentalTraits.includes("Disciplined"))>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _hasDisciplined>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasDisciplined>>✓<<else>>✗<</if>> Disciplined (Mental Trait) </div> <div style="color: #e91e63; font-size: 14px; margin-top: 10px; font-weight: bold;">You will receive: Obsessive (Mental Trait)</div> <div style="color: #7dd3fc; font-size: 14px; margin-top: 5px; font-weight: bold;">Reward: +3 Charisma</div> </div> <<if _hasDisciplined>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Give Disciplined to Xanithar</div>">> <<set _midx = $mentalTraits.indexOf("Disciplined")>><<if _midx !== -1>><<run $mentalTraits.splice(_midx, 1)>><</if>> <<if _npc.mentalTraits.indexOf("Disciplined") === -1>><<run _npc.mentalTraits.push("Disciplined")>><</if>> <<set _pidx = _npc.mentalTraits.indexOf("Obsessive")>><<if _pidx !== -1>><<run _npc.mentalTraits.splice(_pidx, 1)>><</if>> <<if $mentalTraits.indexOf("Obsessive") === -1>><<run $mentalTraits.push("Obsessive")>><</if>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need the Disciplined trait to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "Better... better... but I can't stop COUNTING. Seventeen tiles on that wall. Forty three cracks in the ceiling. I've counted them nine hundred and twelve times. Bring me Discipline. Structure without the CHAINS." </div> </div> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_obsessive")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_crazy">> <<if $questData.active["xanithar_crazy"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "Almost... almost there. I can almost think straight. But the madness is the deepest root. Bring me Wisdom. Let me remember... who I was before the noise." </div> </div> <<set _hasWise = ($mentalTraits && $mentalTraits.includes("Wise"))>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _hasWise>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasWise>>✓<<else>>✗<</if>> Wise (Mental Trait) </div> <div style="color: #e91e63; font-size: 14px; margin-top: 10px; font-weight: bold;">You will receive: Crazy (Mental Trait)</div> </div> <<if _hasWise>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Give Wise to Xanithar</div>">> <<set _midx = $mentalTraits.indexOf("Wise")>><<if _midx !== -1>><<run $mentalTraits.splice(_midx, 1)>><</if>> <<if _npc.mentalTraits.indexOf("Wise") === -1>><<run _npc.mentalTraits.push("Wise")>><</if>> <<set _pidx = _npc.mentalTraits.indexOf("Crazy")>><<if _pidx !== -1>><<run _npc.mentalTraits.splice(_pidx, 1)>><</if>> <<if $mentalTraits.indexOf("Crazy") === -1>><<run $mentalTraits.push("Crazy")>><</if>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need the Wise trait to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "Almost... almost there. I can almost think straight. But the madness is the deepest root. Bring me Wisdom. Let me remember... who I was before the noise." </div> </div> <div style="display: flex; gap: 15px; justify-content: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_crazy")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_youth">> <<if $questData.active["xanithar_youth"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #667eea; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar studies his weathered hands with clear, focused eyes. "I have spent decades trapped in my own mind. Now that I am free... I find myself trapped in this aging body instead." He looks up at you. "You are Adult. Young, vital. I am Mature, worn and weary. I propose a trade. My maturity for your youth. A fair exchange, wouldn't you say?" </div> </div> <<set _playerHasAdult = ($appearance && $appearance.age === "Adult")>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <<if _playerHasAdult>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Exchange Ages</div>">> <<set $appearance.age = "Mature Adult">> <<if _npc.appearance>><<set _npc.appearance.age = "Adult">><</if>> <<set _npc.age = "Adult">> <<set $xanitharYouthSwapDone = true>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You must have the Adult age trait to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar flexes his fingers, marveling at them as if seeing clearly for the first time. "My mind is my own again, thanks to you. But this body... it has aged while I was lost. I want to feel young again." He pauses. "I would trade my maturity for your youth. My Mature age for your Adult age. What do you say?" </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_youth")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_arrangement">> <<if $questData.active["xanithar_arrangement"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #667eea; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar's eyes gleam with quiet determination. "I need three things from you. Specific things. Smooth Skin, so I can look... presentable. Trusting, because I need to believe in people again. And Persuasion, so I can learn to convince others of what I know." He holds up a hand. "All three, or nothing. I won't take them one at a time. And in return..." He taps his temple. "I will teach you Magic Theory. The real thing, not the watered down nonsense they teach at universities." </div> </div> <<set _hasSmoothskin = ($physicalTraits && $physicalTraits.includes("Smooth Skin"))>> <<set _hasTrusting = ($mentalTraits && $mentalTraits.includes("Trusting"))>> <<set _hasPersuasion = ($skills && $skills.includes("Persuasion"))>> <<set _hasAll = _hasSmoothskin && _hasTrusting && _hasPersuasion>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required Traits:</div> <div style="color: <<if _hasSmoothskin>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasSmoothskin>>✓<<else>>✗<</if>> Smooth Skin (Physical Trait) </div> <div style="color: <<if _hasTrusting>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasTrusting>>✓<<else>>✗<</if>> Trusting (Mental Trait) </div> <div style="color: <<if _hasPersuasion>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasPersuasion>>✓<<else>>✗<</if>> Persuasion (Skill) </div> <div style="color: #CE93D8; font-size: 14px; margin-top: 10px; font-weight: bold;"> Reward: Magic Theory (Skill) </div> </div> <<if _hasAll>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Complete the Arrangement</div>">> <<set _pidx = $physicalTraits.indexOf("Smooth Skin")>> <<if _pidx !== -1>><<run $physicalTraits.splice(_pidx, 1)>><</if>> <<set _midx = $mentalTraits.indexOf("Trusting")>> <<if _midx !== -1>><<run $mentalTraits.splice(_midx, 1)>><</if>> <<set _sidx = $skills.indexOf("Persuasion")>> <<if _sidx !== -1>><<run $skills.splice(_sidx, 1)>><</if>> <<if _npc.physicalTraits.indexOf("Smooth Skin") === -1>><<run _npc.physicalTraits.push("Smooth Skin")>><</if>> <<if _npc.mentalTraits.indexOf("Trusting") === -1>><<run _npc.mentalTraits.push("Trusting")>><</if>> <<if !_npc.skills>><<set _npc.skills = []>><</if>> <<if _npc.skills.indexOf("Persuasion") === -1>><<run _npc.skills.push("Persuasion")>><</if>> <<set $xanitharArrangementDone = true>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need all three traits to complete this arrangement.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar looks different now. Younger, brighter. He regards you with a scholar's careful appraisal. "I have one last request. I need three things from you, and I need them all at once. Smooth Skin, Trusting, and Persuasion." He pauses. "Don't ask me why. Just know that in exchange, I will teach you something no one else can. Magic Theory, the real thing." </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_arrangement")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_knowledge">> <<if $questData.active["xanithar_knowledge"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #667eea; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar is hunched over a table covered in diagrams and scribbled notes. He looks up with an intensity that suggests he's working toward something specific. "I need expertise. Occult knowledge, cosmetic skills. Makeup and Hair Styling, to be precise." He taps the diagrams. "Don't ask questions. Just bring me all three." </div> </div> <<set _hasOccult = ($skills && $skills.includes("Occult Expert"))>> <<set _hasMakeup = ($skills && $skills.includes("Makeup"))>> <<set _hasHair = ($skills && $skills.includes("Hair Styling"))>> <<set _hasAllK = _hasOccult && _hasMakeup && _hasHair>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required Skills:</div> <div style="color: <<if _hasOccult>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasOccult>>✓<<else>>✗<</if>> Occult Expert </div> <div style="color: <<if _hasMakeup>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasMakeup>>✓<<else>>✗<</if>> Makeup </div> <div style="color: <<if _hasHair>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasHair>>✓<<else>>✗<</if>> Hair Styling </div> <div style="color: #7dd3fc; font-size: 14px; margin-top: 10px; font-weight: bold;">Reward: +5 Intelligence</div> </div> <<if _hasAllK>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Hand Over the Skills</div>">> <<set _sidx1 = $skills.indexOf("Occult Expert")>><<if _sidx1 !== -1>><<run $skills.splice(_sidx1, 1)>><</if>> <<set _sidx2 = $skills.indexOf("Makeup")>><<if _sidx2 !== -1>><<run $skills.splice(_sidx2, 1)>><</if>> <<set _sidx3 = $skills.indexOf("Hair Styling")>><<if _sidx3 !== -1>><<run $skills.splice(_sidx3, 1)>><</if>> <<if !_npc.skills>><<set _npc.skills = []>><</if>> <<if _npc.skills.indexOf("Occult Expert") === -1>><<run _npc.skills.push("Occult Expert")>><</if>> <<if _npc.skills.indexOf("Makeup") === -1>><<run _npc.skills.push("Makeup")>><</if>> <<if _npc.skills.indexOf("Hair Styling") === -1>><<run _npc.skills.push("Hair Styling")>><</if>> <<set $xanitharKnowledgeDone = true>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need all three skills to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> You find Xanithar surrounded by books and strange diagrams. He looks up with a gleam in his eye that suggests he's planning something. "I have a... project. I need certain skills transferred to me. Occult Expert, Makeup, and Hair Styling." He waves a hand dismissively at your questioning look. "All part of the plan. Are you in?" </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_knowledge")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_style">> <<if $questData.active["xanithar_style"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #667eea; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar is pacing, muttering to himself, but unlike before, his words are coherent. Calculating. "Next I need style. The Fashionable trait and High Heels Proficiency." He catches your expression. "Don't look at me like that. I know exactly what I'm doing." </div> </div> <<set _hasFashionable = ($physicalTraits && $physicalTraits.includes("Fashionable"))>> <<set _hasHeels = ($skills && $skills.includes("High Heels Proficient"))>> <<set _hasAllS = _hasFashionable && _hasHeels>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _hasFashionable>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasFashionable>>✓<<else>>✗<</if>> Fashionable (Physical Trait) </div> <div style="color: <<if _hasHeels>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasHeels>>✓<<else>>✗<</if>> High Heels Proficient (Skill) </div> <div style="color: #51cf66; font-size: 14px; margin-top: 10px; font-weight: bold;">Reward: +5 Dexterity</div> </div> <<if _hasAllS>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Hand Over the Style</div>">> <<set _midx = $physicalTraits.indexOf("Fashionable")>><<if _midx !== -1>><<run $physicalTraits.splice(_midx, 1)>><</if>> <<set _sidx = $skills.indexOf("High Heels Proficient")>><<if _sidx !== -1>><<run $skills.splice(_sidx, 1)>><</if>> <<if _npc.physicalTraits.indexOf("Fashionable") === -1>><<run _npc.physicalTraits.push("Fashionable")>><</if>> <<if !_npc.skills>><<set _npc.skills = []>><</if>> <<if _npc.skills.indexOf("High Heels Proficient") === -1>><<run _npc.skills.push("High Heels Proficient")>><</if>> <<set $xanitharStyleDone = true>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need both traits to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar is examining himself in a small hand mirror, turning his head this way and that. "The knowledge is in place. Now I need the look." He sets the mirror down with purpose. "Fashionable and High Heels Proficient. Before you say anything, yes, the heels are necessary. Trust the process." </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_style")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_allure">> <<if $questData.active["xanithar_allure"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #667eea; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar looks... different. More put together. There's a confidence about him now. "The final pieces. I need the Flirty trait and the Sexually Skilled skill." He holds up a hand before you can speak. "I know how it sounds. But everything I've asked for has been building toward something. You'll see soon enough." </div> </div> <<set _hasFlirty = ($mentalTraits && $mentalTraits.includes("Flirty"))>> <<set _hasSexSkill = ($skills && $skills.includes("Sexually Skilled"))>> <<set _hasAllA = _hasFlirty && _hasSexSkill>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _hasFlirty>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasFlirty>>✓<<else>>✗<</if>> Flirty (Mental Trait) </div> <div style="color: <<if _hasSexSkill>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasSexSkill>>✓<<else>>✗<</if>> Sexually Skilled (Skill) </div> <div style="color: #e91e63; font-size: 14px; margin-top: 10px; font-weight: bold;">Reward: +5 Charisma</div> </div> <<if _hasAllA>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7c4dff 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(224,64,251,0.4);'>Complete the Transformation</div>">> <<set _midx = $mentalTraits.indexOf("Flirty")>><<if _midx !== -1>><<run $mentalTraits.splice(_midx, 1)>><</if>> <<set _sidx = $skills.indexOf("Sexually Skilled")>><<if _sidx !== -1>><<run $skills.splice(_sidx, 1)>><</if>> <<if _npc.mentalTraits.indexOf("Flirty") === -1>><<run _npc.mentalTraits.push("Flirty")>><</if>> <<if !_npc.skills>><<set _npc.skills = []>><</if>> <<if _npc.skills.indexOf("Sexually Skilled") === -1>><<run _npc.skills.push("Sexually Skilled")>><</if>> <<set $xanitharAllureDone = true>> <<goto "NPCTalk">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need both traits to complete this exchange.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar is almost unrecognizable from the gibbering wreck you first met. He stands straighter, moves with purpose. "One last thing. Flirty and Sexually Skilled." He smiles, a knowing, almost mischievous smile. "After this, you'll understand what all of this has been building toward. I promise." </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_allure")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<elseif _questTarget === "xanithar_rebirth">> <<if $questData.active["xanithar_rebirth"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #CE93D8; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar stands before you, looking more alive than you've ever seen him. There's a strange energy crackling around him, something ancient, something powerful. "This is it. The final step." His voice is steady but electric with anticipation. "I need three very specific things from you. Bring them to me and you will understand everything. I will reward you beyond what you can imagine." </div> </div> <<set _hasLucky = ($mentalTraits && $mentalTraits.includes("Lucky")) || ($physicalTraits && $physicalTraits.includes("Lucky")) || ($skills && $skills.includes("Lucky"))>> <<set _hasSunfish = ($mentalTraits && $mentalTraits.includes("Sunfish")) || ($physicalTraits && $physicalTraits.includes("Sunfish")) || ($skills && $skills.includes("Sunfish"))>> <<set _hasSoul = ($mentalTraits && $mentalTraits.includes("Soul")) || ($physicalTraits && $physicalTraits.includes("Soul")) || ($skills && $skills.includes("Soul"))>> <<set _hasAllR = _hasLucky && _hasSunfish && _hasSoul>> <<set _npc = setup.getNPC("Xanithar Galdenentri")>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #CE93D8;"> <div style="color: #CE93D8; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required (Mental Traits):</div> <div style="color: <<if _hasLucky>>#51cf66<<else>>#888<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasLucky>>✓ Lucky<<else>>? ? ?<</if>> </div> <div style="color: <<if _hasSunfish>>#51cf66<<else>>#888<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasSunfish>>✓ Sunfish<<else>>? ? ?<</if>> </div> <div style="color: <<if _hasSoul>>#51cf66<<else>>#888<</if>>; font-size: 14px; margin: 3px 0;"> <<if _hasSoul>>✓ Soul<<else>>? ? ?<</if>> </div> <div style="color: #ffd700; font-size: 14px; margin-top: 10px; font-weight: bold;">Reward: ? ? ?</div> </div> <<if _hasAllR>> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #8b00ff 0%, #4a0080 100%); color: white; padding: 15px 35px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 25px rgba(139,0,255,0.6); border: 2px solid #CE93D8;'>✨ Complete the Ritual ✨</div>">> <<set _midx1 = $mentalTraits.indexOf("Lucky")>><<if _midx1 !== -1>><<run $mentalTraits.splice(_midx1, 1)>><</if>> <<set _midx2 = $mentalTraits.indexOf("Sunfish")>><<if _midx2 !== -1>><<run $mentalTraits.splice(_midx2, 1)>><</if>> <<set _midx3 = $mentalTraits.indexOf("Soul")>><<if _midx3 !== -1>><<run $mentalTraits.splice(_midx3, 1)>><</if>> <<if _npc.mentalTraits.indexOf("Lucky") === -1>><<run _npc.mentalTraits.push("Lucky")>><</if>> <<if _npc.mentalTraits.indexOf("Sunfish") === -1>><<run _npc.mentalTraits.push("Sunfish")>><</if>> <<if _npc.mentalTraits.indexOf("Soul") === -1>><<run _npc.mentalTraits.push("Soul")>><</if>> <<set $xanitharRebirthDone = true>> <<goto "XantriaTransformation">> <</link>> </div> <<else>> <div style="background: #1a1a1a; padding: 12px; border-radius: 8px; border: 2px solid #ff6b6b; margin-top: 15px; text-align: center;"> <span style="color: #ff6b6b;">You need all three traits to complete the ritual.</span> </div> <</if>> <div style="text-align: center; margin-top: 10px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #ffd700; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar takes a deep breath. The air around him shimmers faintly. "You've helped me become who I need to be. But there is one final step, the most important one." His eyes burn with quiet intensity. "I need three more things from you. I cannot tell you what they are yet. You will know when you have them." He leans forward. "When this is done, you will see the truth of everything you've helped me build. And I will give you something extraordinary in return." </div> </div> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<run setup.questSystem.startQuest("xanithar_rebirth")>><<goto "NPCTalk">><</link>> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto "NPCTalk">><</link>> </div> <</if>> <<else>> <<if $xantriaTransformed>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #CE93D8; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xantria has moved to her coven in the Underwater Cave. You can visit her there. </div> </div> <<elseif $questData.completed["xanithar_allure"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #CE93D8; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar stands before you transformed. Not just sane, but refined. Fashionable, confident, alluring. Whatever his plan was, it's complete. He regards you with warm gratitude. "Everything you've given me... I won't forget it. I'm finally who I was meant to be." </div> </div> <<elseif $questData.completed["xanithar_arrangement"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #CE93D8; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> Xanithar smiles, a genuine, warm smile. "You have given me everything I needed. A clear mind, a second youth, and the tools to rejoin the world." He nods respectfully. "The Magic Theory I taught you is the real deal. Use it wisely." </div> </div> <<elseif $questData.completed["xanithar_crazy"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #51cf66; margin-bottom: 15px;"> <div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;"> "I... I can hear myself think. For the first time in years, the world is... quiet." He looks at you with clear, steady eyes. "Thank you." </div> </div> <</if>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto "NPCTalk">><</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <div class="witch-container"> <h1 class="witch-title">The Rebirth</h1> <!-- STAGE 1: The Trigger (immediate) --> <div class="witch-section" style="--delay: 0s;"> <p>The moment Soul leaves your body, something changes in the air itself. The temperature drops. The light bends. Every candle in the room flickers violet.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>Xanithar staggers backward, arms flung wide, and a column of brilliant violet energy erupts from his chest. It spirals upward like a pillar of living flame, illuminating the room in pulsing ultraviolet light.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>"Yes... YES!" His voice cracks, warping between octaves. "Finally... after all these years..."</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p>Then the bond hits you. A jolt of electric warmth slams through your body without warning. You can <em>feel</em> him. Feel the magic pouring through his veins as if it were pouring through yours. Every nerve in your body lights up with a strange, intimate awareness of what is happening to him.</p> </div> <!-- STAGE 2: Frame & Face (5s) --> <<timed 5s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Reshaping</div> <p>His spine straightens with a series of audible cracks, each one sending a sympathetic shiver down your own back. Decades of hunching unravel in seconds. He grows taller, straighter, his bony frame realigning as if invisible hands were sculpting him from within.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>His face begins to change. The sharp, angular jaw softens and narrows. His cheekbones rise, becoming elegant and pronounced. His thin, cracked lips fill out, plumping into something full and sensual, darkening to a deep rose. The deep wrinkles around his eyes smooth away. His nose refines, shrinking delicately, and his brow softens from its permanent furrow into something serene and striking.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>His voice catches mid gasp. What began as a dry rasp climbs steadily upward, shifting through registers until it becomes something rich, melodic, and undeniably feminine. A voice that could command a room or whisper secrets that would make anyone lean closer.</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p>Through the bond, you feel phantom tingles dancing across your own face. A warm pressure along your jaw, a flutter across your lips. Your skin prickles with shared sensation, and you have to steady yourself against the wall.</p> </div> <div class="witch-section" style="--delay: 3.2s;"> <p>His robes have begun to strain at the seams. The fabric pulls tight in places it never pulled before.</p> </div> <</timed>> <!-- STAGE 3: Skin & Waist (12s) --> <<timed 12s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Smoothing</div> <p>The scars go first. Every nick, every weathered line, every rough patch of aged skin begins to glow faintly violet before smoothing away like ripples settling on still water. The transformation spreads outward from his chest, rolling across his arms, his neck, his shoulders. Rough, papery skin becomes soft, flawless, luminously pale. Porcelain smooth and faintly luminous, as if moonlight lives just beneath the surface.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>His waist draws inward with a sound like tightening silk. Ribs shift and narrow. The straight, bony trunk of an old man pinches into a dramatic hourglass, cinching tighter and tighter until his midsection is impossibly slender. The contrast against his still flat chest and narrow hips is striking, but it will not last.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>A long ripping sound echoes through the room. The seams of his robes have split along both sides, unable to contain the body that is forming beneath them. Pale, perfect skin shows through the torn fabric in widening gaps.</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p style="color: #CE93D8;">Through the bond, your own skin flushes hot. A wave of sensitivity rolls across your entire body, from scalp to toes. Every inch of your skin feels alive, heightened, retuned. You can feel the phantom echo of that smoothing, that softening, and it makes your breath catch.</p> </div> <</timed>> <!-- STAGE 4: Full Feminization (20s) --> <<timed 20s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Becoming</div> <p>His hips crack outward with a wet, organic sound that makes you wince in sympathy. They widen dramatically, stretching inches beyond where they were, filling with soft flesh and generous curves. His thighs thicken, pressing together, going from the bony sticks of an old man to full, soft pillars of feminine flesh.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>What remains of his robes cannot survive what happens next. The fabric shreds and falls away in tatters, leaving the transforming body completely bare and bathed in violet light.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>His chest begins to change. Two small swellings appear on the flat plane of his torso, barely noticeable at first. Then they grow. Steadily, relentlessly, they push outward, rounding and filling with weight. They swell past modest, past full, rounding and filling until they settle into a large, voluptuous fullness that suits her new frame. Her nipples darken from pale pink to dusky rose, stiffening and swelling as the cool air hits newly sensitive skin. The sheer weight of them causes her to arch her back instinctively, and a low, involuntary moan escapes her new lips.</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p>Her backside is next. Already widened by the hip transformation, each cheek begins to fill and round, swelling with soft, heavy flesh. They grow rounder, fuller, larger, until her rear has become something extraordinary. Giant, perfectly shaped, impossibly generous. The kind of curves that draw stares and make clothing a negotiation.</p> </div> <div class="witch-section" style="--delay: 3.2s;"> <p>Between her legs, the final change takes place. The small bulge smooths, shrinks, and withdraws. The skin softens and reshapes, folds forming where none existed before. A warmth blooms there, a wetness, a new and intimate sensitivity. She gasps, legs trembling, as her body completes its transformation into something entirely, unmistakably female.</p> </div> <div class="witch-section" style="--delay: 4s;"> <p>Her platinum blonde hair darkens strand by strand, as if ink were being poured from the roots downward. The pale gold surrenders to deep brown, then to midnight black. It thickens, lengthens, cascading past her newly rounded shoulders in waves of glossy raven silk.</p> </div> <div class="witch-section" style="--delay: 4.8s;"> <p style="color: #CE93D8;">Through the bond, you feel all of it. The phantom weight on your own chest. The aching fullness in your hips. A pooling warmth low in your body that mirrors hers. Your skin tingles with borrowed arousal, your breath coming faster, your pulse hammering. The sensation is overwhelming, intimate, as if you are transforming alongside her. When it finally peaks, a shudder runs through both of you simultaneously.</p> </div> <</timed>> <!-- STAGE 5: The Reveal (32s) --> <<timed 32s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">Xantria</div> <p>The violet light fades. The person standing before you is not Xanithar. She is someone else entirely.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>She stands completely nude in the dying glow, and she is breathtaking. Pale, flawless skin stretched over impossible curves. Large breasts that rise and fall with each steady breath. A waist so narrow it seems sculpted. Hips and a backside so generous they border on the absurd. Raven black hair cascading to her waist. A face that is ancient and beautiful and dangerous all at once, with eyes that glow with violet power.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>She stretches luxuriously, rolling her shoulders, arching her back. Her hands glide slowly down her own body with the satisfied expression of someone slipping into a favorite outfit after years of wearing rags. She cups the weight of her own breasts, testing their fullness with an appreciative hum, then runs her palms over the swell of her hips.</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p>"Do you understand now?" Her voice is rich, melodic, dripping with power and pleasure. She turns slowly, letting you see every curve, every detail. "This is what I used to look like. Before the accident." A shadow passes behind her violet eyes, but she does not elaborate. "Everything you gave me. The sanity, the youth, the beauty, the skills, the charm. They were the ingredients I needed to undo what was done to me."</p> </div> <div class="witch-section" style="--delay: 3.2s;"> <p>She snaps her fingers. Violet smoke swirls around her body like living silk, coiling and tightening. When it clears, she is dressed. Flowing dark robes that hug every curve, slit high on one thigh. A pointed witch's hat perched at a rakish angle atop her raven hair. Tall boots that add several inches to her already imposing height. The outfit is as dramatic and commanding as the woman wearing it.</p> </div> <div class="witch-section" style="--delay: 4s;"> <p style="color: #CE93D8; font-size: 20px; font-weight: bold; text-align: center;">Xantria Galdenentri</p> <<if $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <div style="text-align: center; margin-top: 15px;"> <img src="Images/NPCs/StaticNPCs/Xantria_Galdenentri.webp" alt="Xantria Galdenentri" style="max-width: 300px; max-height: 400px; border-radius: 10px; border: 2px solid #CE93D8; box-shadow: 0 0 20px rgba(139,0,255,0.5);"> </div> <</if>> </div> <div class="witch-section" style="--delay: 4.8s;"> <p>She steps forward and places something cold and heavy in your palm. An amulet of dark metal, set with a stone that pulses with the same violet energy that just reshaped her entire being.</p> </div> <div class="witch-section" style="--delay: 5.6s;"> <p>"This is my gift to you. The Witch's Amulet. Activate it and you will become what I am. A witch, in full. Every trait you gave me will be yours again in that form." She smiles, and it is the smile of someone who has waited centuries for this moment. "I am going to the Underwater Cave. Come find me whenever you like."</p> </div> <div class="witch-section" style="--delay: 6.4s;"> <p>And just like that, she vanishes in a swirl of violet smoke. The room falls silent. The amulet in your hand pulses once, warm and alive, and then goes still.</p> </div> <</timed>> <!-- Amulet Reward (42s) --> <<timed 42s>> <div class="witch-section" style="--delay: 0s; border-color: #ffd700; background: rgba(26,26,46,0.9);"> <div style="color: #ffd700; font-size: 20px; font-weight: bold; margin-bottom: 10px; text-align: center;">Witch's Amulet Received!</div> <div style="color: #CE93D8; font-size: 14px; text-align: center;">Equip it from your artifacts to transform into a Witch. All traits you gave Xanithar will be yours in witch form.</div> <div style="color: #51cf66; font-size: 14px; margin-top: 10px; text-align: center;">Xantria's Coven has been unlocked in the Underwater Cave.</div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #8b00ff 0%, #4a0080 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 20px rgba(139,0,255,0.5); border: 2px solid #CE93D8;'>Continue</div>">> <<goto "Alleyway">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <div class="witch-container"> <h1 class="witch-title">The Witch’s Becoming</h1> <!-- STAGE 1: The Pulse (immediate) --> <div class="witch-section" style="--delay: 0s;"> <p>The amulet is warm in your hand. Not warm like metal left in the sun. Warm like something alive. You can feel a heartbeat inside it, steady and slow, pulsing against your palm.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>The moment you close your fingers around it and whisper the word Xantria taught you, the stone at its center flares violet. A column of purple light erupts from between your fingers and slams into your chest like a fist.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>You gasp. Your knees buckle. The energy floods inward, not painful but overwhelming, a torrent of raw arcane power pouring through every vein, every nerve, every cell. It feels like drowning in liquid lightning. Your vision goes violet at the edges, and when you blink, you can see the magic moving under your own skin, glowing threads racing along your arms like living tattoos.</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p>Then the transformation begins.</p> </div> <!-- STAGE 2: The Skin (6s) --> <<timed 6s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Skin</div> <<if $appearance.skinTone === "pale">> <p>Your already pale skin begins to glow. The pallor you have always known shifts into something else entirely, something luminous and unearthly. Every pore tightens. Every blemish dissolves. Your skin becomes porcelain smooth, flawless, almost translucent, as if moonlight were trapped just beneath the surface. You run your fingers along your forearm and the sensation makes you shiver. Every inch of you has become exquisitely sensitive.</p> <<elseif $appearance.skinTone === "tan">> <p>Your sun-kissed skin begins to pale. The warmth drains out of it slowly, like sand through an hourglass, replaced by a cool, luminous glow. The tan fades to ivory, then to porcelain. Freckles vanish. Sun spots dissolve. Your skin becomes impossibly smooth, flawless, almost translucent, as if moonlight were trapped just beneath the surface. You run your fingers along your forearm and the sensation makes you shiver. Every inch of you has become exquisitely sensitive.</p> <<else>> <p>Your dark skin begins to shift. The rich tone lightens gradually, warmth giving way to a cool, luminous pallor. It is not a loss but a transformation, your skin trading its earthen depth for something otherworldly and striking. Blemishes dissolve. Your complexion becomes porcelain smooth, flawless, almost translucent, as if moonlight were trapped just beneath the surface. You run your fingers along your forearm and the sensation makes you shiver. Every inch of you has become exquisitely sensitive.</p> <</if>> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>A wave of heat rolls through you and settles low in your belly. Your breath quickens. The magic is not just changing your surface. It is rewriting your nerve endings, heightening every sensation. Even the brush of air against your bare arms sends a ripple of pleasure across your skin.</p> </div> <</timed>> <!-- STAGE 3: The Feminization (14s) --> <<timed 14s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Reshaping</div> <<if $bodyParts.gender === "male">> <p>Your jaw clenches as something deep inside your skull shifts. There is a grinding pressure, not quite pain, as your jawline narrows and softens. The hard, angular edge of your masculine jaw rounds into something elegant and refined. Your cheekbones rise and sharpen. Your brow smooths, the heavy ridge above your eyes melting away. Your nose refines, shrinking delicately. Your Adam’s apple throbs once, twice, and then dissolves beneath skin that is already impossibly smooth.</p> <<elseif $bodyParts.gender === "female">> <p>Your features were already feminine, but the magic demands perfection. You feel a tingling pressure across your face as your cheekbones lift higher, sharper, more striking. Your lips swell just slightly, their shape becoming fuller and more defined. Your brow smooths into something serene and commanding. Every soft feature sharpens with arcane precision, as if an invisible sculptor were refining a masterpiece.</p> <</if>> </div> <div class="witch-section" style="--delay: 0.8s;"> <<if $bodyParts.gender === "male">> <p>Then your voice breaks. You try to speak and what comes out is a gasp that starts low and climbs, shifting octave by octave. Your vocal cords tighten, thin, reshape. The rumble in your chest vanishes, replaced by something rich and melodic and undeniably feminine. Your shoulders crack inward, narrowing. Your frame compresses, losing inches of breadth. The broad, blocky silhouette of your torso melts into something narrow and sleek.</p> <<else>> <p>Your voice catches in your throat. When you exhale, the sound that escapes is different. Richer. More resonant. A low, melodic quality threads through every syllable, as if your voice has been tuned by something ancient and powerful. Your shoulders shift subtly, narrowing just enough to accentuate the changes that are about to come.</p> <</if>> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>The magic hums through you like a song. You can feel it in your bones, reshaping you from the inside out. Your hips ache with a deep, spreading warmth, and you realize your body is preparing for what comes next.</p> </div> <</timed>> <!-- STAGE 4: The Frame (24s) --> <<timed 24s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Curves</div> <p>Your waist draws inward with a sound like tightening silk. You feel your ribs shift, narrow, compress. Inch by inch your midsection cinches tighter, the flesh above your hips melting away until your waist is impossibly slender. Your hands find it instinctively. Your fingers nearly meet around your own middle.</p> </div> <div class="witch-section" style="--delay: 0.8s;"> <<if $bodyParts.butt === "flat" || $bodyParts.butt === "flat masculine">> <p>Your hips crack outward. You cry out, not from pain but from the sudden flood of sensation. Where your body was flat and angular, flesh surges outward. Your hips widen dramatically, stretching inches beyond where they were, filling with lush, heavy curves. Your backside swells from nothing into something extraordinary, each cheek rounding and filling and growing until they are giant, impossibly full, heavy with soft flesh that bounces with every shifting movement you make. A moan escapes you. You can feel the new weight of yourself every time you shift your stance.</p> <<elseif $bodyParts.butt === "small" || $bodyParts.butt === "medium">> <p>Your hips crack outward. You cry out as sensation floods through you. Your already curved hips widen further, stretching with wet, organic sounds. Your backside, once modest, begins to swell. Each cheek fills with soft, heavy flesh, growing rounder, fuller, more generous with every heartbeat. They push outward relentlessly until they are giant, impossibly lush, the kind of curves that strain fabric and draw stares. A moan escapes you. The sheer weight of your new body makes your thighs press together.</p> <<else>> <p>Your hips crack outward even further. You already had curves, but the magic demands more. Your generous backside swells larger, each cheek filling with additional soft, heavy flesh, growing rounder and rounder until the result is giant, obscene, impossibly lush. Your hips widen to match, the hourglass deepening to something almost cartoonish in its exaggeration. A moan escapes you. The added weight is intoxicating, every tiny movement sending ripples through your flesh.</p> <</if>> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>Your thighs thicken to match, pressing together, soft and warm and powerful. Between the slender waist and the dramatic flare of your hips, you can already feel the hourglass taking shape, and the magic is far from finished.</p> <div class="witch-section-image"> <img src="Images/PostSwap/Butt_giant.webp"> </div> </div> <</timed>> <!-- STAGE 5: The Chest (34s) --> <<timed 34s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Swelling</div> <<if $bodyParts.chest === "flat" || $bodyParts.chest === "flat masculine">> <p>Your chest was flat a moment ago. It is not flat now. Two small swellings appear on the plane of your torso, barely noticeable at first. Then they grow. You look down and watch it happen, unable to tear your eyes away. They push outward, rounding and filling with warm, heavy weight. Past small. Past modest. They round and swell and keep going, your skin stretching taut and sensitive over their growing fullness. Your nipples darken from their original shade to dusky rose, swelling and stiffening as cool air hits newly sensitive skin. By the time they stop, your breasts are huge, full and heavy, straining against gravity with a voluptuous weight that makes your back arch instinctively.</p> <<elseif $bodyParts.chest === "small" || $bodyParts.chest === "medium">> <p>Your breasts begin to tingle, then ache, then burn with a pleasure that borders on pain. You look down and watch them swell. Your modest chest pushes outward, filling with warm weight, rounding and growing. Past full. Past generous. Your nipples darken and stiffen, impossibly sensitive, and every pulse of growth sends a jolt of arousal straight through your core. By the time they stop, your breasts are huge, heavy and voluptuous, spilling over what clothing you still wear with a lush, undeniable presence.</p> <<else>> <p>Your breasts were already generous. The magic does not care. They begin to tingle, then swell further. You can feel them growing heavier, fuller, pushing outward with each pulse of violet light. Your nipples stiffen and darken, achingly sensitive, every brush of fabric sending sparks of pleasure down your spine. They grow until they are huge, impossibly full, straining and heavy with a lush weight that makes you cup them instinctively, feeling their new heft spill over your fingers.</p> <</if>> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>A shuddering moan escapes your new lips. The sensitivity is extraordinary. Even the faintest movement sends waves of pleasure radiating from your swollen nipples through your entire body. You cup the weight of yourself, feeling the warm, heavy fullness spill over your palms, and your breath comes in ragged gasps.</p> <div class="witch-section-image"> <img src="Images/PostSwap/Chest_huge.webp"> </div> </div> <</timed>> <!-- STAGE 6: The Sex (44s) --> <<timed 44s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Becoming</div> <<if $bodyParts.genitals === "vagina" || $bodyParts.genitals === "tight vagina" || $bodyParts.genitals === "loose vagina">> <p>Between your legs, the magic rewrites what is already there. You feel a deep, rolling warmth spread through your core, your most intimate flesh tightening, reshaping, becoming impossibly sensitive. New nerve endings flare to life. Wetness blooms, sudden and intense, and your inner walls clench around nothing as waves of raw pleasure pulse outward from your center. Your knees buckle and you grab the wall for support, panting, trembling with the sheer intensity of what your body has become.</p> <<elseif $bodyParts.genitals === "both">> <p>Between your legs, the magic takes hold of everything you have. Your cock stiffens involuntarily as violet energy wraps around it, and for a single breathless moment it pulses with unbearable pleasure before it begins to shrink, withdrawing slowly. But beneath it, your existing folds remain, and they blossom. The warmth deepens, intensifies, your sex reshaping and tightening as new nerve endings ignite by the thousands. Wetness floods through you. Your inner walls clench in rhythmic spasms of raw pleasure. Your knees give out and you grab the wall, gasping, overwhelmed by sensation.</p> <<else>> <p>Between your legs, the final change begins. Your cock stiffens involuntarily, one last surge of masculine arousal as violet energy wraps around it like a lover’s hand. It throbs once, twice, and then begins to shrink. Slowly. The shaft withdraws, shortening, thinning. Your balls tighten and rise, pulling inward, dissolving into warmth. The skin softens and reshapes, folds forming where none existed before. A slit opens, wet and warm and achingly sensitive. New nerve endings burst to life by the thousands. Wetness blooms, sudden and overwhelming. Your inner walls clench around nothing and a moan tears from your throat, raw and feminine and desperate. Your knees buckle and you grab the wall, trembling, as your new sex pulses with a deep, clenching pleasure that is nothing like anything you have felt before.</p> <</if>> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>Violet light pulses between your thighs in time with your heartbeat. Every throb sends another wave of pleasure crashing through you. You are wet and aching and desperate and the transformation is feeding on that arousal, using it, converting it into more power.</p> <div class="witch-section-image"> <img src="Images/PostSwap/Average_vagina.webp"> </div> </div> <</timed>> <!-- STAGE 7: The Climax & Reveal (52s) --> <<timed 52s>> <div class="witch-divider"></div> <div class="witch-section" style="--delay: 0s;"> <div class="witch-section-title">The Witch</div> <<if $appearance.hairColor === "Black">> <p>Your black hair writhes like living shadow. It thickens, lengthens, pouring down your back in waves of glossy midnight silk until it reaches your waist. Each strand pulses with faint violet light.</p> <<elseif $appearance.hairColor === "Blonde" || $appearance.hairColor === "Platinum Blonde">> <p>Your blonde hair darkens strand by strand, as if ink were being poured from the roots downward. The pale gold surrenders to deep brown, then to midnight black. It thickens, lengthens, cascading down your back in waves of glossy raven silk until it reaches your waist. Each strand pulses with faint violet light.</p> <<elseif $appearance.hairColor === "Brown">> <p>Your brown hair deepens, darkening from its natural shade into rich midnight black. It thickens and lengthens, pouring down your back in waves of glossy silk until it reaches your waist. Each strand pulses with faint violet light.</p> <<elseif $appearance.hairColor === "Red">> <p>Your red hair shifts, the fiery warmth draining away and replaced by cool, deep midnight black. It thickens, lengthens, cascading down your back in waves of glossy raven silk until it reaches your waist. Each strand pulses with faint violet light.</p> <<else>> <p>Your hair darkens to midnight black. It thickens, lengthens, pouring down your back in waves of glossy silk until it reaches your waist. Each strand pulses with faint violet light.</p> <</if>> </div> <div class="witch-section" style="--delay: 0.8s;"> <p>Your eyes burn. You squeeze them shut and when you open them again, the world looks different. Sharper. More vivid. You can see the threads of magic in the air, glowing filaments of violet energy that connect everything. Your irises have turned the color of amethyst, glowing faintly with arcane power.</p> </div> <div class="witch-section" style="--delay: 1.6s;"> <p>And then it peaks. Every sensation, every change, every nerve ending that has been rewritten hits maximum intensity simultaneously. The orgasm slams through you without warning, starting deep in your new sex and radiating outward through every inch of your transformed body. Your huge breasts heave. Your wide hips buck. Your back arches so hard your feet leave the ground for a moment. Violet light pours from your skin, your eyes, your open mouth as you cry out in a voice that is powerful and feminine and raw with ecstasy. It rolls through you in wave after wave, each one stronger than the last, until you are shaking, sobbing, clutching yourself as the magic wrings every last drop of pleasure from your remade body.</p> </div> <div class="witch-section" style="--delay: 2.4s;"> <p>When it finally fades, you are on your knees. Trembling. Panting. Drenched in sweat and slick between your thighs. Your hair pools around you like spilled ink. Your breasts hang heavy, nipples still stiff and aching. Your skin glows with a faint violet luminescence that slowly fades to a soft, permanent shimmer.</p> </div> <div class="witch-section" style="--delay: 3.2s;"> <p>Violet smoke coils from nowhere, wrapping around your naked body like living silk. It tightens, shapes, solidifies. When it clears, you are dressed. Flowing dark robes that cling to every impossible curve. A pointed witch’s hat materialized atop your raven hair. Tall boots that add inches to your height. The outfit is as dramatic and commanding as the body wearing it.</p> </div> <div class="witch-section" style="--delay: 4s;"> <p style="color: #e040fb; font-size: 20px; font-weight: bold; text-align: center;">You are a Witch.</p> <<if $imageSettings && $imageSettings.imagesEnabled>> <div style="text-align: center; margin: 15px 0;"> <img src="Images/Faces/Laboratory/Witch.webp" style="max-width: 280px; border-radius: 12px; border: 3px solid #e040fb; box-shadow: 0 0 25px rgba(224,64,251,0.5);"> </div> <</if>> </div> <div class="witch-section" style="--delay: 4.8s;"> <p>You stand slowly, steadying yourself on legs that are longer and shapelier than you remember. You can feel the power humming through every cell, every nerve, every inch of your remade body. The amulet around your neck pulses once, warm and satisfied, and then goes still.</p> </div> <</timed>> <!-- Continue Button (62s) --> <<timed 62s>> <div class="witch-section" style="--delay: 0s; text-align: center;"> <p style="color: #CE93D8; font-size: 18px; font-weight: bold; margin-bottom: 15px;">This body needs a name. Who are you in this form?</p> <p style="color: #999; font-size: 13px; margin-bottom: 15px;">Your witch form has its own identity, separate from your original self.</p> <div style="display: flex; justify-content: center; gap: 15px; margin-bottom: 20px; flex-wrap: wrap;"> <div style="text-align: center;"> <label style="color: #CE93D8; font-size: 12px; display: block; margin-bottom: 5px;">First Name</label> <<textbox "_witchFirst" "">> </div> <div style="text-align: center;"> <label style="color: #CE93D8; font-size: 12px; display: block; margin-bottom: 5px;">Last Name</label> <<textbox "_witchLast" "">> </div> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #e040fb 0%, #7b1fa2 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 20px rgba(224,64,251,0.5); border: 2px solid #CE93D8;'>Become the Witch</div>">> <<set $witchFirstTransformDone = true>> /* Store witch form name */ <<set $witchFirstName = State.temporary.witchFirst || "Witch">> <<set $witchLastName = State.temporary.witchLast || "">> /* Set initial witch relationships - only Xantria as best friend */ <<set $witchRelationships = {}>> <<set $witchNpcRelationships = {}>> <<set $witchMetNPCs = ["Xantria Galdenentri"]>> <<set $witchRelationships["Xantria Galdenentri"] = {level: 4, points: 100}>> <<set $witchNpcRelationships["Xantria Galdenentri"] = {level: 4, points: 100, levelName: "Best Friend", bestFriendUnlocked: true}>> <<run setup.applyFullTransformation("Witch")>> /* After transformation applies and saves original form, swap to witch name */ <<set $firstName = $witchFirstName>> <<set $lastName = $witchLastName>> /* Swap relationships to witch's (original already saved in witchOriginalForm) */ <<set $relationships = JSON.parse(JSON.stringify($witchRelationships))>> <<set $npcRelationships = JSON.parse(JSON.stringify($witchNpcRelationships))>> <<set $metNPCs = $witchMetNPCs.slice()>> <<goto "Inventory">> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "WitchCoven">> <div style="background: #0a0014; min-height: 100vh; padding: 20px;"> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>← Back to Underwater Cave</div>">> <<goto "UnderWaterCave">> <</link>> </div> <div style="padding: 20px; background: linear-gradient(135deg, #1a0033 0%, #0a0014 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #8b00ff; box-shadow: 0 0 30px rgba(139,0,255,0.4);"> <h1 style="color: #CE93D8; text-align: center; margin: 0 0 10px 0; text-shadow: 0 0 15px rgba(206,147,216,0.6);">🔮 Xantria's Coven</h1> <p style="color: #aaa; text-align: center; font-size: 14px; margin: 0;">A hidden chamber deep within the Underwater Cave, pulsing with arcane energy.</p> </div> <div style="background: #1a1a2e; border: 2px solid #8b00ff; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #ccc; font-size: 16px; line-height: 1.6;"> The cave chamber has been transformed. Glowing violet crystals line the walls, casting everything in an ethereal purple light. Shelves carved into the rock hold bottles of strange liquids, ancient tomes, and bundles of dried herbs. A cauldron bubbles quietly in the center, releasing wisps of fragrant smoke. </p> <p style="color: #ccc; font-size: 16px; line-height: 1.6;"> Xantria Galdenentri stands at a workbench, her raven-black hair cascading over her shoulders, her pale skin almost luminous in the crystal light. She looks up with a warm smile as you approach. </p> </div> <!-- Talk to Xantria --> <div style="text-align: center; margin-bottom: 20px;"> <<set _xantriaNPC = setup.getNPC("Xantria Galdenentri")>> <<if _xantriaNPC>> <<link "<div style='background: linear-gradient(135deg, #8b00ff 0%, #4a0080 100%); color: white; padding: 15px 35px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 15px rgba(139,0,255,0.4); display: inline-block; border: 2px solid #CE93D8;'>🗣️ Talk to Xantria</div>">> <<set $tradingWithNPC = _xantriaNPC>> <<goto "NPCInteraction">> <</link>> <<else>> <div style="color: #888; font-style: italic;">Xantria is not here right now.</div> <</if>> </div> <<set _xanTraining = false>> <<if setup.witchSpells.trainingStepActive("Glamour") || setup.witchSpells.trainingStepActive("Tendril Conjury") || setup.witchSpells.trainingStepActive("Beguile")>><<set _xanTraining = true>><</if>> <<if _xanTraining>> <div style="background: #101a28; border: 2px solid #4dabf7; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 500px; margin-left: auto; margin-right: auto;"> <h3 style="color: #4dabf7; margin: 0 0 8px 0; text-align: center;">🪄 Spell Lessons</h3> <p style="color: #9ab8d0; font-size: 13px; text-align: center; margin: 0 0 10px 0;">Xantria clears the workbench. One session per spell per day, about ninety minutes each.</p> <<for _tsn range ["Glamour", "Tendril Conjury", "Beguile"]>> <<capture _tsn>> <<if setup.witchSpells.trainingStepActive(_tsn) && $spellTrainingDay[_tsn] !== $dayNumber>> <<set _plabel = "<div style='background: #1f4068; color: #cfe8ff; padding: 8px 14px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 6px;'>Practice " + _tsn + " (" + ($spellTraining[_tsn] || 0) + "/" + setup.witchSpells.DEFS[_tsn].sessions + ")</div>">> <<link _plabel>> <<if setup.witchSpells.canTap()>> <<set $practiceSpell = _tsn>> <<set $practiceReturn = "WitchCoven">> <<goto "SpellPractice">> <</if>> <</link>> <<elseif setup.witchSpells.trainingStepActive(_tsn)>> <div style='background: #12203a; color: #6c86a8; padding: 8px 14px; border-radius: 8px; text-align: center; margin-top: 6px;'>Practiced <<print _tsn>> today. Come back tomorrow.</div> <</if>> <</capture>> <</for>> </div> <</if>> </div> <</nobr>>
<<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Back Button --> <div id="artBackTop" style="text-align: center; margin-bottom: 15px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 1px solid #e040fb; color: white; padding: 8px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 2px 6px rgba(0,0,0,0.3), 0 0 10px rgba(224,64,251,0.2); display: inline-block;'>← Back to Credits</div>">> <<goto "Credits">> <</link>> </div> <div id="artHeader"> <h1 style="color: #e040fb; text-align: center; margin: 0 0 5px 0; font-size: 28px;">Art Gallery</h1> <p style="color: #888; text-align: center; font-size: 13px; margin: 0 0 20px 0;">Commissioned artwork for Sunfish City</p> </div> <div id="artGalleryRoot"></div> <<script>> $(function() { var gal = setup.artGallery; var arts = setup.artGalleryArtists; var root = document.getElementById("artGalleryRoot"); if (!root || !gal || gal.length === 0) { root.innerHTML = "<p style='color:#666;text-align:center'>No artwork yet.</p>"; return; } var mode = "grid"; var idx = 0; /* SECTION_TABS_START */ var currentSection = "npcs"; function categorize(item) { var f = item.file || ""; if (f.indexOf("/NPCs/") !== -1) return "npcs"; if (f.indexOf("/Relationships/UniqueNPC/") !== -1) return "npcs"; if (f.indexOf("/Scenes/") !== -1) return "npcs"; if (f.indexOf("/Transformation/") !== -1) return "transformations"; if (f.indexOf("/Faces/Laboratory/") !== -1) return "transformations"; if (f.indexOf("/Relationships/Transformations/") !== -1) return "transformations"; if (f.indexOf("/Jobs/") !== -1) return "transformations"; if (f.indexOf("/Chests/") !== -1) return "bodyparts"; if (f.indexOf("/Butts/") !== -1) return "bodyparts"; return "transformations"; } function filterSection(arr) { return arr.filter(function(it) { return categorize(it) === currentSection; }); } /* SECTION_TABS_END */ var sortMode = "az"; var searchText = ""; var searchByArtist = false; var showSpoilers = false; var sorted = filterSection(gal).sort(function(a, b) { return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : a.title.toLowerCase() > b.title.toLowerCase() ? 1 : 0; }); function sortGallery(sMode) { sortMode = sMode; sorted = filterSection(gal); if (sMode === "az") { sorted.sort(function(a, b) { return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : a.title.toLowerCase() > b.title.toLowerCase() ? 1 : 0; }); } else if (sMode === "za") { sorted.sort(function(a, b) { return b.title.toLowerCase() < a.title.toLowerCase() ? -1 : b.title.toLowerCase() > a.title.toLowerCase() ? 1 : 0; }); } else if (sMode === "added") { /* original array order = order added, no sort needed */ } else if (sMode === "artist") { sorted.sort(function(a, b) { var cmp = a.artist.toLowerCase() < b.artist.toLowerCase() ? -1 : a.artist.toLowerCase() > b.artist.toLowerCase() ? 1 : 0; if (cmp !== 0) return cmp; return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1; }); } } function togglePassageUI(show) { var els = ["artBackTop", "artBackBottom", "artHeader"]; for (var e = 0; e < els.length; e++) { var el = document.getElementById(els[e]); if (el) el.style.display = show ? "" : "none"; } } function makeSortBar() { var btnStyle = "padding:6px 14px;border-radius:6px;cursor:pointer;font-size:13px;font-weight:bold;border:1px solid "; var active = "background:#e040fb;color:#fff;" + btnStyle + "#e040fb"; var inactive = "background:rgba(224,64,251,0.1);color:#e040fb;" + btnStyle + "rgba(224,64,251,0.3)"; /* Section tabs */ var sBtn = "padding:8px 18px;border-radius:8px;cursor:pointer;font-size:14px;font-weight:bold;border:2px solid "; var sActive = "background:#e040fb;color:#fff;" + sBtn + "#e040fb"; var sInactive = "background:rgba(224,64,251,0.08);color:#e040fb;" + sBtn + "rgba(224,64,251,0.35)"; var h = "<div style='display:flex;justify-content:center;gap:10px;margin-bottom:14px;flex-wrap:wrap'>"; h += "<button data-section='npcs' style='" + (currentSection === "npcs" ? sActive : sInactive) + "'>NPCs</button>"; h += "<button data-section='transformations' style='" + (currentSection === "transformations" ? sActive : sInactive) + "'>Transformations</button>"; h += "<button data-section='bodyparts' style='" + (currentSection === "bodyparts" ? sActive : sInactive) + "'>Body Parts</button>"; h += "</div>"; h += "<div style='display:flex;justify-content:center;gap:8px;margin-bottom:15px;flex-wrap:wrap'>"; h += "<button data-sort='az' style='" + (sortMode === "az" ? active : inactive) + "'>A→Z</button>"; h += "<button data-sort='za' style='" + (sortMode === "za" ? active : inactive) + "'>Z→A</button>"; h += "<button data-sort='added' style='" + (sortMode === "added" ? active : inactive) + "'>Date Added</button>"; h += "<button data-sort='artist' style='" + (sortMode === "artist" ? active : inactive) + "'>Artist</button>"; h += "</div>"; h += "<div style='display:flex;justify-content:center;align-items:center;gap:8px;margin-bottom:15px'>"; h += "<input id='artSearchInput' type='text' placeholder='Search by " + (searchByArtist ? "artist" : "title") + "...' value='" + searchText + "' style='background:#1a1a2e;color:#e040fb;border:1px solid rgba(224,64,251,0.3);border-radius:6px;padding:8px 14px;font-size:14px;width:220px;outline:none'>"; var tBtnStyle = "padding:6px 14px;border-radius:6px;cursor:pointer;font-size:13px;font-weight:bold;border:1px solid rgba(224,64,251,0.3);background:rgba(224,64,251,0.1);color:#e040fb"; h += "<button id='artSearchToggle' style='" + tBtnStyle + "'>" + (searchByArtist ? "Artist" : "Title") + "</button>"; h += "</div>"; h += "<div style='display:flex;justify-content:center;align-items:center;gap:8px;margin-bottom:15px'>"; h += "<label style='display:flex;align-items:center;gap:6px;cursor:pointer;color:#888;font-size:13px'>"; h += "<input type='checkbox' id='artSpoilerToggle'" + (showSpoilers ? " checked" : "") + " style='accent-color:#e040fb;cursor:pointer'>"; h += "Show spoilers</label>"; h += "</div>"; return h; } function getFiltered() { if (!searchText) return sorted; var q = searchText.toLowerCase(); return sorted.filter(function(item) { var field = searchByArtist ? item.artist : item.title; return field.toLowerCase().indexOf(q) !== -1; }); } function renderGridItems() { var gridEl = document.getElementById("artGridItems"); if (!gridEl) return; var filtered = getFiltered(); var h = ""; for (var i = 0; i < filtered.length; i++) { var origIdx = sorted.indexOf(filtered[i]); h += "<div class='art-gallery-thumb' data-idx='" + origIdx + "'>"; h += "<img src='" + filtered[i].file + "' alt='" + filtered[i].title + "' loading='lazy'>"; h += "<div class='art-label'><div class='art-title'>" + filtered[i].title + "</div>"; h += "<div class='art-artist'>by " + filtered[i].artist + "</div></div>"; if (filtered[i].spoiler && !showSpoilers) { h += "<div class='art-spoiler-overlay' data-idx='" + origIdx + "' style='position:absolute;top:0;left:0;width:100%;height:100%;background:#0a0a14;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer;z-index:5;border-radius:10px'>"; h += "<span style='color:#e040fb;font-size:24px;margin-bottom:8px'>⚠</span>"; h += "<span style='color:#e040fb;font-weight:bold;font-size:14px'>SPOILER</span>"; h += "<span style='color:#888;font-size:11px;margin-top:4px'>Click to reveal</span>"; h += "</div>"; } h += "</div>"; } if (filtered.length === 0) h += "<p style='color:#888;text-align:center;grid-column:1/-1'>No results found.</p>"; gridEl.innerHTML = h; gridEl.querySelectorAll(".art-gallery-thumb").forEach(function(el) { el.addEventListener("click", function() { idx = parseInt(this.getAttribute("data-idx")); showFull(); }); }); gridEl.querySelectorAll(".art-spoiler-overlay").forEach(function(el) { el.addEventListener("click", function(e) { e.stopPropagation(); this.style.display = "none"; }); }); } function showGrid() { mode = "grid"; togglePassageUI(true); var h = makeSortBar(); h += "<div id='artGridItems' class='art-gallery-grid art-fade-in'></div>"; root.innerHTML = h; renderGridItems(); root.querySelectorAll("[data-sort]").forEach(function(btn) { btn.addEventListener("click", function() { var s = this.getAttribute("data-sort"); searchByArtist = (s === "artist"); sortGallery(s); showGrid(); }); }); root.querySelectorAll("[data-section]").forEach(function(btn) { btn.addEventListener("click", function() { currentSection = this.getAttribute("data-section"); idx = 0; searchText = ""; sortGallery(sortMode); showGrid(); }); }); var searchInput = document.getElementById("artSearchInput"); if (searchInput) { searchInput.addEventListener("input", function() { searchText = this.value; renderGridItems(); }); searchInput.focus(); searchInput.setSelectionRange(searchText.length, searchText.length); } var toggleBtn = document.getElementById("artSearchToggle"); if (toggleBtn) { toggleBtn.addEventListener("click", function() { searchByArtist = !searchByArtist; this.textContent = searchByArtist ? "Artist" : "Title"; searchInput.placeholder = "Search by " + (searchByArtist ? "artist" : "title") + "..."; renderGridItems(); }); } var spoilerToggle = document.getElementById("artSpoilerToggle"); if (spoilerToggle) { spoilerToggle.addEventListener("change", function() { showSpoilers = this.checked; renderGridItems(); }); } } function makeArrows() { var h = "<div style='display:flex;justify-content:center;align-items:center;gap:15px;margin-top:10px'>"; if (sorted.length > 1) h += "<button class='art-nav-btn' data-act='prev'>←</button>"; h += "<span style='color:#888;font-size:14px'>" + (idx + 1) + " / " + sorted.length + "</span>"; if (sorted.length > 1) h += "<button class='art-nav-btn' data-act='next'>→</button>"; h += "</div>"; return h; } function bindNav(container) { container.querySelectorAll("[data-act='grid']").forEach(function(b) { b.addEventListener("click", showGrid); }); container.querySelectorAll("[data-act='prev']").forEach(function(b) { b.addEventListener("click", function() { idx = (idx - 1 + sorted.length) % sorted.length; showFull(); }); }); container.querySelectorAll("[data-act='next']").forEach(function(b) { b.addEventListener("click", function() { idx = (idx + 1) % sorted.length; showFull(); }); }); } function showFull() { mode = "full"; togglePassageUI(false); var p = sorted[idx]; var ad = arts[p.artist]; var h = "<div class='art-fullview art-fade-in'>"; /* Exit button row above image */ h += "<div style='text-align:left;margin-bottom:8px'>"; h += "<button class='art-nav-btn' data-act='grid' style='padding:6px 10px;font-size:16px' title='Back to grid'>↖</button>"; h += "</div>"; /* Image */ h += "<div style='text-align:center;position:relative;display:inline-block'>"; h += "<img src='" + p.file + "' alt='" + p.title + "'>"; if (p.spoiler && !showSpoilers) { h += "<div class='art-spoiler-full' style='position:absolute;top:0;left:0;width:100%;height:100%;background:#0a0a14;display:flex;flex-direction:column;align-items:center;justify-content:center;cursor:pointer'>"; h += "<span style='color:#e040fb;font-size:48px;margin-bottom:12px'>⚠</span>"; h += "<span style='color:#e040fb;font-weight:bold;font-size:20px'>SPOILER</span>"; h += "<span style='color:#888;font-size:14px;margin-top:8px'>Click to reveal</span>"; h += "</div>"; } h += "</div>"; /* Info */ h += "<div class='art-fullview-info'>"; h += "<div class='art-full-title'>" + p.title + "</div>"; h += "<div class='art-full-artist'>by " + p.artist + "</div>"; h += "</div>"; /* Centered arrows */ h += makeArrows(); h += "</div>"; root.innerHTML = h; bindNav(root); var spoilerFull = root.querySelector(".art-spoiler-full"); if (spoilerFull) { spoilerFull.addEventListener("click", function() { this.style.display = "none"; }); } } /* Keyboard */ $(document).off("keydown.artGal").on("keydown.artGal", function(e) { if (mode !== "full") return; if (e.key === "ArrowLeft") { idx = (idx - 1 + sorted.length) % sorted.length; showFull(); } else if (e.key === "ArrowRight") { idx = (idx + 1) % sorted.length; showFull(); } else if (e.key === "Escape") { showGrid(); } }); showGrid(); }); <</script>> <!-- Back Button (Bottom) --> <div id="artBackBottom" style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 1px solid #e040fb; color: white; padding: 8px 20px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 2px 6px rgba(0,0,0,0.3), 0 0 10px rgba(224,64,251,0.2); display: inline-block;'>← Back to Credits</div>">> <<goto "Credits">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ThePufferfish">> <<if !setup.diving.QUESTLINES_DISABLED && $sunfishDayAccepted && !$queshaRecruitState.maidCafe>> <div style="background: linear-gradient(135deg, #2a1f08 0%, #1a1408 100%); border: 2px solid #ffd700; border-radius: 10px; padding: 14px; margin: 10px 0;"> <h3 style="color: #ffd700; margin: 0 0 8px 0;">🌅 Sunfish Day: Talk to Bun Bun</h3> <p style="color: #ddd; line-height: 1.5; margin: 0 0 10px 0;">Quesha asked you to see if the cafe could feed everyone on the festival day.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Ask Bun Bun about Sunfish Day</div>">> <<goto "QueshaRecruitBunBun">> <</link>> </div> <</if>> <<run setup.tickOjouRefinement("pufferfish", 5)>> <<if !$pufferfishVisits>><<set $pufferfishVisits = 0>><</if>> <<set $pufferfishVisits += 1>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <<if $cafeOwnership && $cafeOwnership.owned>><h1 style="text-align: center; color: #d4d4d4; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🐡 <<= $cafeOwnership.cafeName>></h1><<else>><h1 style="text-align: center; color: #d4d4d4; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🐡 Puffy's</h1><</if>> <p style="text-align: center; color: #ff69b4; font-style: italic; margin-top: 0; margin-bottom: 20px;">Maid Cafe</p> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 15px; margin-bottom: 25px;"> <<if $cafeOwnership && $cafeOwnership.owned && !setup.cafe.isOpen()>> <p style="color: #ccc; line-height: 1.6; margin: 0;">The building is still a work in progress. Dust covers the counters, and construction materials are stacked in the corner. The bones of something great are here — it just needs investment. A faded sign above the door reads: <em style="color: #888;">"<<= $cafeOwnership.cafeName>>"</em></p> <<elseif $cafeOwnership && $cafeOwnership.owned && $cafeOwnership.staff.length === 0>> <p style="color: #ccc; line-height: 1.6; margin: 0;">The cafe is open but quiet. Tables are set, the kitchen is stocked, but without any staff it feels a little empty. You're running the whole show yourself for now. A hand-painted sign above the counter reads: <em style="color: #ff69b4;">"<<= $cafeOwnership.cafeName>>"</em></p> <<elseif $cafeOwnership && $cafeOwnership.owned && $cafeOwnership.staff.length === 1>> <p style="color: #ccc; line-height: 1.6; margin: 0;">The cafe hums with a modest energy. Your one employee handles the customers while you oversee things. The scent of fresh pastries drifts from the kitchen. It's small, but it's yours. The sign above the counter reads: <em style="color: #ff69b4;">"<<= $cafeOwnership.cafeName>>"</em></p> <<elseif $cafeOwnership && $cafeOwnership.owned && $cafeOwnership.staff.length >= 2>> <p style="color: #ccc; line-height: 1.6; margin: 0;">The scent of fresh pastries and sweet tea fills the air. Your maids bustle between tables decorated with tiny figurines, greeting customers with bright smiles. Soft music plays from hidden speakers as laughter and the clink of porcelain echo through the cozy space. A hand-painted sign above the counter reads: <em style="color: #ff69b4;">"Welcome home, Master~!"</em></p> <<else>> <p style="color: #ccc; line-height: 1.6; margin: 0;">A cozy cafe in the Outskirts. The door is open, the lights are warm, and the scent of something sweet hangs in the air. A hand-painted sign above the counter reads: <em style="color: #ff69b4;">"Welcome home, Master~!"</em></p> <</if>> </div> <!-- Side Job Discovery (only if lifeswapped into a female body — your old life owns the cafe) --> <<if $sideJobs && !$sideJobs.includes("Maid") && $pufferfishVisits >= 3 && ($bodyParts.gender === "female" || $gender === "female") && ($cafeOwnership && $cafeOwnership.owned || $lifeSwapOriginalBodyNPC)>> <div style="background: linear-gradient(135deg, #3d2040 0%, #2a1a2e 100%); border: 2px solid #ff69b4; border-radius: 10px; padding: 15px; margin-bottom: 20px; text-align: center;"> <p style="color: #ffb6c1; margin: 0 0 10px 0;">📋 A <strong>Help Wanted</strong> sign sits on the counter. One of the maids notices you looking at it and smiles. <em>"We could always use another pair of hands! Want to try working a shift?"</em></p> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Sign Up as a Maid</div>">> <<if !$sideJobs>><<set $sideJobs = []>><</if>> <<run $sideJobs.push("Maid")>> <<goto "ThePufferfish">> <</link>> </div> <</if>> <h2 style="color: #ffb6c1;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Order from Menu --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ffb6c1; margin: 0 0 10px 0;">🍵 Order from Menu</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Browse fish-themed treats and drinks. Each item comes with a special buff.</p> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>View Menu</div>">> <<advancetime 5>> <<goto "PufferfishMenu">> <</link>> </div> <!-- Chat with a Maid --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ffb6c1; margin: 0 0 10px 0;">💬 Chat with a Maid</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Get to know the staff. Build relationships over friendly conversation.</p> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Chat</div>">> <<advancetime 5>> <<goto "PufferfishChat">> <</link>> </div> <!-- Watch a Performance --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ffb6c1; margin: 0 0 10px 0;">🎶 Watch a Performance</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Enjoy today's special maid show. Performances rotate daily.</p> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Watch Show</div>">> <<advancetime 5>> <<goto "PufferfishPerformance">> <</link>> </div> <!-- Work a Shift (Side Job) --> <<if $sideJobs && $sideJobs.includes("Maid")>> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ff69b4; margin: 0 0 10px 0;">🏅 Work a Shift</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Put on your uniform and serve customers. Earn tips and experience.</p> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Start Shift</div>">> <<goto "PufferfishWork">> <</link>> </div> <</if>> <!-- Produce Milk (Player) --> <<if $cafeOwnership && $cafeOwnership.owned && ($physicalTraits.indexOf("Hucow") !== -1 || $physicalTraits.indexOf("Lactating") !== -1) && $cafeOwnership.lastMilkProduced !== $dayNumber>> <div style="border: 3px solid #ecf0f1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #ecf0f1; margin: 0 0 10px 0;">🥛 Produce Milk</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Use a private back room to express milk for the cafe. Adds 5 milk to inventory. (30 min, once per day)</p> <<link "<div style='background: #ecf0f1; color: #2c3e50; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Produce Milk</div>">> <<run window.advanceTime(30)>> <<run setup.cafe.addIngredient("milk", 5)>> <<set $cafeOwnership.lastMilkProduced = $dayNumber>> <<goto "ThePufferfish">> <</link>> </div> <</if>> <!-- Produce Honey (Player) --> <<if $cafeOwnership && $cafeOwnership.owned && $physicalTraits.indexOf("Honeybee") !== -1 && $cafeOwnership.lastHoneyProduced !== $dayNumber>> <div style="border: 3px solid #f1c40f; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #f1c40f; margin: 0 0 10px 0;">🍯 Produce Honey</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Retreat to a quiet corner and produce fresh honey for the cafe. Adds 5 honey to inventory. (30 min, once per day)</p> <<link "<div style='background: #f1c40f; color: #2c3e50; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Produce Honey</div>">> <<run window.advanceTime(30)>> <<run setup.cafe.addIngredient("honey", 5)>> <<set $cafeOwnership.lastHoneyProduced = $dayNumber>> <<goto "ThePufferfish">> <</link>> </div> <</if>> <!-- Manage Cafe (Owner only) --> <<if $cafeOwnership && $cafeOwnership.owned>> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">📊 Manage Cafe</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">View finances, buy upgrades, manage staff.</p> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Dashboard</div>">> <<goto "PufferfishManage">> <</link>> </div> <</if>> </div> <h2 style="color: #ffb6c1;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Back to Outskirts --> <div style="border: 3px solid #888; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 180px;"> <h3 style="color: #888; margin: 0 0 10px 0;">🚶 Outskirts</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Head back to the Outskirts.</p> <<link "<div style='background: #888; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Outskirts</div>">> <<advancetime 15>> <<goto "Outskirts">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <h1 style="text-align: center; color: #ffb6c1; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🐡 <<= ($cafeOwnership && $cafeOwnership.cafeName) ? $cafeOwnership.cafeName : "Puffy's">> Menu</h1> <p style="text-align: center; color: #ff69b4; font-style: italic; margin-top: 0; margin-bottom: 5px;">Every dish is made with love~!</p> <p style="text-align: center; color: #ffd700; margin-top: 0; margin-bottom: 20px;">Your money: $<<= $money>></p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Puffer Parfait --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">🍨 Puffer Parfait</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">Layered cream and tropical fruit, shaped like a pufferfish. Topped with a tiny chocolate fin.</p> <p style="font-size: 12px; color: #ff69b4; margin: 0 0 5px 0; font-weight: bold;">+2 relationship per talk (6h)</p> <p style="font-size: 14px; color: #ffd700; margin: 0 0 10px 0; font-weight: bold;">$15</p> <<if $money >= 15>> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Order</div>">> <<set $money -= 15>> <<run setup.addBuff("food_puffy_parfait", 360, 1)>> <<advancetime 15>> <<goto "PufferfishMenuResult">> <</link>> <<else>> <div style="background: #555; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money</div> <</if>> </div> <!-- Coral Tea --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">🍵 Coral Tea</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">Rose-pink herbal tea served in a shell-shaped cup. Warm and soothing.</p> <p style="font-size: 12px; color: #ff69b4; margin: 0 0 5px 0; font-weight: bold;">+1 relationship per talk (4h)</p> <p style="font-size: 14px; color: #ffd700; margin: 0 0 10px 0; font-weight: bold;">$8</p> <<if $money >= 8>> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Order</div>">> <<set $money -= 8>> <<run setup.addBuff("food_puffy_coral_tea", 240, 1)>> <<advancetime 15>> <<goto "PufferfishMenuResult">> <</link>> <<else>> <div style="background: #555; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money</div> <</if>> </div> <!-- Reef Roll --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">🍣 Reef Roll</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">Colorful sushi roll with fish roe and edible flowers. Each piece is a tiny ocean scene.</p> <p style="font-size: 12px; color: #ff69b4; margin: 0 0 5px 0; font-weight: bold;">+$3-8 money bonus (6h)</p> <p style="font-size: 14px; color: #ffd700; margin: 0 0 10px 0; font-weight: bold;">$12</p> <<if $money >= 12>> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Order</div>">> <<set $money -= 12>> <<run setup.addBuff("food_puffy_reef_roll", 360, 1)>> <<advancetime 15>> <<goto "PufferfishMenuResult">> <</link>> <<else>> <div style="background: #555; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money</div> <</if>> </div> <!-- Starfish Cookie --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">🍪 Starfish Cookie</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">Star-shaped shortbread with pink icing and sprinkles. Simple and sweet.</p> <p style="font-size: 12px; color: #ff69b4; margin: 0 0 5px 0; font-weight: bold;">+5% trading bonus (4h)</p> <p style="font-size: 14px; color: #ffd700; margin: 0 0 10px 0; font-weight: bold;">$5</p> <<if $money >= 5>> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Order</div>">> <<set $money -= 5>> <<run setup.addBuff("food_puffy_starfish_cookie", 240, 1)>> <<advancetime 15>> <<goto "PufferfishMenuResult">> <</link>> <<else>> <div style="background: #555; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money</div> <</if>> </div> <!-- Anglerfish Espresso --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">☕ Anglerfish Espresso</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">Dark as the deep sea, with a swirl of cream that glows under the cafe lights.</p> <p style="font-size: 12px; color: #ff69b4; margin: 0 0 5px 0; font-weight: bold;">+10% trading bonus (6h)</p> <p style="font-size: 14px; color: #ffd700; margin: 0 0 10px 0; font-weight: bold;">$10</p> <<if $money >= 10>> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Order</div>">> <<set $money -= 10>> <<run setup.addBuff("food_puffy_espresso", 360, 1)>> <<advancetime 15>> <<goto "PufferfishMenuResult">> <</link>> <<else>> <div style="background: #555; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money</div> <</if>> </div> <!-- Ocean Breeze Smoothie --> <div style="border: 3px solid #ff69b4; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 200px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">🥤 Ocean Breeze Smoothie</h3> <p style="font-size: 13px; color: #aaa; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">Blue-green layered smoothie with crushed ice and a tiny umbrella. Tastes like the tropics.</p> <p style="font-size: 12px; color: #ff69b4; margin: 0 0 5px 0; font-weight: bold;">+1% treasure, -1% trash fishing (8h)</p> <p style="font-size: 14px; color: #ffd700; margin: 0 0 10px 0; font-weight: bold;">$18</p> <<if $money >= 18>> <<link "<div style='background: #ff69b4; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Order</div>">> <<set $money -= 18>> <<run setup.addBuff("food_puffy_smoothie", 480, 1)>> <<advancetime 15>> <<goto "PufferfishMenuResult">> <</link>> <<else>> <div style="background: #555; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;">Not enough money</div> <</if>> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 30px; max-width: 500px; text-align: center;"> <h2 style="color: #ffb6c1; margin: 0 0 15px 0;">💖 Enjoy your meal~!</h2> <p style="color: #ccc; line-height: 1.6;">A maid sets down your order with a curtsy and a bright smile. <em style="color: #ff69b4;">"Made with extra love, just for you!"</em></p> <p style="color: #aaa; font-size: 14px; margin-top: 10px;">Your food buff has been applied.</p> <div style="margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Thank you~!</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ThePufferfish">> <<run setup.tickOjouRefinement("pufferfish", 5)>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <h1 style="text-align: center; color: #ffb6c1; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">💬 Chat with a Maid</h1> <p style="text-align: center; color: #ff69b4; font-style: italic; margin-top: 0; margin-bottom: 20px;">Who would you like to spend time with?</p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px; margin-bottom: 25px;"> <!-- Mochi (only if hired and on shift) --> <<set _mochiHired = false>> <<set _mochiShift = "off">> <<if $cafeOwnership && $cafeOwnership.staff>><<for _s range $cafeOwnership.staff>><<if _s.name === "Mochi">><<set _mochiHired = true>><<set _mochiShift = _s.shift || "both">><</if>><</for>><</if>> <<set _mochiOnShift = _mochiHired && (_mochiShift === "both" || (_mochiShift === "morning" && $timeOfDay === "Morning") || (_mochiShift === "day" && $timeOfDay === "Day"))>> <<if _mochiOnShift>> <<set _maid = null>> <<for _npc range $npcs>><<if _npc.name === "Mochi">><<set _maid = _npc>><</if>><</for>> <<if _maid !== null>> <<set _relPoints = ($relationships && $relationships["Mochi"]) ? ($relationships["Mochi"].points || 0) : 0>> <<set _hasRomance = $npcRomance && $npcRomance["Mochi"] ? true : false>> <<set _romLevel = _hasRomance ? ($npcRomance["Mochi"].level || "none") : "none">> <div style="border: 3px solid #ffb6c1; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 220px;"> <h3 style="color: #ffb6c1; margin: 0 0 8px 0;">🐱 Mochi</h3> <p style="font-size: 13px; color: #ccc; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">A petite werecat with pink hair and bright eyes. She fidgets with her apron, tail swishing behind her.</p> <p style="font-size: 12px; color: #aaa; margin: 0 0 5px 0;">❤ Relationship: <span style="color: #ffb6c1;"><<= _relPoints>> pts</span></p> <<if _hasRomance>><p style="font-size: 12px; color: #e91e63; margin: 0 0 10px 0;">💓 Romance: <<= _romLevel>></p><</if>> <<link "<div style='background: #ffb6c1; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Chat with Mochi</div>">> <<set $pufferfishChatTarget = "Mochi">> <<set $tradingWithNPC = $npcs.find(function(n) { return n.name === "Mochi"; })>> <<set $preNPCLocation = "ThePufferfish">> <<advancetime 15>> <<goto "PufferfishChatScene">> <</link>> </div> <</if>> <</if>> <!-- Ren (only if hired and on shift) --> <<set _renHired = false>> <<set _renShift = "off">> <<if $cafeOwnership && $cafeOwnership.staff>><<for _s range $cafeOwnership.staff>><<if _s.name === "Ren">><<set _renHired = true>><<set _renShift = _s.shift || "both">><</if>><</for>><</if>> <<set _renOnShift = _renHired && (_renShift === "both" || (_renShift === "morning" && $timeOfDay === "Morning") || (_renShift === "day" && $timeOfDay === "Day"))>> <<if _renOnShift>> <<set _maid = null>> <<for _npc range $npcs>><<if _npc.name === "Ren">><<set _maid = _npc>><</if>><</for>> <<if _maid !== null>> <<set _relPoints = ($relationships && $relationships["Ren"]) ? ($relationships["Ren"].points || 0) : 0>> <<set _hasRomance = $npcRomance && $npcRomance["Ren"] ? true : false>> <<set _romLevel = _hasRomance ? ($npcRomance["Ren"].level || "none") : "none">> <div style="border: 3px solid #9b59b6; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 220px;"> <h3 style="color: #9b59b6; margin: 0 0 8px 0;">🦊 Ren</h3> <p style="font-size: 13px; color: #ccc; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">A tall kitsune with flowing purple hair and glowing eyes. She leans against the counter, watching you with a knowing smile.</p> <p style="font-size: 12px; color: #aaa; margin: 0 0 5px 0;">❤ Relationship: <span style="color: #9b59b6;"><<= _relPoints>> pts</span></p> <<if _hasRomance>><p style="font-size: 12px; color: #e91e63; margin: 0 0 10px 0;">💓 Romance: <<= _romLevel>></p><</if>> <<link "<div style='background: #9b59b6; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Chat with Ren</div>">> <<set $pufferfishChatTarget = "Ren">> <<set $tradingWithNPC = $npcs.find(function(n) { return n.name === "Ren"; })>> <<set $preNPCLocation = "ThePufferfish">> <<advancetime 15>> <<goto "PufferfishChatScene">> <</link>> </div> <</if>> <</if>> <!-- Clover (only if hired and on shift) --> <<set _cloverHired = false>> <<set _cloverShift = "off">> <<if $cafeOwnership && $cafeOwnership.staff>><<for _s range $cafeOwnership.staff>><<if _s.name === "Clover">><<set _cloverHired = true>><<set _cloverShift = _s.shift || "both">><</if>><</for>><</if>> <<set _cloverOnShift = _cloverHired && (_cloverShift === "both" || (_cloverShift === "morning" && $timeOfDay === "Morning") || (_cloverShift === "day" && $timeOfDay === "Day"))>> <<if _cloverOnShift>> <<set _maid = null>> <<for _npc range $npcs>><<if _npc.name === "Clover">><<set _maid = _npc>><</if>><</for>> <<if _maid !== null>> <<set _relPoints = ($relationships && $relationships["Clover"]) ? ($relationships["Clover"].points || 0) : 0>> <<set _hasRomance = $npcRomance && $npcRomance["Clover"] ? true : false>> <<set _romLevel = _hasRomance ? ($npcRomance["Clover"].level || "none") : "none">> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column; min-height: 220px;"> <h3 style="color: #2ecc71; margin: 0 0 8px 0;">🐄 Clover</h3> <p style="font-size: 13px; color: #ccc; margin: 0 0 8px 0; line-height: 1.4; flex-grow: 1;">An incredibly curvy hucow with black-spotted white hair and small horns peeking through. She waves cheerfully, her ample figure straining against her maid uniform.</p> <p style="font-size: 12px; color: #aaa; margin: 0 0 5px 0;">❤ Relationship: <span style="color: #2ecc71;"><<= _relPoints>> pts</span></p> <<if _hasRomance>><p style="font-size: 12px; color: #e91e63; margin: 0 0 10px 0;">💓 Romance: <<= _romLevel>></p><</if>> <<link "<div style='background: #2ecc71; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Chat with Clover</div>">> <<set $pufferfishChatTarget = "Clover">> <<set $tradingWithNPC = $npcs.find(function(n) { return n.name === "Clover"; })>> <<set $preNPCLocation = "ThePufferfish">> <<advancetime 15>> <<goto "PufferfishChatScene">> <</link>> </div> <</if>> <</if>> </div> <!-- No maids message --> <<set _anyMaidAvailable = (_mochiOnShift || _renOnShift || _cloverOnShift)>> <<if !_anyMaidAvailable>> <div style="text-align: center; padding: 20px; color: #888;"> <p>No maids are currently on shift. Check the management dashboard to schedule shifts.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<set _npcName = _npc.name>> <<if !$relationships>><<set $relationships = {}>><</if>> <<if !$relationships[_npcName]>><<set $relationships[_npcName] = {points: 0, level: 0}>><</if>> <<set _relPoints = $relationships[_npcName].points>> <<set _hasRomance = $npcRomance && $npcRomance[_npcName] ? true : false>> <<set _canChat = setup.maidCafe.canChatToday(_npcName)>> <<set _maidColor = "#ff69b4">> <<set _greeting = "">> <<if _npcName === "Mochi">> <<set _maidColor = "#ffb6c1">> <<if _relPoints < 25>><<set _greeting = "Mochi jumps a little when you approach, her cat ears perking up. She clutches her serving tray to her chest and gives you a shy smile. 'O-oh! H-hi there... did you want to talk to me?'">> <<elseif _relPoints < 75>><<set _greeting = "Mochi's tail swishes happily when she spots you. She sets down her tray and bounces over. 'Hi hi! I was hoping you'd come by today!'">> <<elseif _relPoints < 150>><<set _greeting = "Mochi practically pounces on you, wrapping her arms around yours. Her ears are flat with contentment. 'You came to see me again! I saved you the best seat.'">> <<else>><<set _greeting = "Mochi slides into the seat next to you, close enough that her tail curls around your leg under the table. She gazes up at you with those big eyes. 'I've been thinking about you all day...'">> <</if>> <<elseif _npcName === "Ren">> <<set _maidColor = "#9b59b6">> <<if _relPoints < 25>><<set _greeting = "Ren glances at you with those glowing eyes and smirks. Her fox tail sways slowly behind her as she leans across the counter. 'Well, well... a new regular? I'm Ren. Make yourself comfortable.'">> <<elseif _relPoints < 75>><<set _greeting = "Ren spots you and her smirk deepens into something warmer. She pours you a drink without being asked. 'I saved something special for you today. Hope you don't mind me being presumptuous.'">> <<elseif _relPoints < 150>><<set _greeting = "Ren abandons her duties the moment she sees you, sliding into the booth across from you. Her tail brushes against your ankle under the table. 'Finally. The only person worth talking to in this whole place.'">> <<else>><<set _greeting = "Ren pulls you aside before you even sit down, pressing close. Her lips brush your ear as she whispers, 'I've been waiting for you. I can barely keep my hands to myself today...' Her glowing eyes are intense with barely restrained desire.">> <</if>> <<elseif _npcName === "Clover">> <<set _maidColor = "#2ecc71">> <<if _relPoints < 25>><<set _greeting = "Clover turns to greet you with a bright smile, her enormous bust threatening to spill out of her maid uniform. She doesn't seem to notice or care. 'Welcome back, sweetie! Come sit with me!'">> <<elseif _relPoints < 75>><<set _greeting = "Clover beams when she sees you and hurries over, her voluptuous body bouncing with every step. She pulls you into a hug that buries your face in her ample chest. 'There you are! I baked something just for you today.'">> <<elseif _relPoints < 150>><<set _greeting = "Clover wraps her arms around you from behind, pressing her massive chest against your back. She smells like warm milk and vanilla. 'Mmm, I missed you. Sit with me during my break?'">> <<else>><<set _greeting = "Clover pulls you into the back room, her horns gleaming and her spotted white hair cascading over her shoulders. She sits in your lap like it's the most natural thing in the world, her curves overwhelming. 'I've been so pent up today... you have no idea what you do to me.'">> <</if>> <</if>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <<if _npcName === "Mochi">><h1 style="text-align: center; color: #ffb6c1; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🐱 Mochi</h1> <<elseif _npcName === "Ren">><h1 style="text-align: center; color: #9b59b6; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🦊 Ren</h1> <<elseif _npcName === "Clover">><h1 style="text-align: center; color: #2ecc71; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🐄 Clover</h1> <</if>> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid <<= _maidColor>>; border-radius: 12px; padding: 15px; margin-bottom: 20px;"> <p style="color: #ccc; line-height: 1.6; margin: 0; font-style: italic;"><<= _greeting>></p> </div> <<if !_canChat>> <div style="background: rgba(255,105,180,0.1); border: 1px solid #ff69b4; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: center;"> <p style="color: #ff69b4; margin: 0; font-size: 14px;">You've already spent quality time with <<= _npcName>> today. Come back tomorrow!</p> </div> <</if>> <h2 style="color: <<= _maidColor>>;">What do you do?</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-bottom: 20px;"> <<if _npcName === "Mochi">> <div style="border: 2px solid #ffb6c1; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #ffb6c1; margin: 0 0 6px 0;">😊 Friendly Chat</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Have a casual conversation.</p> <<if _canChat>> <<link "<div style='background: #ffb6c1; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Friendly Chat</div>">> <<set $pufferfishChatType = "friendly">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "friendly")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 13px; cursor: not-allowed;">Already chatted</div> <</if>> </div> <<elseif _npcName === "Ren">> <div style="border: 2px solid #9b59b6; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #9b59b6; margin: 0 0 6px 0;">😊 Friendly Chat</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Have a casual conversation.</p> <<if _canChat>> <<link "<div style='background: #9b59b6; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Friendly Chat</div>">> <<set $pufferfishChatType = "friendly">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "friendly")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 13px; cursor: not-allowed;">Already chatted</div> <</if>> </div> <<elseif _npcName === "Clover">> <div style="border: 2px solid #2ecc71; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #2ecc71; margin: 0 0 6px 0;">😊 Friendly Chat</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Have a casual conversation.</p> <<if _canChat>> <<link "<div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Friendly Chat</div>">> <<set $pufferfishChatType = "friendly">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "friendly")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 13px; cursor: not-allowed;">Already chatted</div> <</if>> </div> <</if>> <<if _npcName === "Mochi">> <div style="border: 2px solid #ffb6c1; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #ffb6c1; margin: 0 0 6px 0;">✨ Compliment</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Say something nice.</p> <<if _canChat>> <<link "<div style='background: #ffb6c1; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Compliment</div>">> <<set $pufferfishChatType = "compliment">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "compliment")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 13px; cursor: not-allowed;">Already chatted</div> <</if>> </div> <<elseif _npcName === "Ren">> <div style="border: 2px solid #9b59b6; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #9b59b6; margin: 0 0 6px 0;">✨ Compliment</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Say something nice.</p> <<if _canChat>> <<link "<div style='background: #9b59b6; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Compliment</div>">> <<set $pufferfishChatType = "compliment">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "compliment")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 13px; cursor: not-allowed;">Already chatted</div> <</if>> </div> <<elseif _npcName === "Clover">> <div style="border: 2px solid #2ecc71; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #2ecc71; margin: 0 0 6px 0;">✨ Compliment</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Say something nice.</p> <<if _canChat>> <<link "<div style='background: #2ecc71; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Compliment</div>">> <<set $pufferfishChatType = "compliment">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "compliment")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> <<else>> <div style="background: #444; color: #888; padding: 8px; border-radius: 6px; text-align: center; font-weight: bold; font-size: 13px; cursor: not-allowed;">Already chatted</div> <</if>> </div> <</if>> <<if _relPoints >= 25 && _canChat>> <<if _npcName === "Mochi">> <div style="border: 2px solid #e91e63; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #e91e63; margin: 0 0 6px 0;">💋 Flirt</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Get a little flirty.</p> <<link "<div style='background: #e91e63; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Flirt</div>">> <<set $pufferfishChatType = "flirt">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "flirt")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> </div> <<elseif _npcName === "Ren">> <div style="border: 2px solid #e91e63; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #e91e63; margin: 0 0 6px 0;">💋 Flirt</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Get a little flirty.</p> <<link "<div style='background: #e91e63; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Flirt</div>">> <<set $pufferfishChatType = "flirt">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "flirt")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> </div> <<elseif _npcName === "Clover">> <div style="border: 2px solid #e91e63; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #e91e63; margin: 0 0 6px 0;">💋 Flirt</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Get a little flirty.</p> <<link "<div style='background: #e91e63; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Flirt</div>">> <<set $pufferfishChatType = "flirt">> <<set _chatResult = setup.maidCafe.calculateChatPoints(_npcName, "flirt")>> <<run setup.addRelationshipPoints(_npcName, _chatResult.points)>> <<run setup.maidCafe.markChatted(_npcName)>> <<set $pufferfishChatPts = _chatResult.points>> <<set $pufferfishChatFlavor = _chatResult.flavor>> <<advancetime 15>> <<goto "PufferfishChatResult">> <</link>> </div> <</if>> <</if>> <<if _relPoints >= 75>> <<if _npcName === "Mochi">> <div style="border: 2px solid #d81b60; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #d81b60; margin: 0 0 6px 0;">🔥 Get Intimate</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Take things further.</p> <<link "<div style='background: #d81b60; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Get Intimate</div>">> <<set $preNPCLocation = "ThePufferfish">> <<set $tradingWithNPC = $npcs.find(function(n) { return n.name === _npcName; })>> <<if !$npcRomance>><<set $npcRomance = {}>><</if>> <<if !$npcRomance[_npcName]>><<run setup.romance.initRomance(_npcName)>><</if>> <<set $romanceTarget = _npcName>> <<goto "RomanceInitiate">> <</link>> </div> <<elseif _npcName === "Ren">> <div style="border: 2px solid #d81b60; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #d81b60; margin: 0 0 6px 0;">🔥 Get Intimate</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Take things further.</p> <<link "<div style='background: #d81b60; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Get Intimate</div>">> <<set $preNPCLocation = "ThePufferfish">> <<set $tradingWithNPC = $npcs.find(function(n) { return n.name === _npcName; })>> <<if !$npcRomance>><<set $npcRomance = {}>><</if>> <<if !$npcRomance[_npcName]>><<run setup.romance.initRomance(_npcName)>><</if>> <<set $romanceTarget = _npcName>> <<goto "RomanceInitiate">> <</link>> </div> <<elseif _npcName === "Clover">> <div style="border: 2px solid #d81b60; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #d81b60; margin: 0 0 6px 0;">🔥 Get Intimate</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Take things further.</p> <<link "<div style='background: #d81b60; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Get Intimate</div>">> <<set $preNPCLocation = "ThePufferfish">> <<set $tradingWithNPC = $npcs.find(function(n) { return n.name === _npcName; })>> <<if !$npcRomance>><<set $npcRomance = {}>><</if>> <<if !$npcRomance[_npcName]>><<run setup.romance.initRomance(_npcName)>><</if>> <<set $romanceTarget = _npcName>> <<goto "RomanceInitiate">> <</link>> </div> <</if>> <</if>> <div style="border: 2px solid #666; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <h4 style="color: #aaa; margin: 0 0 6px 0;">🗣 Full Interaction</h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px 0;">Trade, talk topics, view full profile.</p> <<link "<div style='background: #666; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>Interact</div>">> <<set $preNPCLocation = "ThePufferfish">> <<goto "NPCInteraction">> <</link>> </div> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npc = $tradingWithNPC>> <<set _npcName = _npc.name>> <<set _chatType = $pufferfishChatType>> <<set _maidColor = "#ff69b4">> <<if _npcName === "Mochi">><<set _maidColor = "#ffb6c1">> <<elseif _npcName === "Ren">><<set _maidColor = "#9b59b6">> <<elseif _npcName === "Clover">><<set _maidColor = "#2ecc71">> <</if>> <<set _response = "">> <<set _responseRoll = random(1, 3)>> <<if _chatType === "friendly">> <<if _npcName === "Mochi">> <<if _responseRoll === 1>><<set _response = "Mochi chatters excitedly about the new dessert menu she's been working on. Her tail wags as she describes each creation in loving detail, accidentally knocking over a sugar dispenser. 'Kyaa! S-sorry!'">> <<elseif _responseRoll === 2>><<set _response = "Mochi shows you a stray cat she's been feeding behind the cafe. 'Don't tell anyone,' she whispers, ears twitching. 'But I named him Mr. Whiskers and he's basically my best friend now.'">> <<else>><<set _response = "Mochi tells you about her morning, how she practiced a new latte art design. 'Look, look!' She proudly presents a cup with a wobbly cat face drawn in foam. 'It's supposed to be me! ...Does it look like me?'">> <</if>> <<elseif _npcName === "Ren">> <<if _responseRoll === 1>><<set _response = "Ren tells you about the book she's reading, some obscure mythology collection. Her eyes light up as she explains kitsune folklore, then catches herself. 'Sorry. I get carried away. Most people find it boring.' Her tail flicks, betraying how much she wants you to ask more.">> <<elseif _responseRoll === 2>><<set _response = "Ren leans back and shares a story about her life before the cafe. 'I've lived many places,' she says, swirling her tea. 'But nowhere felt like home until here.' Her glowing eyes study your reaction carefully.">> <<else>><<set _response = "Ren shows you a trick with her fox fire, letting tiny violet flames dance between her fingers. 'Useless party trick,' she says with false modesty. 'But the customers love it. Almost as much as they love staring at my ass in this uniform.' She winks.">> <</if>> <<elseif _npcName === "Clover">> <<if _responseRoll === 1>><<set _response = "Clover tells you about her garden at home, how she grows herbs for the cafe's recipes. 'There's something so satisfying about growing things,' she says, absently adjusting her straining uniform. 'Nurturing them until they bloom.'">> <<elseif _responseRoll === 2>><<set _response = "Clover insists on feeding you a sample of her homemade cookies, holding one up to your lips. 'Open wide~' She watches you chew with a warm, nurturing expression. 'Good, right? I put extra love in them today.'">> <<else>><<set _response = "Clover leans forward across the table to chat, giving you an unavoidable view of her massive cleavage. She either doesn't notice or doesn't care. 'You know, you're my favorite customer. Don't tell the others.' She giggles.">> <</if>> <</if>> <<elseif _chatType === "compliment">> <<if _npcName === "Mochi">> <<if _responseRoll === 1>><<set _response = "Mochi's face turns bright red, matching her pink hair. Her ears flatten and she hides behind her tray. 'Y-you really think so? Nobody's ever...' Her tail wraps around her own leg nervously. '...thank you.'">> <<elseif _responseRoll === 2>><<set _response = "Mochi squeaks and nearly drops her tray. 'M-me?! Pretty?!' She fidgets, tugging at her maid headband. 'I just... I mean... you're the pretty one!' She looks mortified at her own outburst.">> <<else>><<set _response = "Mochi freezes, then a slow, genuine smile spreads across her face. 'That's... the nicest thing anyone's said to me all week.' She reaches out and squeezes your hand softly, her small fingers warm. 'Thank you. Really.'">> <</if>> <<elseif _npcName === "Ren">> <<if _responseRoll === 1>><<set _response = "Ren's smirk widens. 'Flattery? From you?' She leans closer, close enough for you to catch her scent — something musky and intoxicating. 'Keep going. I'm listening.' Her tail swishes with pleasure.">> <<elseif _responseRoll === 2>><<set _response = "For once, Ren's composure cracks. A genuine flush colors her cheeks and her fox ears twitch. 'I...' She recovers quickly, but you caught it. 'Well. You certainly know how to make a fox feel special.'">> <<else>><<set _response = "Ren catches your hand and brings it to her lips, pressing a deliberate kiss to your knuckles. Her glowing eyes never leave yours. 'You have excellent taste,' she murmurs against your skin. 'In more ways than one.'">> <</if>> <<elseif _npcName === "Clover">> <<if _responseRoll === 1>><<set _response = "Clover giggles and does a little twirl, her massive bust bouncing. 'Aww, you charmer! Come here.' She pulls you into another suffocating hug. 'You always know just what to say to make a girl feel good.'">> <<elseif _responseRoll === 2>><<set _response = "Clover bites her lip and gives you a look that's half cute, half smoldering. 'You think I'm pretty? Even with these?' She taps her horns. 'Most people stare at... other things.' Her eyes drop pointedly to her own chest, then back up with a sly grin.">> <<else>><<set _response = "Clover places her hand over her heart — which means her hand is resting on her enormous breast. 'That means so much to me, sweetie.' She leans in conspiratorially. 'Between you and me, I dress up extra cute on days I think you'll visit.'">> <</if>> <</if>> <<elseif _chatType === "flirt">> <<if _npcName === "Mochi">> <<if _responseRoll === 1>><<set _response = "Mochi's entire face goes scarlet. Her tail puffs up and she makes a tiny 'mrrp!' sound. 'Y-you can't just SAY things like that!' But she doesn't move away. If anything, she inches closer. '...say it again?'">> <<elseif _responseRoll === 2>><<set _response = "Mochi covers her face with both hands, peeking through her fingers. 'A-are you flirting with me?' Her voice is tiny but her tail is wagging furiously. 'Because... I don't hate it. At all. Please continue.'">> <<else>><<set _response = "Mochi buries her face in your chest to hide her blush. You can feel her cat ears tickling your chin. 'You're so mean,' she mumbles. 'Making my heart go all crazy like this.' She peeks up at you. '...but don't stop.'">> <</if>> <<elseif _npcName === "Ren">> <<if _responseRoll === 1>><<set _response = "Ren's eyes darken with interest. She catches your chin between her fingers and tilts your face up. 'Careful,' she purrs. 'Flirting with a fox is dangerous. We don't play fair.' Her thumb traces your lower lip.">> <<elseif _responseRoll === 2>><<set _response = "Ren pulls you close by the waist. You can feel the heat radiating off her body. 'You want to play that game?' Her voice drops low. 'I should warn you — I always win.' Her tail coils around your thigh possessively.">> <<else>><<set _response = "Ren leans in until her lips almost touch yours. 'You're being very brave,' she whispers. 'Or very foolish. Either way...' She pulls back with a dangerous smile. 'I like it. A lot.' She presses her thighs together, her arousal barely contained.">> <</if>> <<elseif _npcName === "Clover">> <<if _responseRoll === 1>><<set _response = "Clover's eyes light up and she leans forward, her massive breasts pressing against the table. 'Ooh, getting bold, are we?' She runs a finger down your arm. 'I like bold. Keep it up and I might drag you into the back room.'">> <<elseif _responseRoll === 2>><<set _response = "Clover giggles and 'accidentally' drops a napkin, bending over right in front of you. She takes her sweet time picking it up. 'Oops~' she says innocently, looking back over her shoulder with a grin. 'See something you like?'">> <<else>><<set _response = "Clover grabs your hand and presses it against her chest. You can feel her heartbeat racing through her enormous breast. 'Feel that?' she breathes. 'That's what you do to me, sweetie. And that's just above the waist.' She winks.">> <</if>> <</if>> <</if>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <h2 style="text-align: center; color: <<= _maidColor>>; text-shadow: 0 0 10px rgba(255,105,180,0.3);"><<= _npcName>></h2> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid <<= _maidColor>>; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;"> <p style="color: #ccc; line-height: 1.7; margin: 0;"><<= _response>></p> </div> <div style="text-align: center;"> <p style="color: <<= _maidColor>>; font-size: 14px; font-style: italic;"><<= _npcName>> <<= $pufferfishChatFlavor>>.</p> </div> <div style="display: flex; gap: 15px; justify-content: center; margin-top: 20px; flex-wrap: wrap;"> <<if _npcName === "Mochi">> <<link "<div style='background: #ffb6c1; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Back to Chat</div>">> <<goto "PufferfishChat">> <</link>> <<elseif _npcName === "Ren">> <<link "<div style='background: #9b59b6; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Back to Chat</div>">> <<goto "PufferfishChat">> <</link>> <<elseif _npcName === "Clover">> <<link "<div style='background: #2ecc71; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Back to Chat</div>">> <<goto "PufferfishChat">> <</link>> <</if>> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _perfDay = $dayNumber % 7>> <<set _alreadyWatched = $pufferfishPerfDay === $dayNumber>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <h1 style="text-align: center; color: #ffb6c1; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🎶 Today's Performance</h1> <!-- Performance content based on day --> <<if _perfDay === 0>> <!-- Mochi: Cat Dance --> <<set _perfMaid = "Mochi">> <<set _perfColor = "#ffb6c1">> <<set _perfTitle = "🐱 Mochi's Kitty Dance">> <<set _perfDesc = "Mochi takes the small stage, her pink hair bouncing as she performs an adorable cat-themed dance. Her werecat ears twitch in time with the music, and her tail sways gracefully. She stumbles once, catches herself with a 'Nyaa!', and the audience erupts in cheers. Her cheeks flush as she takes a clumsy bow.">> <<elseif _perfDay === 1>> <!-- Ren: Fox Fire Show --> <<set _perfMaid = "Ren">> <<set _perfColor = "#9b59b6">> <<set _perfTitle = "🦊 Ren's Fox Fire Illusions">> <<set _perfDesc = "The lights dim as Ren steps forward, her glowing eyes piercing the darkness. Violet fox fire dances between his fingers, forming shapes — a butterfly, a dragon, a blooming flower. Her purple hair catches the ethereal light as she moves with practiced elegance. The flames spiral around him before bursting into sparks that rain down like tiny stars. She finishes with a smoldering look at the audience that makes several patrons fan themselves.">> <<elseif _perfDay === 2>> <!-- Clover: Baking Demo --> <<set _perfMaid = "Clover">> <<set _perfColor = "#2ecc71">> <<set _perfTitle = "🐄 Clover's Sweet Treats Show">> <<set _perfDesc = "Clover sets up a small baking station on stage, her enormous bust barely contained by her flour-dusted apron. She narrates each step in a warm, motherly tone while kneading dough with surprising skill. 'The secret ingredient is fresh cream~' she says with a wink, gesturing at herself. The audience laughs. She distributes warm pastries to the front row, leaning forward generously.">> <<elseif _perfDay === 3>> <!-- All three: Group Number --> <<set _perfMaid = "all">> <<set _perfColor = "#ff69b4">> <<set _perfTitle = "💖 Puffy's Special: Group Performance">> <<set _perfDesc = "All three maids take the stage together. Mochi handles the choreography — simple, cute moves that even Clover can follow. Ren adds dramatic flair with fox fire accents. Clover provides the vocals, her rich voice surprisingly beautiful. Mochi trips into Ren, who catches her smoothly without missing a beat. Clover laughs and pulls them both into a group pose. The cafe erupts in applause.">> <<elseif _perfDay === 4>> <!-- Mochi: Song --> <<set _perfMaid = "Mochi">> <<set _perfColor = "#ffb6c1">> <<set _perfTitle = "🎵 Mochi's Lullaby">> <<set _perfDesc = "Mochi sits on a stool with a small ukulele, her tail curled around the leg. She starts to sing softly — a gentle, lilting melody about the ocean. Her voice wavers with nerves at first, but as the cafe goes quiet, she finds her confidence. By the end, her big eyes are glistening. The audience sits in hushed silence before breaking into warm applause. Mochi hides behind the ukulele, ears pink.">> <<elseif _perfDay === 5>> <!-- Ren: Storytelling --> <<set _perfMaid = "Ren">> <<set _perfColor = "#9b59b6">> <<set _perfTitle = "📖 Ren's Kitsune Tales">> <<set _perfDesc = "Ren reclines in a velvet chair, legs crossed, and tells an old kitsune folk tale. Her silky voice weaves through the story — a tale of a fox who fell in love with a mortal. Fox fire illustrations float in the air beside him, painting scenes from the story. Her glowing eyes grow distant as she reaches the bittersweet ending. The audience is spellbound. 'All love stories are a little sad,' she murmurs. 'That's what makes them beautiful.'">> <<else>> <!-- Clover: Cosplay Parade --> <<set _perfMaid = "Clover">> <<set _perfColor = "#2ecc71">> <<set _perfTitle = "🎀 Clover's Costume Showcase">> <<set _perfDesc = "Clover models a series of outfits, each more outrageous than the last. A nurse outfit that barely contains her curves. A schoolgirl uniform stretched to its absolute limit. A bunny suit that leaves nothing to the imagination. She poses shamelessly for each one, asking the audience to vote for their favorite. 'I couldn't possibly choose,' she says, hands on her hips. 'They all feel so... snug.' She shimmies and the audience loses it.">> <</if>> <!-- Check if performing maid(s) are actually recruited --> <<set _staffNames = []>> <<if $cafeOwnership && $cafeOwnership.staff>> <<for _s range $cafeOwnership.staff>> <<run _staffNames.push(_s.name)>> <</for>> <</if>> <<set _perfAvailable = false>> <<if _perfMaid === "all">> <<set _perfAvailable = _staffNames.length > 0>> <<else>> <<set _perfAvailable = _staffNames.includes(_perfMaid)>> <</if>> <<if !_perfAvailable>> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #666; border-radius: 12px; padding: 30px; margin-bottom: 20px; text-align: center;"> <h2 style="color: #888; margin: 0 0 15px 0;">🎶 No Performance Today</h2> <p style="color: #666; line-height: 1.7; margin: 0;">The stage is empty. You'll need to recruit maid staff before performances can begin.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> <<else>> <!-- Show description --> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid <<= _perfColor>>; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h2 style="color: <<= _perfColor>>; margin: 0 0 15px 0; text-align: center;"><<= _perfTitle>></h2> <p style="color: #ccc; line-height: 1.7; margin: 0;"><<= _perfDesc>></p> </div> <!-- Watch button or already watched --> <<if _alreadyWatched>> <div style="text-align: center; margin-bottom: 20px;"> <p style="color: #ff69b4; font-style: italic;">You already enjoyed today's show. Come back tomorrow for something new!</p> </div> <<else>> <div style="text-align: center; margin-bottom: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 12px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px;'>👏 Applaud</div>">> <<set $pufferfishPerfDay = $dayNumber>> <<advancetime 30>> <!-- Relationship boost for performing maid(s) --> <<if !$relationships>><<set $relationships = {}>><</if>> <<if _perfMaid === "all">> <<run setup.addRelationshipPoints("Mochi", 2)>> <<run setup.addRelationshipPoints("Ren", 2)>> <<run setup.addRelationshipPoints("Clover", 2)>> <<else>> <<run setup.addRelationshipPoints(_perfMaid, 3)>> <</if>> <<goto "PufferfishPerformance">> <</link>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<run setup.maidCafe.initData()>> <<set _canWork = setup.maidCafe.canWork()>> <<if !_canWork.allowed && $maidWorkState !== "complete">> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 30px; max-width: 500px; text-align: center;"> <h2 style="color: #ff69b4; margin: 0 0 15px 0;">🐡 Can't Work Right Now</h2> <p style="color: #ccc; line-height: 1.6;"><<= _canWork.reason>></p> <<link "<div style='background: #ff69b4; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold; margin-top: 15px;'>Back</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <<else>> <<set _tier = setup.maidCafe.getTier()>> <<set _tierInfo = setup.maidCafe.tiers[_tier]>> <<if !$maidWorkState>><<set $maidWorkState = "start">><</if>> <!-- Defensive: if the player navigated away mid-shift (e.g., to inventory) and re-entered PufferfishWork, $maidWorkState may be in an intermediate state owned by PufferfishWorkReaction. Advance to the next stable state so the page renders content instead of just the header. --> <<if $maidWorkState === "reaction" || $maidWorkState === "followup" || $maidWorkState === "vip" || $maidWorkState === "coworker" || $maidWorkState === "coworkerIntimate" || $maidWorkState === "event">> <<if $maidWorkCustomers && $maidWorkIndex >= $maidWorkCustomers.length>> <<set $maidWorkState = "complete">> <<else>> <<set $maidWorkState = "serve">> <</if>> <</if>> <!-- ===== START STATE ===== --> <<if $maidWorkState === "start">> <<set $maidWorkCustomers = []>> <<set $maidWorkActions = []>> <<set $maidWorkTips = []>> <<set $maidWorkIndex = 0>> <<set $maidWorkBonusTips = 0>> <<set $maidWorkCoworker = setup.maidCafe.getCoworkerForShift()>> <<set $maidWorkCoworkerUsed = false>> <<set $maidWorkEventUsed = false>> <<set $maidWorkVIPChoice = null>> <<set _numCustomers = _tierInfo.customersPerShift>> /* Oni debuff: customers avoid the cafe, cut shift count in half (min 1). */ <<if setup.oniBuffs && setup.oniBuffs.isOni && setup.oniBuffs.isOni()>> <<set _numCustomers = Math.max(1, Math.floor(_numCustomers * setup.oniBuffs.cafeCustomerMultiplier))>> <</if>> <<for _ci = 0; _ci < _numCustomers; _ci++>> <<run $maidWorkCustomers.push(setup.maidCafe.generateCustomer())>> <</for>> <<set $maidWorkState = "serve">> <</if>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <h1 style="text-align: center; color: #ffb6c1; text-shadow: 0 0 10px rgba(255,105,180,0.3); margin-bottom: 5px;">🐡 Maid Shift</h1> <p style="text-align: center; color: #ff69b4; font-style: italic; margin-top: 0; margin-bottom: 5px;"><<= _tierInfo.name>> — <<= $maidCafeData.xp>> XP</p> <<if $maidWorkCoworker>><p style="text-align: center; color: #aaa; margin-top: 0; margin-bottom: 5px; font-size: 13px;">Working with: <strong style="color: #2ecc71;"><<= $maidWorkCoworker>></strong></p><</if>> <p style="text-align: center; color: #aaa; margin-top: 0; margin-bottom: 20px;">Customer <<= $maidWorkIndex + 1>> of <<= $maidWorkCustomers.length>></p> <!-- ===== SERVE STATE ===== --> <<if $maidWorkState === "serve">> <<if $maidWorkIndex >= $maidWorkCustomers.length>> <<set $maidWorkState = "complete">> <<goto "PufferfishWork">> <<else>> <<set _customer = $maidWorkCustomers[$maidWorkIndex]>> <<set _moodEmoji = "">> <<if _customer.mood === "happy">><<set _moodEmoji = "😊">> <<elseif _customer.mood === "impatient">><<set _moodEmoji = "⏰">> <<elseif _customer.mood === "shy">><<set _moodEmoji = "😳">> <<elseif _customer.mood === "flirty">><<set _moodEmoji = "😉">> <<elseif _customer.mood === "grumpy">><<set _moodEmoji = "😠">> <<elseif _customer.mood === "excited">><<set _moodEmoji = "🤩">> <<elseif _customer.mood === "bored">><<set _moodEmoji = "😴">> <</if>> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 15px; margin-bottom: 20px;"> <p style="color: #ccc; line-height: 1.6; margin: 0;">You approach <<= _customer.name>>. They seem <span style="color: #ff69b4; font-weight: bold;"><<= _moodEmoji>> <<= _customer.mood>></span>.</p> </div> <h2 style="color: #ffb6c1;">How do you serve them?</h2> <<set _options = setup.maidCafe.getActionOptions(_tier, _customer.mood)>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 20px;"> <<for _opt range _options>> <<set _cardStyle = "border: 2px solid " + _opt.color + "; border-radius: 10px; padding: 12px; background: #2a2a2a;">> <<set _headStyle = "color: " + _opt.color + "; margin: 0 0 6px;">> <<set _btnHtml = "<div style='background: " + _opt.color + "; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 13px;'>" + _opt.label + "</div>">> <div @style="_cardStyle"> <h4 @style="_headStyle"><<= _opt.emoji>> <<= _opt.label>></h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 8px;"><<= _opt.desc>></p> <<capture _opt, _btnHtml>> <<link _btnHtml>> <<set _customer = $maidWorkCustomers[$maidWorkIndex]>> <<if _opt.isVIP>> <<set _vipScene = setup.maidCafe.getVIPScene(_customer.mood, _customer.gender)>> <<set $maidWorkVIPScene = _vipScene>> <<set $maidWorkVIPChoice = null>> <<set $maidWorkState = "vip">> <<advancetime 30>> <<goto "PufferfishWorkReaction">> <<else>> <<set _dialogue = setup.maidCafe.dialogueReactions[_opt.type]>> <<if _dialogue && _dialogue[_customer.mood]>> <<set $maidWorkReaction = _dialogue[_customer.mood]>> <<else>> <<set $maidWorkReaction = {reaction: "You serve them with " + _opt.type + " energy. They seem to appreciate it.", followUps: [{label: "Continue serving", actionCount: _opt.type, tipMult: 1.0}, {label: "Move on", actionCount: "professional", tipMult: 0.8}]}>> <</if>> <<set $maidWorkCurrentAction = _opt.type>> <<set $maidWorkState = "reaction">> <<advancetime 20>> <<goto "PufferfishWorkReaction">> <</if>> <</link>> <</capture>> </div> <</for>> </div> <!-- Man the Kitchen (player cooking action) --> <<if ($skills && $skills.indexOf("Cooking") !== -1) || ($cafeOwnership && $cafeOwnership.playerCookingProf >= 25)>> <div style="background: linear-gradient(135deg, #3a2a1a 0%, #2a1e10 100%); border: 2px solid #e67e22; border-radius: 10px; padding: 15px; margin-top: 10px; text-align: center;"> <p style="color: #f5c890; margin: 0 0 10px 0; font-size: 14px;">🍳 The kitchen is slammed. Step away from the floor and take over the stoves for the rest of the shift.</p> <<link "<div style='background: #e67e22; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>🍳 Man the Kitchen</div>">> <<set $cafeOwnership.playerCookingProf += 3>> <<set $maidWorkManKitchen = true>> <<set $maidWorkState = "complete">> <<advancetime 60>> <<goto "PufferfishWork">> <</link>> </div> <</if>> <</if>> <!-- ===== EVENT STATE ===== --> <<elseif $maidWorkState === "event">> <<set _event = $maidWorkCurrentEvent>> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #f39c12; border-radius: 12px; padding: 20px; margin-bottom: 20px; text-align: center;"> <h2 style="color: #f39c12; margin: 0 0 10px;">⚡ <<= _event.title>></h2> <p style="color: #ccc; line-height: 1.6; margin: 0 0 15px;"><<= _event.text>></p> <div style="display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;"> <<for _choice range _event.choices>> <<capture _choice>> <<link "<div style='background: #f39c12; color: #1a1a1a; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 13px;'><<= _choice.label>></div>">> <<set $maidWorkBonusTips += _choice.tipEffect>> <<set $maidCafeData.xp += _choice.xpEffect>> <<if $maidCafeData.actionCounts[_choice.actionCount] !== undefined>> <<set $maidCafeData.actionCounts[_choice.actionCount] += 1>> <</if>> <<set $maidWorkEventUsed = true>> <<set $maidWorkState = "serve">> <<goto "PufferfishWork">> <</link>> <</capture>> <</for>> </div> </div> <!-- ===== COWORKER STATE ===== --> <<elseif $maidWorkState === "coworker">> <<set _cwName = $maidWorkCoworker>> <<set _cwComments = setup.maidCafe.coworkerComments[_cwName]>> <<set _avgTip = 0>> <<if $maidWorkTips.length > 0>> <<for _t range $maidWorkTips>><<set _avgTip += _t>><</for>> <<set _avgTip = Math.floor(_avgTip / $maidWorkTips.length)>> <</if>> <<set _cwText = _avgTip >= 15 ? _cwComments.goodService : _cwComments.badService>> <div style="background: linear-gradient(135deg, #1a2a1a 0%, #0d1a0d 100%); border: 2px solid #2ecc71; border-radius: 12px; padding: 20px; margin-bottom: 20px; text-align: center;"> <h2 style="color: #2ecc71; margin: 0 0 10px;">👥 <<= _cwName>></h2> <p style="color: #ccc; line-height: 1.6; font-style: italic; margin: 0 0 15px;"><<= _cwText>></p> <div style="display: flex; gap: 12px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='background: #2ecc71; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Accept help (+10% next tip)</div>">> <<set $maidWorkBonusTips += 5>> <<set $maidWorkCoworkerUsed = true>> <<set $maidWorkState = "serve">> <<goto "PufferfishWork">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Thanks, I've got this</div>">> <<set $maidWorkCoworkerUsed = true>> <<set $maidWorkState = "serve">> <<goto "PufferfishWork">> <</link>> </div> </div> <!-- ===== COMPLETE STATE ===== --> <<elseif $maidWorkState === "complete">> <<set _results = setup.maidCafe.getShiftResults($maidWorkActions, $maidWorkTips, _tier)>> <<set _results.totalPay += $maidWorkBonusTips>> <<set _transformBonus = setup.maidCafe.getTransformBonus()>> <<if _transformBonus.mult > 1.0>> <<set _transformExtra = Math.round(_results.totalPay * (_transformBonus.mult - 1))>> <<set _results.totalPay += _transformExtra>> <<elseif _transformBonus.mult < 1.0>> /* Oni debuff: cafe customers are scared of you, total pay is reduced. */ <<set _transformExtra = -Math.round(_results.totalPay * (1 - _transformBonus.mult))>> <<set _results.totalPay += _transformExtra>> <<if _results.totalPay < 0>><<set _results.totalPay = 0>><</if>> <</if>> <<set $money += _results.totalPay>> <<set _traitGains = setup.maidCafe.checkTraitGains()>> <<run setup.cafe.grantShiftProficiency()>> <<set $maidWorkState = null>> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 20px; margin-bottom: 20px; text-align: center;"> <h2 style="color: #ffb6c1; margin: 0 0 15px;">🎉 Shift Complete!</h2> <p style="color: #ccc; margin: 5px 0;">Base Pay: <span style="color: #ffd700;">$<<= _results.basePay>></span></p> <p style="color: #ccc; margin: 5px 0;">Tips: <span style="color: #ffd700;">$<<= _results.totalTips>></span></p> <<if $maidWorkBonusTips > 0>><p style="color: #ccc; margin: 5px 0;">Event Bonus: <span style="color: #f39c12;">$<<= $maidWorkBonusTips>></span></p><</if>> <<if _results.streakExtra > 0>><p style="color: #ccc; margin: 5px 0;">🔥 Streak Bonus (<<= _results.streakCount>>-day): <span style="color: #e67e22;">+$<<= _results.streakExtra>></span></p><</if>> <<if _transformBonus.mult > 1.0>><p style="color: #ccc; margin: 5px 0;"><<= _transformBonus.label>>: <span style="color: #e91e63;">+$<<= _transformExtra>></span></p><<elseif _transformBonus.mult < 1.0>><p style="color: #ccc; margin: 5px 0;"><<= _transformBonus.label>>: <span style="color: #e74c3c;">$<<= _transformExtra>></span></p><</if>> <p style="color: #ffd700; font-size: 18px; font-weight: bold; margin: 10px 0;">Total: $<<= _results.totalPay>></p> <p style="color: #ff69b4; margin: 5px 0;">+<<= _results.xpGain>> XP</p> <<if _results.tierUp>> <div style="background: rgba(255,105,180,0.2); border: 2px solid #ff69b4; border-radius: 8px; padding: 12px; margin-top: 15px;"> <p style="color: #ff69b4; font-weight: bold; font-size: 16px; margin: 0;">🌟 Promoted to <<= setup.maidCafe.tiers[_results.newTier].name>>!</p> </div> <</if>> <<if _traitGains.length > 0>> <div style="background: rgba(46,204,113,0.2); border: 2px solid #2ecc71; border-radius: 8px; padding: 12px; margin-top: 15px;"> <p style="color: #2ecc71; font-weight: bold; margin: 0 0 5px;">🌟 New Traits Earned!</p> <<for _tg range _traitGains>> <p style="color: #2ecc71; margin: 2px 0;">✅ <<= _tg>></p> <</for>> </div> <</if>> </div> <!-- Coworker shift end comment --> <<if $maidWorkCoworker && setup.maidCafe.coworkerComments[$maidWorkCoworker]>> <div style="background: #1a1a1a; border: 1px solid #2ecc71; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: center;"> <p style="color: #aaa; font-style: italic; margin: 0;"><<= setup.maidCafe.coworkerComments[$maidWorkCoworker].shiftEnd>></p> </div> <</if>> <div style="text-align: center;"> <<link "<div style='background: #ff69b4; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> <</if>> </div> <</if>> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <!-- ===== REACTION STATE ===== --> <<if $maidWorkState === "reaction">> <h2 style="text-align: center; color: #ffb6c1; margin-bottom: 15px;">💬 Service Interaction</h2> <!-- Reaction prose --> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;"> <p style="color: #ccc; line-height: 1.7; margin: 0;"><<= $maidWorkReaction.reaction>></p> </div> <!-- Follow-up choices --> <h3 style="text-align: center; color: #aaa; margin-bottom: 12px;">What do you do next?</h3> <div style="display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; max-width: 600px; margin: 0 auto 20px;"> <<for _fu range $maidWorkReaction.followUps>> <<capture _fu>> <<link "<div style='background: #ff69b4; color: white; padding: 10px 20px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 13px; max-width: 280px; text-align: center;'><<= _fu.label>></div>">> <<set _customer = $maidWorkCustomers[$maidWorkIndex]>> <<set _compat = (setup.maidCafe.moodCompatibility[_customer.mood] || {})[_fu.actionCount] || 1.0>> <<set _tipResult = setup.maidCafe.calculateTip(_customer, $maidWorkCurrentAction, _fu.tipMult, setup.maidCafe.getTier())>> <<set _tip = _tipResult.tip>> <<run $maidWorkActions.push(_fu.actionCount)>> <<run $maidWorkTips.push(_tip)>> <<if $maidCafeData.actionCounts[_fu.actionCount] !== undefined>> <<set $maidCafeData.actionCounts[_fu.actionCount] += 1>> <</if>> <<set _resultPool = setup.maidCafe.followUpResults[_fu.actionCount] || ["The customer seems satisfied."]>> <<set $maidWorkFollowUpText = _resultPool[Math.floor(Math.random() * _resultPool.length)]>> <<set $maidWorkLastTip = _tip>> <<set $maidWorkIndex += 1>> <<set $maidWorkState = "followup">> <<goto "PufferfishWorkReaction">> <</link>> <</capture>> <</for>> </div> <!-- ===== FOLLOWUP STATE ===== --> <<elseif $maidWorkState === "followup">> <div style="background: linear-gradient(135deg, #2a2035 0%, #1e1e2e 100%); border: 2px solid #ff69b4; border-radius: 12px; padding: 25px; margin-bottom: 20px; max-width: 500px; margin-left: auto; margin-right: auto; text-align: center;"> <p style="color: #ccc; line-height: 1.6; font-size: 15px; margin: 0 0 15px;"><<= $maidWorkFollowUpText>></p> <p style="color: #ffd700; font-weight: bold; font-size: 20px; margin: 0;">Tip: $<<= $maidWorkLastTip>></p> </div> <div style="text-align: center;"> <!-- Check if random event or coworker should trigger --> <<set _nextState = "serve">> <<if $maidWorkIndex >= $maidWorkCustomers.length>> <<set _nextState = "complete">> <<elseif !$maidWorkEventUsed && $maidWorkIndex === 2 && random(1, 100) <= 20>> <<set _nextState = "event">> <<set $maidWorkCurrentEvent = setup.maidCafe.rollRandomEvent(setup.maidCafe.getTier())>> <<elseif !$maidWorkCoworkerUsed && $maidWorkCoworker && $maidWorkIndex === 1 && setup.maidCafe.canDoCoworkerIntimate($maidWorkCoworker)>> <<set _nextState = "coworkerIntimate">> <<elseif !$maidWorkCoworkerUsed && $maidWorkCoworker && $maidWorkIndex === 1>> <<set _nextState = "coworker">> <</if>> <<link "<div style='background: #ff69b4; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'><<if _nextState === 'complete'>>Finish Shift<<else>>Next Customer<</if>></div>">> <<set $maidWorkState = _nextState>> <<if _nextState === "coworkerIntimate">> <<goto "PufferfishWorkReaction">> <<else>> <<goto "PufferfishWork">> <</if>> <</link>> </div> <!-- ===== VIP SCENE STATE ===== --> <<elseif $maidWorkState === "vip">> <<set _scene = $maidWorkVIPScene>> <<if _scene.isExpanded && !$maidWorkVIPChoice>> <!-- Branch A: Expanded intro + choices --> <h2 style="text-align: center; color: #8e24aa; margin-bottom: 15px;">💎 <<= _scene.title>></h2> <<if _scene.image>> <div style="text-align: center; margin-bottom: 15px;"> <<if $showExplicitImages !== false>> <<print '<img src="' + _scene.image + '" style="max-width: 100%; width: 500px; border-radius: 12px; border: 3px solid #8e24aa; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" />'>> <</if>> </div> <</if>> <div style="background: linear-gradient(135deg, #2a1a35 0%, #1a0d25 100%); border: 2px solid #8e24aa; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;"> <p style="color: #dcc; line-height: 1.8; margin: 0;"><<= _scene.intro>></p> </div> <h3 style="text-align: center; color: #aaa; margin-bottom: 12px;">What do you do?</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; max-width: 600px; margin: 0 auto 20px;"> <<for _ch range _scene.choices>> <<capture _ch>> <div style="border: 2px solid #8e24aa; border-radius: 10px; padding: 12px; background: #2a2a2a;"> <<link "<div style='background: #8e24aa; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; font-size: 14px;'><<= _ch.label>></div>">> <<set $maidWorkVIPChoice = _ch>> <<goto "PufferfishWorkReaction">> <</link>> </div> <</capture>> <</for>> </div> <<elseif _scene.isExpanded && $maidWorkVIPChoice>> <!-- Branch B: Choice made — show prose + tip --> <<set _ch = $maidWorkVIPChoice>> <h2 style="text-align: center; color: #8e24aa; margin-bottom: 15px;">💎 <<= _scene.title>></h2> <<if _scene.image>> <div style="text-align: center; margin-bottom: 15px;"> <<if $showExplicitImages !== false>> <<print '<img src="' + _scene.image + '" style="max-width: 100%; width: 500px; border-radius: 12px; border: 3px solid #8e24aa; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" />'>> <</if>> </div> <</if>> <div style="background: linear-gradient(135deg, #2a1a35 0%, #1a0d25 100%); border: 2px solid #8e24aa; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;"> <p style="color: #dcc; line-height: 1.8; margin: 0;"><<= _ch.text>></p> </div> <<set _vipTip = Math.round(setup.maidCafe.tiers[setup.maidCafe.getTier()].payBase * _ch.tipMult * (setup.maidCafe.tiers[setup.maidCafe.getTier()].vipBonus || 1.0))>> <<run $maidWorkTips.push(_vipTip)>> <<run $maidWorkActions.push("teasing")>> <<if $maidCafeData.actionCounts.teasing !== undefined>><<set $maidCafeData.actionCounts.teasing += 1>><</if>> <<set $maidCafeData.xp += _ch.xpBonus>> <<set $maidWorkIndex += 1>> <<set $maidWorkVIPChoice = null>> <div style="text-align: center;"> <p style="color: #ffd700; font-weight: bold; font-size: 20px;">VIP Tip: $<<= _vipTip>></p> <p style="color: #8e24aa; font-size: 14px;">+<<= _ch.xpBonus>> bonus XP</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: #8e24aa; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'><<if $maidWorkIndex >= $maidWorkCustomers.length>>Finish Shift<<else>>Next Customer<</if>></div>">> <<if $maidWorkIndex >= $maidWorkCustomers.length>> <<set $maidWorkState = "complete">> <<else>> <<set $maidWorkState = "serve">> <</if>> <<goto "PufferfishWork">> <</link>> </div> <<else>> <!-- Branch C: Non-expanded single paragraph --> <h2 style="text-align: center; color: #8e24aa; margin-bottom: 15px;">💎 <<= _scene.title>></h2> <<if _scene.image>> <div style="text-align: center; margin-bottom: 15px;"> <<if $showExplicitImages !== false>> <<print '<img src="' + _scene.image + '" style="max-width: 100%; width: 500px; border-radius: 12px; border: 3px solid #8e24aa; box-shadow: 0 4px 8px rgba(0,0,0,0.4);" />'>> <</if>> </div> <</if>> <div style="background: linear-gradient(135deg, #2a1a35 0%, #1a0d25 100%); border: 2px solid #8e24aa; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;"> <p style="color: #dcc; line-height: 1.8; margin: 0;"><<= _scene.text>></p> </div> <<set _vipTip = Math.round(setup.maidCafe.tiers[setup.maidCafe.getTier()].payBase * _scene.tipMult * (setup.maidCafe.tiers[setup.maidCafe.getTier()].vipBonus || 1.0))>> <<run $maidWorkTips.push(_vipTip)>> <<run $maidWorkActions.push("teasing")>> <<if $maidCafeData.actionCounts.teasing !== undefined>><<set $maidCafeData.actionCounts.teasing += 1>><</if>> <<set $maidCafeData.xp += _scene.xpBonus>> <<set $maidWorkIndex += 1>> <div style="text-align: center;"> <p style="color: #ffd700; font-weight: bold; font-size: 20px;">VIP Tip: $<<= _vipTip>></p> <p style="color: #8e24aa; font-size: 14px;">+<<= _scene.xpBonus>> bonus XP</p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: #8e24aa; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'><<if $maidWorkIndex >= $maidWorkCustomers.length>>Finish Shift<<else>>Next Customer<</if>></div>">> <<if $maidWorkIndex >= $maidWorkCustomers.length>> <<set $maidWorkState = "complete">> <<else>> <<set $maidWorkState = "serve">> <</if>> <<goto "PufferfishWork">> <</link>> </div> <</if>> <!-- ===== COWORKER INTIMATE STATE ===== --> <<elseif $maidWorkState === "coworkerIntimate">> <<set _cwScene = setup.maidCafe.getCoworkerIntimateScene($maidWorkCoworker)>> <<if _cwScene>> <h2 style="text-align: center; color: #e91e63; margin-bottom: 15px;">💖 <<= _cwScene.title>></h2> <div style="background: linear-gradient(135deg, #2a1520 0%, #1a0d15 100%); border: 2px solid #e91e63; border-radius: 12px; padding: 20px; margin-bottom: 20px; max-width: 600px; margin-left: auto; margin-right: auto;"> <p style="color: #dcc; line-height: 1.8; margin: 0;"><<= _cwScene.text>></p> </div> <<run setup.addRelationshipPoints($maidWorkCoworker, _cwScene.relBonus)>> <<set $maidWorkBonusTips += _cwScene.tipBonus>> <div style="text-align: center;"> <p style="color: #e91e63; font-size: 14px;">+<<= _cwScene.relBonus>> relationship with <<= $maidWorkCoworker>></p> </div> <div style="text-align: center; margin-top: 15px;"> <<link "<div style='background: #e91e63; color: white; padding: 10px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Work</div>">> <<set $maidWorkCoworkerUsed = true>> <<set $maidWorkState = "serve">> <<goto "PufferfishWork">> <</link>> </div> <</if>> <</if>> </div> <</nobr>>
<<nobr>> <<set $cafeOwnership.owned = true>> <<set $cafeOwnership.dayPurchased = $dayNumber>> <div style="background: linear-gradient(180deg, #0d1b2a 0%, #1b2838 50%, #0d1b2a 100%); min-height: 100vh; padding: 20px; color: #e0e0e0; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="background: linear-gradient(135deg, #1a2a1a 0%, #0d1a0d 100%); border: 3px solid #2ecc71; border-radius: 15px; padding: 30px; max-width: 600px; text-align: center;"> <h1 style="color: #2ecc71; text-shadow: 0 0 15px rgba(46,204,113,0.4); margin: 0 0 15px 0;">🎉 Congratulations!</h1> <p style="color: #ccc; font-size: 16px; line-height: 1.6; margin: 0 0 20px 0;">The city clerk stamps the deed and slides it across the counter with a smile. <em style="color: #2ecc71;">"The Outskirts property is officially yours. Welcome to the business owners of Sunfish City!"</em></p> <p style="color: #aaa; margin: 0 0 10px 0;">You hold the deed in your hands. It's a rundown building, but it's <em>yours</em>. All it needs is a name.</p> <h2 style="color: #2ecc71; margin: 20px 0 10px 0;">✏ Name Your Cafe</h2> <p style="color: #888; font-size: 13px; margin: 0 0 15px 0;">You can change this later for $500 (sign change fee).</p> <div id="cafeNamingBox" style="margin-bottom: 20px;"> <input id="cafeNameInput" type="text" value="Maid Cafe" maxlength="30" style="background: #1a1a1a; border: 2px solid #2ecc71; border-radius: 6px; color: #e0e0e0; padding: 10px 15px; font-size: 18px; text-align: center; width: 80%; max-width: 400px; outline: none;"> </div> <div id="cafeConfirmBtn"></div> <<run $(function() { var btn = $("<div>").css({ background: "linear-gradient(135deg, #2ecc71 0%, #27ae60 100%)", color: "white", padding: "12px 40px", borderRadius: "6px", textAlign: "center", cursor: "pointer", fontWeight: "bold", fontSize: "16px", display: "inline-block" }).text("Open Your Cafe!").on("click", function() { var name = $("#cafeNameInput").val().trim(); if (name.length === 0) name = "Maid Cafe"; State.variables.cafeOwnership.cafeName = name; SugarCube.Engine.play("CafeAcquisitionComplete"); }); $("#cafeConfirmBtn").append(btn); })>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0d1b2a 0%, #1b2838 50%, #0d1b2a 100%); min-height: 100vh; padding: 20px; color: #e0e0e0; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="background: linear-gradient(135deg, #1a2a1a 0%, #0d1a0d 100%); border: 3px solid #2ecc71; border-radius: 15px; padding: 30px; max-width: 600px; text-align: center;"> <h1 style="color: #ffd700; text-shadow: 0 0 15px rgba(255,215,0,0.4); margin: 0 0 15px 0; font-size: 28px;">✨ <<= $cafeOwnership.cafeName>> ✨</h1> <p style="color: #ccc; font-size: 16px; line-height: 1.6; margin: 0 0 15px 0;">You step back and admire the freshly painted sign above the door. It's crooked, the paint is still wet, and the building behind it is a disaster — but a warmth fills your chest.</p> <p style="color: #ccc; font-size: 16px; line-height: 1.6; margin: 0 0 15px 0;">This is <em style="color: #2ecc71;">your</em> cafe. Your business. Your dream.</p> <p style="color: #aaa; font-size: 14px; line-height: 1.6; margin: 0 0 20px 0;">Of course, the place is still a wreck. You'll need to invest in renovations before you can open for business — furniture, a working kitchen, some actual decor. But that's a problem for tomorrow.</p> <div style="background: rgba(46,204,113,0.1); border: 1px solid #2ecc71; border-radius: 8px; padding: 12px; margin-bottom: 20px;"> <p style="color: #2ecc71; margin: 0; font-weight: bold;">🏠 You now own <<= $cafeOwnership.cafeName>>!</p> <p style="color: #aaa; margin: 5px 0 0 0; font-size: 13px;">Visit the Outskirts to see your new property. You'll need to buy upgrades before opening.</p> </div> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 40px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px;'>Begin Your Journey</div>">> <<goto "Outskirts">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$cafeOwnership || !$cafeOwnership.owned>> <<goto "ThePufferfish">> <</if>> <div style="background: linear-gradient(180deg, #0d1b2a 0%, #1b2838 50%, #0d1b2a 100%); min-height: 100vh; padding: 20px; color: #e0e0e0;"> <h1 style="text-align: center; color: #2ecc71; text-shadow: 0 0 10px rgba(46,204,113,0.3); margin-bottom: 5px;">🏠 <<= $cafeOwnership.cafeName>></h1> <p style="text-align: center; color: #aaa; font-style: italic; margin-top: 0; margin-bottom: 20px;">Management Dashboard</p> <!-- Financial Summary --> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin-bottom: 20px;"> <div style="background: #1a2a1a; border: 2px solid #2ecc71; border-radius: 10px; padding: 12px; text-align: center;"> <p style="color: #888; margin: 0; font-size: 11px;">Yesterday's Revenue</p> <p style="color: #2ecc71; margin: 5px 0 0; font-size: 20px; font-weight: bold;">$<<= $cafeOwnership.finances.yesterdayRevenue>></p> </div> <div style="background: #2a1a1a; border: 2px solid #e74c3c; border-radius: 10px; padding: 12px; text-align: center;"> <p style="color: #888; margin: 0; font-size: 11px;">Yesterday's Expenses</p> <p style="color: #e74c3c; margin: 5px 0 0; font-size: 20px; font-weight: bold;">$<<= $cafeOwnership.finances.yesterdayExpenses>></p> </div> <div style="background: #2a2a1a; border: 2px solid #ffd700; border-radius: 10px; padding: 12px; text-align: center;"> <p style="color: #888; margin: 0; font-size: 11px;">Yesterday's Profit</p> <p style="color: #ffd700; margin: 5px 0 0; font-size: 20px; font-weight: bold;">$<<= $cafeOwnership.finances.yesterdayProfit>></p> </div> <div style="background: #1a1a2a; border: 2px solid #3498db; border-radius: 10px; padding: 12px; text-align: center;"> <p style="color: #888; margin: 0; font-size: 11px;">Reputation</p> <p style="color: #3498db; margin: 5px 0 0; font-size: 20px; font-weight: bold;"><<= Math.floor($cafeOwnership.reputation)>>/100</p> </div> </div> <!-- Cafe Status --> <<if !setup.cafe.isOpen()>> <div style="background: rgba(231,76,60,0.1); border: 2px solid #e74c3c; border-radius: 10px; padding: 15px; margin-bottom: 20px; text-align: center;"> <p style="color: #e74c3c; font-weight: bold; margin: 0;">⚠ Cafe Not Yet Open</p> <p style="color: #aaa; margin: 5px 0 0; font-size: 13px;">You need at least Basic Decor, Basic Kitchen, and Basic Tables before opening.</p> </div> <</if>> <!-- Upgrade Status --> <h2 style="color: #2ecc71;">⬆ Upgrades</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 12px; margin-bottom: 20px;"> <<set _categories = ["decor", "kitchen", "furniture", "entertainment", "vipRoom", "staffRoom"]>> <<for _cat range _categories>> <<set _label = setup.cafe.upgradeLabels[_cat]>> <<set _currentTier = $cafeOwnership.upgrades[_cat]>> <<set _tiers = setup.cafe.upgrades[_cat]>> <<set _maxed = _currentTier >= _tiers.length>> <<set _currentName = _currentTier > 0 ? _tiers[_currentTier - 1].name : "None">> <<set _nextInfo = setup.cafe.getNextUpgrade(_cat)>> <div style="border: 2px solid <<= _label.color>>; border-radius: 10px; padding: 12px; background: #1a1a1a;"> <h4 style="color: <<= _label.color>>; margin: 0 0 5px;"><<= _label.emoji>> <<= _label.name>></h4> <p style="font-size: 12px; color: #aaa; margin: 0 0 3px;"><<= _label.desc>></p> <p style="font-size: 13px; color: #ccc; margin: 0 0 8px;">Current: <strong style="color: <<= _label.color>>;"><<= _currentName>></strong> (Tier <<= _currentTier>>/<<= _tiers.length>>)</p> <<if _cat === "entertainment" && _currentTier > 0>><p style="font-size: 12px; color: #9c27b0; margin: -4px 0 8px;">Active bonus: <strong>+<<= Math.round(_tiers[_currentTier - 1].tipBonus * 100)>>% performance tips</strong></p><</if>> <<if _maxed>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #888; padding: 10px; border-radius: 8px; text-align: center; font-size: 13px; border: 3px solid #555; box-shadow: 0 4px 8px rgba(0,0,0,0.4);">MAX LEVEL</div> <<elseif $money >= _nextInfo.next.cost>> <<capture _cat>> <<link "<div style='background: <<= _label.color>>; color: white; background: linear-gradient(135deg, #1a3a1a 0%, #0d1f0d 100%); padding: 10px; border-radius: 8px; text-align: center; font-size: 13px; cursor: pointer; font-weight: bold; border: 3px solid #2ecc71; box-shadow: 0 4px 8px rgba(0,0,0,0.4), 0 0 15px rgba(46,204,113,0.2);'>Upgrade: <<= _nextInfo.next.name>> — $<<= _nextInfo.next.cost>></div>">> <<run setup.cafe.purchaseUpgrade(_cat)>> <<goto "PufferfishManage">> <</link>> <</capture>> <<else>> <div style="background: linear-gradient(135deg, #222 0%, #181818 100%); color: #555; padding: 10px; border-radius: 8px; text-align: center; font-size: 13px; cursor: not-allowed; border: 3px solid #333; box-shadow: 0 2px 4px rgba(0,0,0,0.3);"><<= _nextInfo.next.name>> — $<<= _nextInfo.next.cost>> (can't afford)</div> <</if>> </div> <</for>> </div> <!-- Ingredients Section --> <h3 style="color: #ffd700; border-bottom: 1px solid #444; padding-bottom: 4px;">🥘 Ingredients</h3> <div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 4px; margin-bottom: 8px;"> <<for _ingKey, _ingDef range setup.cafe.ingredients>> <<set _ingCount = $cafeOwnership.inventory[_ingKey] || 0>> <<if _ingCount === 0>> <div style="background: #2a1a1a; border: 1px solid #e74c3c; border-radius: 4px; padding: 4px 6px; font-size: 11px; color: #e74c3c;"> <<= _ingDef.emoji>> <<= _ingDef.name>>: <strong><<= _ingCount>></strong> </div> <<elseif _ingCount < 20>> <div style="background: #2a2a1a; border: 1px solid #f39c12; border-radius: 4px; padding: 4px 6px; font-size: 11px; color: #f39c12;"> <<= _ingDef.emoji>> <<= _ingDef.name>>: <strong><<= _ingCount>></strong> </div> <<else>> <div style="background: #1a2a1a; border: 1px solid #2ecc71; border-radius: 4px; padding: 4px 6px; font-size: 11px; color: #2ecc71;"> <<= _ingDef.emoji>> <<= _ingDef.name>>: <strong><<= _ingCount>></strong> </div> <</if>> <</for>> </div> <div style="text-align: center; margin-bottom: 15px;"> <<link "<div style='background: #3498db; color: white; padding: 6px 16px; border-radius: 4px; cursor: pointer; display: inline-block; font-size: 12px;'>Shop at Supplier</div>">> <<goto "CafeSupplier">> <</link>> </div> <!-- Staff Section --> <h2 style="color: #2ecc71;">👥 Staff (<<= $cafeOwnership.staff.length>>)</h2> <div style="background: #1a1a1a; border: 2px solid #2ecc71; border-radius: 10px; padding: 15px; margin-bottom: 20px;"> <<if $cafeOwnership.staff.length === 0>> <p style="color: #888; text-align: center; margin: 0;">No staff hired yet. Find Mochi, Ren, or Clover in the city and build a relationship (25+ points) to recruit them!</p> <<else>> <<for _staff range $cafeOwnership.staff>> <div style="background: #0d0d0d; border: 1px solid #333; border-radius: 8px; padding: 12px; margin-bottom: 8px;"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> <div> <strong style="color: #2ecc71;"><<= _staff.name>></strong> <span style="color: #888; font-size: 12px;"> — <<= _staff.role>></span> </div> <span style="color: <<if _staff.happiness >= 70>>#2ecc71<<elseif _staff.happiness >= 40>>#f39c12<<else>>#e74c3c<</if>>; font-size: 12px;">❤ <<= Math.floor(_staff.happiness)>>% happy</span> </div> <div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;"> <span style="color: #ffd700; font-size: 14px; font-weight: bold;">$<<= _staff.salary>>/day</span> <span style="color: #666; font-size: 11px;">(min $<<= _staff.minSalary>>)</span> <<capture _staff>> <<link "<div style='background: #2ecc71; color: white; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>+$10</div>">> <<run setup.cafe.adjustSalary(_staff.name, 10)>> <<goto "PufferfishManage">> <</link>> <<link "<div style='background: #e74c3c; color: white; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>-$10</div>">> <<run setup.cafe.adjustSalary(_staff.name, -10)>> <<goto "PufferfishManage">> <</link>> <<link "<div style='background: #333; color: #e74c3c; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-size: 11px; border: 1px solid #e74c3c;'>Fire</div>">> <<run setup.cafe.fireStaff(_staff.name)>> <<goto "PufferfishManage">> <</link>> <</capture>> </div> <div style="display: flex; align-items: center; gap: 6px; margin-top: 6px;"> <span style="color: #888; font-size: 12px;">Shift: <strong style="color: #2ecc71;"><<= _staff.shift || "both">></strong></span> <<capture _staff>> <<link "<div style='background: #3498db; color: white; padding: 2px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;'>AM</div>">> <<run setup.cafe.setStaffShift(_staff.name, "morning")>> <<goto "PufferfishManage">> <</link>> <<link "<div style='background: #9b59b6; color: white; padding: 2px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;'>PM</div>">> <<run setup.cafe.setStaffShift(_staff.name, "day")>> <<goto "PufferfishManage">> <</link>> <<link "<div style='background: #2ecc71; color: white; padding: 2px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;'>All Day</div>">> <<run setup.cafe.setStaffShift(_staff.name, "both")>> <<goto "PufferfishManage">> <</link>> <<link "<div style='background: #e74c3c; color: white; padding: 2px 8px; border-radius: 3px; cursor: pointer; font-size: 11px;'>Off</div>">> <<run setup.cafe.setStaffShift(_staff.name, "off")>> <<goto "PufferfishManage">> <</link>> <</capture>> </div> <div style="margin-top: 10px; padding: 8px; background: #1a1a1a; border-radius: 6px;"> <div style="display: flex; align-items: center; gap: 6px; font-size: 11px; margin-bottom: 4px;"> <span style="color: #aaa; width: 55px;">Serving:</span> <div style="flex: 1; background: #222; height: 10px; border-radius: 3px; overflow: hidden;"> <div style="background: #3498db; height: 100%; width: <<= Math.round(((_staff.proficiencies.serving || 0) / (_staff.caps.serving || 100)) * 100)>>%;"></div> </div> <span style="color: #ddd; width: 60px; text-align: right;"><<= _staff.proficiencies.serving || 0>> / <<= _staff.caps.serving || 100>></span> </div> <div style="display: flex; align-items: center; gap: 6px; font-size: 11px; margin-bottom: 4px;"> <span style="color: #aaa; width: 55px;">Cooking:</span> <div style="flex: 1; background: #222; height: 10px; border-radius: 3px; overflow: hidden;"> <div style="background: #e67e22; height: 100%; width: <<= Math.round(((_staff.proficiencies.cooking || 0) / (_staff.caps.cooking || 100)) * 100)>>%;"></div> </div> <span style="color: #ddd; width: 60px; text-align: right;"><<= _staff.proficiencies.cooking || 0>> / <<= _staff.caps.cooking || 100>></span> </div> <div style="display: flex; align-items: center; gap: 6px; font-size: 11px;"> <span style="color: #aaa; width: 55px;">Charm:</span> <div style="flex: 1; background: #222; height: 10px; border-radius: 3px; overflow: hidden;"> <div style="background: #e91e63; height: 100%; width: <<= Math.round(((_staff.proficiencies.charm || 0) / (_staff.caps.charm || 100)) * 100)>>%;"></div> </div> <span style="color: #ddd; width: 60px; text-align: right;"><<= _staff.proficiencies.charm || 0>> / <<= _staff.caps.charm || 100>></span> </div> </div> <div style="display: flex; align-items: center; gap: 6px; margin-top: 6px; flex-wrap: wrap;"> <span style="color: #888; font-size: 12px;">Role:</span> <<capture _staff>> <<if _staff.role === "Maid">> <<link "<div style='background: #2ecc71; color: white; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px; font-weight: bold;'>Maid</div>">> <<run setup.cafe.setStaffRole(_staff.name, "Maid")>> <<goto "PufferfishManage">> <</link>> <<else>> <<link "<div style='background: #444; color: #ccc; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px;'>Maid</div>">> <<run setup.cafe.setStaffRole(_staff.name, "Maid")>> <<goto "PufferfishManage">> <</link>> <</if>> <<if _staff.role === "Chef">> <<link "<div style='background: #e67e22; color: white; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px; font-weight: bold;'>Chef</div>">> <<run setup.cafe.setStaffRole(_staff.name, "Chef")>> <<goto "PufferfishManage">> <</link>> <<else>> <<link "<div style='background: #444; color: #ccc; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px;'>Chef</div>">> <<run setup.cafe.setStaffRole(_staff.name, "Chef")>> <<goto "PufferfishManage">> <</link>> <</if>> <<link "<div style='background: #9b59b6; color: white; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px;'>Train</div>">> <<set $trainTarget = _staff.name>> <<goto "CafeTrain">> <</link>> <<if _staff.isHeadMaid>> <<if _staff.currentTask>> <span style="background: #3a2a4a; color: #b8a8d0; padding: 2px 10px; border-radius: 3px; font-size: 11px; font-style: italic;">Away - back at <<= setup.bunBunTasks._formatClock(_staff.currentTask.endMin)>></span> <<else>> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px; font-weight: bold;'>Talk</div>">> <<set _talkNpc = null>> <<for _bn = 0; _bn < $npcs.length; _bn++>> <<if $npcs[_bn].name === _staff.name || $npcs[_bn].originalName === _staff.name>> <<set _talkNpc = $npcs[_bn]>> <</if>> <</for>> <<if _talkNpc>> <<set $tradingWithNPC = _talkNpc>> <<set $preNPCLocation = "PufferfishManage">> <<goto "NPCInteraction">> <</if>> <</link>> <</if>> <</if>> <<if !_staff.traitTradingLocked>> <<link "<div style='background: #f39c12; color: white; padding: 2px 10px; border-radius: 3px; cursor: pointer; font-size: 11px;'>Gift Trait</div>">> <<set $giftTarget = _staff.name>> <<goto "CafeGiftTrait">> <</link>> <</if>> <</capture>> </div> </div> <</for>> <</if>> </div> <!-- Bun Bun Task Panels (in-place re-render via #bunbun-panels-root) --> <<if setup.bunBunTasks && setup.bunBunTasks.getStaffEntry()>> <div id="bunbun-panels-root"> <<include "BunBunCafePanels">> </div> <</if>> <!-- Maid Cafe Notes & Bonds (in-place re-render via #maid-bonds-root) --> <div id="maid-bonds-root"> <<include "MaidBondsPanel">> </div> <!-- Rename Cafe --> <div style="background: #1a1a1a; border: 2px solid #666; border-radius: 10px; padding: 15px; margin-bottom: 20px;"> <h4 style="color: #aaa; margin: 0 0 8px;">✏ Rename Cafe ($500)</h4> <div id="cafeRenameBox"> <input id="cafeRenameInput" type="text" value="" maxlength="30" style="background: #0d0d0d; border: 1px solid #444; border-radius: 4px; color: #e0e0e0; padding: 6px 10px; font-size: 14px; width: 60%; outline: none; margin-right: 8px;"> </div> <<run $(function() { $("#cafeRenameInput").val(State.variables.cafeOwnership.cafeName); })>> <div id="cafeRenameBtn" style="margin-top: 8px;"></div> <<run $(function() { var btn = $("<div>").css({ background: "#666", color: "white", padding: "6px 20px", borderRadius: "4px", textAlign: "center", cursor: "pointer", fontWeight: "bold", fontSize: "13px", display: "inline-block" }).text("Change Sign ($500)").on("click", function() { var v = State.variables; if (v.money < 500) { $(this).text("Not enough money!"); return; } var newName = $("#cafeRenameInput").val().trim(); if (newName.length === 0 || newName === v.cafeOwnership.cafeName) return; v.money -= 500; v.cafeOwnership.cafeName = newName; SugarCube.Engine.play("PufferfishManage"); }); $("#cafeRenameBtn").append(btn); })>> </div> <!-- Lifetime Stats --> <div style="background: #1a1a1a; border: 2px solid #444; border-radius: 10px; padding: 15px; margin-bottom: 20px;"> <h4 style="color: #888; margin: 0 0 8px;">📊 Lifetime Stats</h4> <p style="color: #aaa; margin: 2px 0; font-size: 13px;">Total Revenue: <span style="color: #2ecc71;">$<<= $cafeOwnership.finances.totalRevenue>></span></p> <p style="color: #aaa; margin: 2px 0; font-size: 13px;">Total Expenses: <span style="color: #e74c3c;">$<<= $cafeOwnership.finances.totalExpenses>></span></p> <p style="color: #aaa; margin: 2px 0; font-size: 13px;">Total Profit: <span style="color: #ffd700;">$<<= $cafeOwnership.finances.totalProfit>></span></p><<if $cafeOwnership.finances.yesterdayHeadMaidPresent && $cafeOwnership.finances.yesterdayHeadMaidBonus > 0>><p style="color: #c9a9ff; margin: 2px 0; font-size: 13px;">✨ <<= ($bunBunChosenName || "Bun Bun")>>'s leadership last shift: <span style="color: #ff8fc8;">+$<<= $cafeOwnership.finances.yesterdayHeadMaidBonus>></span></p><</if>> <p style="color: #aaa; margin: 2px 0; font-size: 13px;">Your Money: <span style="color: #ffd700;">$<<= $money>></span></p> </div> <!-- Back --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #2ecc71; color: white; padding: 10px 20px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Back to Cafe</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _npcName = $cafeRecruitTarget>> <<set _info = setup.cafe.recruitableNPCs[_npcName]>> <div style="background: linear-gradient(180deg, #0d1b2a 0%, #1b2838 50%, #0d1b2a 100%); min-height: 100vh; padding: 20px; color: #e0e0e0; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="background: linear-gradient(135deg, #1a2a1a 0%, #0d1a0d 100%); border: 3px solid #2ecc71; border-radius: 15px; padding: 30px; max-width: 550px; text-align: center;"> <h2 style="color: #2ecc71; margin: 0 0 15px;">🏠 Recruit <<= _npcName>>?</h2> <p style="color: #ccc; line-height: 1.6; margin: 0 0 15px;"><<= _info.desc>></p> <div style="background: #0d0d0d; border: 1px solid #444; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: left;"> <p style="color: #aaa; margin: 3px 0; font-size: 13px;">💼 Role: <strong style="color: #2ecc71;"><<= _info.role>></strong></p> <p style="color: #aaa; margin: 3px 0; font-size: 13px;">💰 Starting Salary: <strong style="color: #ffd700;">$<<= _info.minSalary>>/day</strong> (minimum)</p> <p style="color: #aaa; margin: 3px 0; font-size: 13px;">💡 You can adjust their salary later from the management dashboard.</p> </div> <<if _npcName === "Mochi">> <p style="color: #ffb6c1; font-style: italic; margin: 0 0 15px;">Mochi's ears perk up. 'Y-you want me to work at your cafe? Really?!' Her tail starts wagging. 'I'll do my best! I promise!'</p> <<elseif _npcName === "Ren">> <p style="color: #9b59b6; font-style: italic; margin: 0 0 15px;">Ren raises an eyebrow, then smirks. 'Running your own cafe? How ambitious.' She tucks a strand of purple hair behind her fox ear. 'Fine. I'll grace your establishment with my presence. But I expect to be appreciated.'</p> <<elseif _npcName === "Clover">> <p style="color: #2ecc71; font-style: italic; margin: 0 0 15px;">Clover's face lights up and she pulls you into a crushing hug. 'Oh sweetie, I'd LOVE to! I'll bake the best pastries and make everyone feel right at home!' She releases you, adjusting her straining top. 'When do I start?'</p> <</if>> <div style="display: flex; gap: 15px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #27ae60 100%); color: white; padding: 12px 30px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 16px;'>✅ Hire <<= _npcName>></div>">> <<run setup.cafe.hireNPC(_npcName)>> <<goto "CafeRecruitComplete">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 12px 30px; border-radius: 6px; cursor: pointer; font-weight: bold;'>Maybe Later</div>">> <<goto "NPCInteraction">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _npcName = $cafeRecruitTarget>> <div style="background: linear-gradient(180deg, #0d1b2a 0%, #1b2838 50%, #0d1b2a 100%); min-height: 100vh; padding: 20px; color: #e0e0e0; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="background: linear-gradient(135deg, #1a2a1a 0%, #0d1a0d 100%); border: 3px solid #2ecc71; border-radius: 15px; padding: 30px; max-width: 500px; text-align: center;"> <h2 style="color: #ffd700; margin: 0 0 15px;">🎉 New Staff Member!</h2> <p style="color: #ccc; font-size: 16px; line-height: 1.6; margin: 0 0 15px;"><<= _npcName>> has joined the staff of <strong style="color: #2ecc71;"><<= $cafeOwnership.cafeName>></strong>!</p> <div style="background: rgba(46,204,113,0.1); border: 1px solid #2ecc71; border-radius: 8px; padding: 12px; margin-bottom: 20px;"> <p style="color: #2ecc71; margin: 0; font-size: 14px;">You can manage their salary and view their stats from the Cafe Management Dashboard.</p> </div> <<link "<div style='background: #2ecc71; color: white; padding: 12px 30px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Continue</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> <</nobr>>
<<if ndef $supplierCart>><<set $supplierCart = {}>><</if>> <h2 style="color: #ffd700;">Cafe Supplier - Bulk Orders</h2> <p style="color: #aaa; font-style: italic;">Bulk prices are cheaper than retail. Minimum order: $500. Delivery arrives the next day.</p> <<set _cartTotal = 0>> <<for _ck, _cv range $supplierCart>> <<set _cartTotal += (setup.cafe.ingredients[_ck].bulk * _cv)>> <</for>> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 12px 0;"> <<for _key, _def range setup.cafe.ingredients>> <<capture _key, _def>> <<set _qty = $supplierCart[_key] || 0>> <div style="background: #1a1a1a; border: 1px solid #444; border-radius: 6px; padding: 8px;"> <div style="color: #ffd700; font-size: 12px; font-weight: bold;"><<= _def.emoji>> <<= _def.name>></div> <div style="color: #888; font-size: 10px;">$<<= _def.bulk>> / unit (retail $<<= _def.retail>>)</div> <div style="display: flex; align-items: center; gap: 4px; margin-top: 4px;"> <<link "<div style='background: #e74c3c; color: white; padding: 2px 8px; border-radius: 3px; font-size: 11px;'>-5</div>">> <<set $supplierCart[_key] = Math.max(0, (($supplierCart[_key] || 0) - 5))>> <<if $supplierCart[_key] === 0>><<run delete $supplierCart[_key]>><</if>> <<goto "CafeSupplier">> <</link>> <span style="color: #ddd; min-width: 30px; text-align: center; font-size: 12px;"><<= _qty>></span> <<link "<div style='background: #2ecc71; color: white; padding: 2px 8px; border-radius: 3px; font-size: 11px;'>+5</div>">> <<set $supplierCart[_key] = (($supplierCart[_key] || 0) + 5)>> <<goto "CafeSupplier">> <</link>> </div> <div style="display: flex; align-items: center; gap: 4px; margin-top: 4px;"> <input type="number" min="0" @id="'qty-input-' + _key" placeholder="qty" style="width: 70px; padding: 2px 4px; background: #2a2a2a; color: #ddd; border: 1px solid #555; border-radius: 3px; font-size: 11px;"> <<link "<div style='background: #3498db; color: white; padding: 2px 10px; border-radius: 3px; font-size: 11px;'>Set</div>">> <<set _val = parseInt(document.getElementById("qty-input-" + _key).value)>> <<if isNaN(_val) || _val < 0>><<set _val = 0>><</if>> <<set $supplierCart[_key] = _val>> <<if $supplierCart[_key] === 0>><<run delete $supplierCart[_key]>><</if>> <<goto "CafeSupplier">> <</link>> </div> </div> <</capture>> <</for>> </div> <div style="display: flex; gap: 8px; justify-content: center; margin: 8px 0;"> <<link "<div style='background: #3498db; color: white; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>+5 All Ingredients</div>">> <<run (function(){ var keys = Object.keys(setup.cafe.ingredients); for (var ai = 0; ai < keys.length; ai++) { State.variables.supplierCart[keys[ai]] = ((State.variables.supplierCart[keys[ai]] || 0) + 5); } })()>> <<goto "CafeSupplier">> <</link>> <<link "<div style='background: #e74c3c; color: white; padding: 6px 14px; border-radius: 4px; cursor: pointer; font-size: 12px; font-weight: bold;'>Clear Cart</div>">> <<set $supplierCart = {}>> <<goto "CafeSupplier">> <</link>> </div> <div style="background: #1a2a1a; border: 2px solid #ffd700; border-radius: 8px; padding: 12px; text-align: center; margin: 12px 0;"> <div style="color: #888; font-size: 11px;">Cart Total</div> <div style="color: #ffd700; font-size: 22px; font-weight: bold;">$<<= _cartTotal>></div> <<if _cartTotal >= 500 and $money >= _cartTotal>> <<link "<div style='background: #2ecc71; color: white; padding: 8px 20px; border-radius: 4px; display: inline-block; cursor: pointer; margin-top: 6px;'>Place Order</div>">> <<set $money -= _cartTotal>> <<if !$cafeOwnership.pendingSupplierOrders>><<set $cafeOwnership.pendingSupplierOrders = []>><</if>> <<run $cafeOwnership.pendingSupplierOrders.push({ items: clone($supplierCart), arrivalDay: $dayNumber + 1 })>> <<set $supplierCart = {}>> <<goto "PufferfishManage">> <</link>> <<elseif _cartTotal < 500>> <div style="color: #888; font-size: 11px;">Minimum $500 order required</div> <<else>> <div style="color: #e74c3c; font-size: 11px;">Insufficient funds</div> <</if>> </div> <<if $cafeOwnership.pendingSupplierOrders && $cafeOwnership.pendingSupplierOrders.length > 0>> <<for _po range $cafeOwnership.pendingSupplierOrders>> <div style="background: #1a1a2a; border: 1px solid #3498db; border-radius: 6px; padding: 8px; margin: 8px 0;"> <p style="color: #3498db; margin: 0;">Pending order arrives day <<= _po.arrivalDay>></p> </div> <</for>> <</if>> <<link "<div style='background: #444; color: white; padding: 6px 14px; border-radius: 4px; display: inline-block;'>Back to Dashboard</div>">> <<goto "PufferfishManage">> <</link>>
<<nobr>> <<set $lastLocation = "GroceryStoreCafeSupplies">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h2 style="color: #ffd700; text-align: center;">🫕 Cafe Supplies — Retail</h2> <p style="color: #aaa; font-style: italic; text-align: center;">Retail prices. Small quantities. For bulk discounts, visit the Supplier from your cafe dashboard.</p> <div style="background: #2a2a2a; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center;"> <p style="color: #ffd700; font-size: 20px; margin: 0;">💵 Your Balance: $<<print $money>></p> </div> <<if $cafeOwnership and $cafeOwnership.owned>> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 12px 0;"> <<for _gKey, _gDef range setup.cafe.ingredients>> <<set _gStock = $cafeOwnership.inventory[_gKey] || 0>> <<set _gCost = setup.drifterDiscount(_gDef.retail * 5)>> <<capture _gKey, _gDef, _gCost>> <div style="background: #1a1a1a; border: 1px solid #444; border-radius: 6px; padding: 8px;"> <div style="color: #ffd700; font-size: 12px; font-weight: bold;"><<= _gDef.emoji>> <<= _gDef.name>></div> <div style="color: #888; font-size: 10px;">Stock: <<= _gStock>> | $<<= _gDef.retail>>/unit</div> <<if $money gte _gCost>> <<link "<div style='background: #2ecc71; color: white; padding: 4px 10px; border-radius: 3px; font-size: 11px; margin-top: 4px; display: inline-block;'>Buy 5 — $<<= _gCost>></div>">> <<set $money -= _gCost>> <<run setup.cafe.addIngredient(_gKey, 5)>> <<goto "GroceryStoreCafeSupplies">> <</link>> <<else>> <div style="color: #e74c3c; font-size: 11px; margin-top: 4px;">Need $<<= _gCost>></div> <</if>> </div> <</capture>> <</for>> </div> <<else>> <p style="color: #e74c3c; text-align: center;">You don't own a cafe.</p> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #444; color: white; padding: 6px 14px; border-radius: 4px; display: inline-block;'>← Back to Grocery Store</div>">> <<goto "GroceryStore">> <</link>> </div> </div> <</nobr>>
<<if ndef $trainTarget>> <p style="color: #e74c3c;">No training target selected.</p> <<link "<div style='background: #444; color: white; padding: 6px 14px; border-radius: 4px; display: inline-block;'>Back</div>">> <<goto "PufferfishManage">> <</link>> <<else>> <<set _trainStaff = null>> <<for _ti = 0; _ti < $cafeOwnership.staff.length; _ti++>> <<if $cafeOwnership.staff[_ti].name === $trainTarget>> <<set _trainStaff = $cafeOwnership.staff[_ti]>> <</if>> <</for>> <<if _trainStaff === null>> <p style="color: #e74c3c;">Staff not found.</p> <<else>> <h2 style="color: #ffd700;">Train <<= $trainTarget>></h2> <p style="color: #aaa; font-style: italic;">Each training session advances time 2 hours and grants +5 x affinity to the chosen skill. One session per staff per day.</p> <<if _trainStaff.lastTrainedDay === $dayNumber>> <p style="color: #e67e22;">Already trained today. Come back tomorrow.</p> <<else>> <div style="display: grid; grid-template-columns: 1fr; gap: 8px; margin: 12px 0;"><<set _cur = _trainStaff.proficiencies.serving || 0>><<set _cap = _trainStaff.caps.serving || 100>><<set _cost = 200 + Math.floor(_cur * 3)>><<set _aff = _trainStaff.affinities.serving || 1.0>><<set _gain = Math.round(5 * _aff)>><div style="background: #1a1a1a; border: 1px solid #444; border-radius: 6px; padding: 10px;"><div style="color: #3498db; font-weight: bold;">Serving - <<= _cur>> / <<= _cap>></div><div style="color: #888; font-size: 11px;">Affinity: <<= _aff>>x | Gain: +<<= _gain>> | Cost: $<<= _cost>></div><<if _cur >= _cap>><div style="color: #888; font-size: 11px; margin-top: 4px;">Maxed out</div><<elseif $money < _cost>><div style="color: #e74c3c; font-size: 11px; margin-top: 4px;">Need $<<= _cost>></div><<else>><<link "<div style='background: #3498db; color: white; padding: 4px 12px; border-radius: 3px; font-size: 12px; margin-top: 4px; display: inline-block; cursor: pointer;'>Train Serving</div>">><<set _result = setup.cafe.trainStaff($trainTarget, "serving")>><<if _result.success>><<run window.advanceTime(120)>><<set $trainResult = "Trained serving +" + _result.gain + " (now " + _result.newValue + ")">><<else>><<set $trainResult = _result.reason>><</if>><<goto "CafeTrain">><</link>><</if>></div><<set _cur = _trainStaff.proficiencies.cooking || 0>><<set _cap = _trainStaff.caps.cooking || 100>><<set _cost = 200 + Math.floor(_cur * 3)>><<set _aff = _trainStaff.affinities.cooking || 1.0>><<set _gain = Math.round(5 * _aff)>><div style="background: #1a1a1a; border: 1px solid #444; border-radius: 6px; padding: 10px;"><div style="color: #e67e22; font-weight: bold;">Cooking - <<= _cur>> / <<= _cap>></div><div style="color: #888; font-size: 11px;">Affinity: <<= _aff>>x | Gain: +<<= _gain>> | Cost: $<<= _cost>></div><<if _cur >= _cap>><div style="color: #888; font-size: 11px; margin-top: 4px;">Maxed out</div><<elseif $money < _cost>><div style="color: #e74c3c; font-size: 11px; margin-top: 4px;">Need $<<= _cost>></div><<else>><<link "<div style='background: #e67e22; color: white; padding: 4px 12px; border-radius: 3px; font-size: 12px; margin-top: 4px; display: inline-block; cursor: pointer;'>Train Cooking</div>">><<set _result = setup.cafe.trainStaff($trainTarget, "cooking")>><<if _result.success>><<run window.advanceTime(120)>><<set $trainResult = "Trained cooking +" + _result.gain + " (now " + _result.newValue + ")">><<else>><<set $trainResult = _result.reason>><</if>><<goto "CafeTrain">><</link>><</if>></div><<set _cur = _trainStaff.proficiencies.charm || 0>><<set _cap = _trainStaff.caps.charm || 100>><<set _cost = 200 + Math.floor(_cur * 3)>><<set _aff = _trainStaff.affinities.charm || 1.0>><<set _gain = Math.round(5 * _aff)>><div style="background: #1a1a1a; border: 1px solid #444; border-radius: 6px; padding: 10px;"><div style="color: #e91e63; font-weight: bold;">Charm - <<= _cur>> / <<= _cap>></div><div style="color: #888; font-size: 11px;">Affinity: <<= _aff>>x | Gain: +<<= _gain>> | Cost: $<<= _cost>></div><<if _cur >= _cap>><div style="color: #888; font-size: 11px; margin-top: 4px;">Maxed out</div><<elseif $money < _cost>><div style="color: #e74c3c; font-size: 11px; margin-top: 4px;">Need $<<= _cost>></div><<else>><<link "<div style='background: #e91e63; color: white; padding: 4px 12px; border-radius: 3px; font-size: 12px; margin-top: 4px; display: inline-block; cursor: pointer;'>Train Charm</div>">><<set _result = setup.cafe.trainStaff($trainTarget, "charm")>><<if _result.success>><<run window.advanceTime(120)>><<set $trainResult = "Trained charm +" + _result.gain + " (now " + _result.newValue + ")">><<else>><<set $trainResult = _result.reason>><</if>><<goto "CafeTrain">><</link>><</if>></div></div> <</if>> <<if $trainResult>> <div style="background: #1a2a1a; border: 1px solid #2ecc71; border-radius: 4px; padding: 8px; margin: 8px 0; color: #2ecc71;"><<= $trainResult>></div> <<run delete $trainResult>> <</if>> <</if>> <<link "<div style='background: #444; color: white; padding: 6px 14px; border-radius: 4px; display: inline-block;'>Back to Dashboard</div>">> <<goto "PufferfishManage">> <</link>> <</if>>
<<if ndef $giftTarget>> <p style="color: #e74c3c;">No gift target selected.</p> <<link "<div style='background: #444; color: white; padding: 6px 14px; border-radius: 4px; display: inline-block;'>Back</div>">> <<goto "PufferfishManage">> <</link>> <<else>> <<set _giftStaff = null>> <<for _gi = 0; _gi < $cafeOwnership.staff.length; _gi++>> <<if $cafeOwnership.staff[_gi].name === $giftTarget>> <<set _giftStaff = $cafeOwnership.staff[_gi]>> <</if>> <</for>> <<if _giftStaff === null>> <p style="color: #e74c3c;">Staff not found.</p> <<else>> <h2 style="color: #ffd700;">Gift Trait to <<= $giftTarget>></h2> <p style="color: #aaa; font-style: italic;">Permanently transfer one of your traits to this staff member. They gain proficiency bonuses; you lose the trait.</p> <h3 style="color: #e91e63;">Mental Traits</h3> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; margin-bottom: 12px;"> <<for _mi = 0; _mi < $mentalTraits.length; _mi++>> <<set _mTrait = $mentalTraits[_mi]>> <<capture _mi, _mTrait>> <<if setup.cafe.canGiftTrait(_mTrait) and _giftStaff.traitsGifted.indexOf(_mTrait) === -1>> <div style="background: #1a1a1a; border: 1px solid #444; border-radius: 4px; padding: 6px;"> <div style="color: #ddd; font-size: 12px; font-weight: bold;"><<= _mTrait>></div> <<if setup.cafe.traitGiftBonuses[_mTrait]>> <div style="color: #888; font-size: 10px;"><<= setup.cafe.formatTraitBonusString(_mTrait)>></div> <<else>> <div style="color: #888; font-size: 10px;">No bonus</div> <</if>> <<link "<div style='background: #e91e63; color: white; padding: 2px 10px; border-radius: 3px; font-size: 11px; margin-top: 4px; display: inline-block; cursor: pointer;'>Gift</div>">> <<set _giftResult = setup.cafe.giftTraitToStaff($giftTarget, _mTrait, "mental")>> <<if _giftResult.success>> <<set $giftMessage = "Gifted " + _mTrait + " to " + $giftTarget>> <<else>> <<set $giftMessage = _giftResult.reason>> <</if>> <<goto "CafeGiftTrait">> <</link>> </div> <</if>> <</capture>> <</for>> </div> <h3 style="color: #3498db;">Physical Traits</h3> <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; margin-bottom: 12px;"> <<for _pi = 0; _pi < $physicalTraits.length; _pi++>> <<set _pTrait = $physicalTraits[_pi]>> <<capture _pi, _pTrait>> <<if setup.cafe.canGiftTrait(_pTrait) and _giftStaff.traitsGifted.indexOf(_pTrait) === -1>> <div style="background: #1a1a1a; border: 1px solid #444; border-radius: 4px; padding: 6px;"> <div style="color: #ddd; font-size: 12px; font-weight: bold;"><<= _pTrait>></div> <<if setup.cafe.traitGiftBonuses[_pTrait]>> <div style="color: #888; font-size: 10px;"><<= setup.cafe.formatTraitBonusString(_pTrait)>></div> <<else>> <div style="color: #888; font-size: 10px;">No bonus</div> <</if>> <<link "<div style='background: #3498db; color: white; padding: 2px 10px; border-radius: 3px; font-size: 11px; margin-top: 4px; display: inline-block; cursor: pointer;'>Gift</div>">> <<set _giftResult = setup.cafe.giftTraitToStaff($giftTarget, _pTrait, "physical")>> <<if _giftResult.success>> <<set $giftMessage = "Gifted " + _pTrait + " to " + $giftTarget>> <<else>> <<set $giftMessage = _giftResult.reason>> <</if>> <<goto "CafeGiftTrait">> <</link>> </div> <</if>> <</capture>> <</for>> </div> <<if $giftMessage>> <div style="background: #1a2a1a; border: 1px solid #2ecc71; border-radius: 4px; padding: 8px; margin: 8px 0; color: #2ecc71;"><<= $giftMessage>></div> <<run delete $giftMessage>> <</if>> <</if>> <<link "<div style='background: #444; color: white; padding: 6px 14px; border-radius: 4px; display: inline-block;'>Back to Dashboard</div>">> <<goto "PufferfishManage">> <</link>> <</if>>
<<nobr>> <<set $lastLocation = "Outskirts">> <div style="background: #0f0a1a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #c9a9ff; text-align: center; text-shadow: 0 0 10px rgba(201,169,255,0.4);">🚪 Hidden Door</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a1528 0%, #0f0a1a 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #c9a9ff; box-shadow: 0 0 20px rgba(201,169,255,0.2);"> <p style="color: #e0d4ff; font-size: 16px; line-height: 1.7;"> The alley behind <<= $cafeOwnership.cafeName>> is narrow enough that your shoulder brushes damp brick on both sides. At the very back, half-hidden behind an old delivery crate, stands a door that shouldn't be there. The wood is dark and polished in a way nothing else in this alley is, and set into it at hip-height is a small keyhole cut in the exact shape of a heart. </p> <p style="color: #b8a8d0; font-size: 15px; line-height: 1.6; margin-top: 12px; font-style: italic;"> There is no handle. Only the keyhole. </p> </div> <<if $skills && $skills.includes("Maid")>> <div style="padding: 20px; background: #1a2a1a; border: 2px solid #2ecc71; border-radius: 12px; margin: 20px auto; max-width: 700px;"> <p style="color: #a8e6b8; font-size: 15px; line-height: 1.6; margin: 0;"> As you step closer, the heart-shaped keyhole gives off a faint warm glow. Something in you, some practiced softness you've earned a hundred small shifts at a time, is being recognized. The door clicks, just once, and swings inward a few inches on its own. </p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #8b6fc9 100%); color: white; padding: 14px 28px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 12px rgba(201,169,255,0.5);'>Push the door open</div>">> <<advancetime 2>> <<goto "SecretCafeInterior">> <</link>> </div> <<else>> <div style="padding: 20px; background: #2a1a1a; border: 2px solid #8b4a4a; border-radius: 12px; margin: 20px auto; max-width: 700px;"> <p style="color: #e6a8a8; font-size: 15px; line-height: 1.6; margin: 0;"> You press against the wood, try to get your fingernails into the seam, push, pull. Nothing. The door doesn't budge a millimetre. It's almost as if the door itself is sizing you up and finding you lacking. Whatever opens this thing, it isn't force. It's something only a true maid would carry. </p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #444; color: white; padding: 10px 22px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Leave</div>">> <<advancetime 2>> <<goto "Outskirts">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "Outskirts">> <div style="background: #0f0a1a; min-height: 100vh; padding: 40px 20px;"> <h1 style="color: #c9a9ff; text-align: center; text-shadow: 0 0 10px rgba(201,169,255,0.4);">🕯️ Behind the Door</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a1528 0%, #0f0a1a 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #c9a9ff; box-shadow: 0 0 25px rgba(201,169,255,0.25);"> <p style="color: #e0d4ff; font-size: 16px; line-height: 1.7;"> You slip through into a dimly lit corridor that smells faintly of jasmine and old paper. Candles in wall sconces burn with a soft violet flame, and the walls are hung with tapestries too shadowed to make out. Something moves at the far end of the corridor. A silhouette, maybe, or just a trick of the flickering light. Whatever it is, it isn't ready to be seen yet. </p> <p style="color: #b8a8d0; font-size: 14px; line-height: 1.6; margin-top: 14px;"> Whatever this place is, it has clearly been waiting for you. </p> </div> <<if $cafeSecretSolved>> <div style="padding: 25px; background: linear-gradient(135deg, #1a1528 0%, #0f0a1a 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #ffd700; box-shadow: 0 0 30px rgba(255,215,0,0.35); text-align: center;"> <p style="color: #ffd700; font-size: 18px; line-height: 1.6; margin: 0 0 18px 0; font-weight: bold;">The mechanism has already accepted your three numbers. The door at the end of the corridor stands open, soft light spilling out from beyond.</p> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6a4a9a 100%); color: white; padding: 14px 32px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 18px rgba(201,169,255,0.5);'>Step through the door</div>">> <<goto "SecretCafeInnerRoom">> <</link>> </div> <<else>> <<if typeof $cafeSecretProgress === "undefined">><<set $cafeSecretProgress = 0>><</if>> <div style="padding: 25px; background: linear-gradient(135deg, #1a1528 0%, #0f0a1a 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px dashed #c9a9ff; box-shadow: 0 0 18px rgba(201,169,255,0.15);"> <h3 style="color: #c9a9ff; margin: 0 0 14px 0; text-align: center; letter-spacing: 2px; text-transform: uppercase; font-size: 14px;">The Tapestry's Riddle</h3> <p style="color: #d4c4f0; font-size: 15px; line-height: 1.7; font-style: italic; margin: 0 0 12px 0;">Three numbers were written in three places, and none of the writers wished to be remembered. Speak them in the order the riddle gives them, or do not speak them at all.</p> <p style="color: #d4c4f0; font-size: 15px; line-height: 1.7; font-style: italic; margin: 0 0 12px 0;">The first was pressed into a shaking hand by one whose mind had grown too crowded with watching things. It was paid for with something the giver could no longer afford to keep.</p> <p style="color: #d4c4f0; font-size: 15px; line-height: 1.7; font-style: italic; margin: 0 0 12px 0;">The second was scratched into stone where wood had been laid to disguise it. Only those who hear the dust settle can find the place where the floor lies about itself.</p> <p style="color: #d4c4f0; font-size: 15px; line-height: 1.7; font-style: italic; margin: 0;">The third was cut into a pale spire that the mountain is patient with. It rises briefly when the molten breath stills, then sinks again as if ashamed.</p> </div> <style> @keyframes cafeGearSpin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @keyframes cafeSteamPuff { 0% { opacity: 0.8; transform: translateY(0) scale(1); } 100% { opacity: 0; transform: translateY(-40px) scale(1.5); } } @keyframes cafePulse { 0%, 100% { box-shadow: 0 0 5px rgba(201,169,255,0.3); } 50% { box-shadow: 0 0 15px rgba(201,169,255,0.6); } } .cafe-gear-container { display: flex; justify-content: center; gap: 20px; margin: 20px 0; flex-wrap: wrap; } .cafe-gear-dial { width: 110px; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 8px 4px; position: relative; user-select: none; -webkit-user-select: none; touch-action: none; } .cafe-gear-dial-label { color: #c9a9ff; font-size: 11px; font-weight: bold; text-transform: uppercase; letter-spacing: 2px; text-shadow: 0 0 5px rgba(201,169,255,0.5); } .cafe-gear-circle { position: relative; width: 96px; height: 96px; border-radius: 50%; background: radial-gradient(circle at 30% 30%, #3a2a4a 0%, #1a1028 60%, #0d0518 100%); border: 3px solid #c9a9ff; box-shadow: 0 4px 10px rgba(0,0,0,0.6), inset 0 2px 4px rgba(201,169,255,0.25), 0 0 12px rgba(201,169,255,0.35); animation: cafePulse 3s ease-in-out infinite; overflow: hidden; } .cafe-gear-pointer { position: absolute; top: -4px; left: 50%; transform: translateX(-50%); width: 0; height: 0; border-left: 7px solid transparent; border-right: 7px solid transparent; border-top: 12px solid #c9a9ff; filter: drop-shadow(0 0 4px rgba(201,169,255,0.9)); z-index: 3; pointer-events: none; } .cafe-gear-disc { position: absolute; top: 0; left: 0; width: 100%; height: 100%; transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1); } .cafe-gear-numlabel { position: absolute; top: 50%; left: 50%; width: 22px; height: 22px; margin: -11px 0 0 -11px; line-height: 22px; text-align: center; font-family: "Courier New", monospace; font-size: 14px; font-weight: bold; color: #d4c4f0; text-shadow: 0 0 4px rgba(201,169,255,0.6); transform: rotate(calc(var(--n) * 36deg)) translateY(-30px) rotate(calc(var(--n) * -36deg)) rotate(calc(var(--disc-rot, 0deg) * -1)); } .cafe-gear-numlabel.is-current { color: #ffffff; font-size: 18px; text-shadow: 0 0 8px rgba(255,143,200,0.9), 0 0 16px rgba(255,143,200,0.5); } .cafe-gear-number { display: none; } .cafe-gear-btn { width: 36px; height: 26px; border: 2px solid #c9a9ff; background: linear-gradient(180deg, #3a2a4a 0%, #1a1028 100%); color: #c9a9ff; font-size: 16px; font-weight: bold; border-radius: 6px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s; touch-action: manipulation; -webkit-tap-highlight-color: transparent; } .cafe-gear-btn:hover, .cafe-gear-btn:active { background: linear-gradient(180deg, #4a3a5a 0%, #2a1a3a 100%); border-color: #ffffff; color: #ffffff; box-shadow: 0 0 10px rgba(201,169,255,0.4); } .cafe-steam-puff { position: absolute; top: -10px; font-size: 16px; opacity: 0; animation: cafeSteamPuff 2s ease-out forwards; pointer-events: none; } .cafe-submit-btn { background: linear-gradient(180deg, #6a4a9a 0%, #4a2a7a 100%); border: 3px solid #c9a9ff; color: #ffffff; padding: 15px 40px; border-radius: 10px; font-size: 18px; font-weight: bold; cursor: pointer; display: inline-block; box-shadow: 0 4px 8px rgba(0,0,0,0.6), 0 0 20px rgba(201,169,255,0.3); transition: all 0.2s; text-shadow: 0 0 8px rgba(201,169,255,0.6); touch-action: manipulation; -webkit-tap-highlight-color: transparent; } .cafe-submit-btn:hover { background: linear-gradient(180deg, #7a5aaa 0%, #5a3a8a 100%); border-color: #ffffff; box-shadow: 0 4px 8px rgba(0,0,0,0.6), 0 0 30px rgba(255,255,255,0.4); } </style> <div style="padding: 25px; background: linear-gradient(135deg, #1a1528 0%, #0f0a1a 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #c9a9ff; box-shadow: 0 0 25px rgba(201,169,255,0.25); text-align: center;"> <h3 style="color: #c9a9ff; margin: 0 0 5px 0;">The Three Locks</h3> <p style="color: #888; font-size: 13px; margin: 0 0 12px 0; font-style: italic;">Turn each gear to set a digit. Click the arrows or swipe up/down.</p> <div id="cafeLockProgress" style="margin-bottom: 15px;"> <div style="display: flex; justify-content: center; gap: 8px; margin-bottom: 8px;"> <<for _lk = 0; _lk < 3; _lk++>> <<if _lk < $cafeSecretProgress>> <div style="width: 28px; height: 28px; border-radius: 50%; background: #c9a9ff; border: 2px solid #ffffff; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #1a1028; font-weight: bold; box-shadow: 0 0 10px rgba(201,169,255,0.5);"><<print _lk + 1>></div> <<elseif _lk === $cafeSecretProgress>> <div style="width: 28px; height: 28px; border-radius: 50%; background: #c9a9ff; border: 2px solid #ffffff; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #1a1028; font-weight: bold; box-shadow: 0 0 10px rgba(201,169,255,0.5);"><<print _lk + 1>></div> <<else>> <div style="width: 28px; height: 28px; border-radius: 50%; background: #1a1028; border: 2px solid #555; display: flex; align-items: center; justify-content: center; font-size: 14px; color: #555; font-weight: bold;"><<print _lk + 1>></div> <</if>> <</for>> </div> <p style="color: #c9a9ff; font-size: 14px; margin: 0; font-weight: bold;">Lock <<print $cafeSecretProgress + 1>> of 3</p> </div> <div id="cafeGearPuzzle" class="cafe-gear-container"> <div class="cafe-gear-dial" data-gear="0"> <div class="cafe-gear-dial-label">I</div> <div class="cafe-gear-btn" data-dir="up">▲</div> <div class="cafe-gear-circle"> <div class="cafe-gear-pointer"></div> <div class="cafe-gear-disc"> <span class="cafe-gear-numlabel is-current" style="--n:0">0</span> <span class="cafe-gear-numlabel" style="--n:1">1</span> <span class="cafe-gear-numlabel" style="--n:2">2</span> <span class="cafe-gear-numlabel" style="--n:3">3</span> <span class="cafe-gear-numlabel" style="--n:4">4</span> <span class="cafe-gear-numlabel" style="--n:5">5</span> <span class="cafe-gear-numlabel" style="--n:6">6</span> <span class="cafe-gear-numlabel" style="--n:7">7</span> <span class="cafe-gear-numlabel" style="--n:8">8</span> <span class="cafe-gear-numlabel" style="--n:9">9</span> </div> <div class="cafe-gear-number" data-digit="0">0</div> </div> <div class="cafe-gear-btn" data-dir="down">▼</div> </div> <div class="cafe-gear-dial" data-gear="1"> <div class="cafe-gear-dial-label">II</div> <div class="cafe-gear-btn" data-dir="up">▲</div> <div class="cafe-gear-circle"> <div class="cafe-gear-pointer"></div> <div class="cafe-gear-disc"> <span class="cafe-gear-numlabel is-current" style="--n:0">0</span> <span class="cafe-gear-numlabel" style="--n:1">1</span> <span class="cafe-gear-numlabel" style="--n:2">2</span> <span class="cafe-gear-numlabel" style="--n:3">3</span> <span class="cafe-gear-numlabel" style="--n:4">4</span> <span class="cafe-gear-numlabel" style="--n:5">5</span> <span class="cafe-gear-numlabel" style="--n:6">6</span> <span class="cafe-gear-numlabel" style="--n:7">7</span> <span class="cafe-gear-numlabel" style="--n:8">8</span> <span class="cafe-gear-numlabel" style="--n:9">9</span> </div> <div class="cafe-gear-number" data-digit="0">0</div> </div> <div class="cafe-gear-btn" data-dir="down">▼</div> </div> <div class="cafe-gear-dial" data-gear="2"> <div class="cafe-gear-dial-label">III</div> <div class="cafe-gear-btn" data-dir="up">▲</div> <div class="cafe-gear-circle"> <div class="cafe-gear-pointer"></div> <div class="cafe-gear-disc"> <span class="cafe-gear-numlabel is-current" style="--n:0">0</span> <span class="cafe-gear-numlabel" style="--n:1">1</span> <span class="cafe-gear-numlabel" style="--n:2">2</span> <span class="cafe-gear-numlabel" style="--n:3">3</span> <span class="cafe-gear-numlabel" style="--n:4">4</span> <span class="cafe-gear-numlabel" style="--n:5">5</span> <span class="cafe-gear-numlabel" style="--n:6">6</span> <span class="cafe-gear-numlabel" style="--n:7">7</span> <span class="cafe-gear-numlabel" style="--n:8">8</span> <span class="cafe-gear-numlabel" style="--n:9">9</span> </div> <div class="cafe-gear-number" data-digit="0">0</div> </div> <div class="cafe-gear-btn" data-dir="down">▼</div> </div> <div class="cafe-gear-dial" data-gear="3"> <div class="cafe-gear-dial-label">IV</div> <div class="cafe-gear-btn" data-dir="up">▲</div> <div class="cafe-gear-circle"> <div class="cafe-gear-pointer"></div> <div class="cafe-gear-disc"> <span class="cafe-gear-numlabel is-current" style="--n:0">0</span> <span class="cafe-gear-numlabel" style="--n:1">1</span> <span class="cafe-gear-numlabel" style="--n:2">2</span> <span class="cafe-gear-numlabel" style="--n:3">3</span> <span class="cafe-gear-numlabel" style="--n:4">4</span> <span class="cafe-gear-numlabel" style="--n:5">5</span> <span class="cafe-gear-numlabel" style="--n:6">6</span> <span class="cafe-gear-numlabel" style="--n:7">7</span> <span class="cafe-gear-numlabel" style="--n:8">8</span> <span class="cafe-gear-numlabel" style="--n:9">9</span> </div> <div class="cafe-gear-number" data-digit="0">0</div> </div> <div class="cafe-gear-btn" data-dir="down">▼</div> </div> </div> <div id="cafeGearResult" style="margin-top: 15px; min-height: 30px;"></div> <div style="margin-top: 15px;"> <span id="cafeGearSubmitBtn" class="cafe-submit-btn">Engage the Lock</span> </div> </div> <script> (function() { var V = SugarCube.State.variables; function pad4(s) { s = String(s == null ? "" : s); while (s.length < 4) s = "0" + s; return s; } var TARGETS_STR = [ pad4(V.xanitharCode), pad4(V.manorSecretCode), (V.volcanoRedHerring && V.volcanoRedHerring.length === 4) ? V.volcanoRedHerring.map(function(d){return String(d);}).join("") : "" ]; var TARGETS = []; for (var t = 0; t < TARGETS_STR.length; t++) { var s = pad4(TARGETS_STR[t]); TARGETS.push([Number(s.charAt(0)), Number(s.charAt(1)), Number(s.charAt(2)), Number(s.charAt(3))]); } var progress = Number(V.cafeSecretProgress) || 0; var currentCode = TARGETS[progress] || [0,0,0,0]; var digits = [0, 0, 0, 0]; var discRotations = [0, 0, 0, 0]; /* cumulative degrees so 9->0 spins +36 not -324 */ var container = document.getElementById("cafeGearPuzzle"); if (!container) return; function updateDisplay(index) { var dials = container.querySelectorAll(".cafe-gear-dial"); var numEl = dials[index].querySelector(".cafe-gear-number"); if (numEl) { numEl.textContent = digits[index]; numEl.setAttribute("data-digit", digits[index]); } var disc = dials[index].querySelector(".cafe-gear-disc"); if (disc) { var deg = discRotations[index]; disc.style.transform = "rotate(" + deg + "deg)"; disc.style.setProperty("--disc-rot", deg + "deg"); } var labels = dials[index].querySelectorAll(".cafe-gear-numlabel"); for (var li = 0; li < labels.length; li++) { if (li === digits[index]) labels[li].classList.add("is-current"); else labels[li].classList.remove("is-current"); } } var _dialLastChange = {}; function changeDigit(index, direction) { /* Per-dial 250ms debounce to prevent click+touchend double-fire */ var _now = Date.now(); if ((_now - (_dialLastChange[index] || 0)) < 250) return; _dialLastChange[index] = _now; if (direction === "up") { digits[index] = (digits[index] + 1) % 10; discRotations[index] -= 36; /* always step in same direction; never wrap backwards */ } else { digits[index] = (digits[index] + 9) % 10; discRotations[index] += 36; /* opposite step */ } updateDisplay(index); } container.addEventListener("click", function(e) { var btn = e.target.closest(".cafe-gear-btn"); if (!btn) return; var dial = btn.closest(".cafe-gear-dial"); var index = parseInt(dial.getAttribute("data-gear")); var dir = btn.getAttribute("data-dir"); changeDigit(index, dir); }); var touchStartY = {}; container.addEventListener("touchstart", function(e) { var dial = e.target.closest(".cafe-gear-dial"); if (!dial) return; var touch = e.touches[0]; var index = dial.getAttribute("data-gear"); touchStartY[index] = touch.clientY; }, {passive: true}); container.addEventListener("touchend", function(e) { var dial = e.target.closest(".cafe-gear-dial"); if (!dial) return; var touch = e.changedTouches[0]; var index = dial.getAttribute("data-gear"); if (touchStartY[index] !== undefined) { var diff = touchStartY[index] - touch.clientY; if (Math.abs(diff) > 20) { changeDigit(parseInt(index), diff > 0 ? "up" : "down"); } delete touchStartY[index]; } }, {passive: true}); container.addEventListener("wheel", function(e) { var dial = e.target.closest(".cafe-gear-dial"); if (!dial) return; e.preventDefault(); var index = parseInt(dial.getAttribute("data-gear")); changeDigit(index, e.deltaY < 0 ? "up" : "down"); }, {passive: false}); var submitBtn = document.getElementById("cafeGearSubmitBtn"); var resultDiv = document.getElementById("cafeGearResult"); var submitting = false; if (submitBtn) { function handleSubmit() { if (submitting) return; submitting = true; var correct = true; for (var i = 0; i < 4; i++) { if (digits[i] !== currentCode[i]) { correct = false; break; } } if (correct) { progress++; V.cafeSecretProgress = progress; if (progress >= 3) { resultDiv.innerHTML = '<p style="color: #ff8fc8; font-size: 20px; font-weight: bold; text-shadow: 0 0 15px rgba(255,143,200,0.8);">All three numbers settle into place. The mechanism behind the wall sighs, and somewhere ahead, a heavy bolt slides home...</p>'; submitBtn.style.display = "none"; V.cafeSecretSolved = true; setTimeout(function() { SugarCube.Engine.play("SecretCafeInnerRoom"); }, 3000); } else { setTimeout(function() { SugarCube.Engine.play("SecretCafeInterior"); }, 500); } } else { V.cafeSecretProgress = 0; resultDiv.innerHTML = '<p style="color: #ff6b6b; font-size: 16px; font-style: italic;">The gear refuses to turn. The air shifts and the locks reset themselves.</p>'; for (var j = 0; j < 4; j++) { digits[j] = 0; updateDisplay(j); } setTimeout(function() { SugarCube.Engine.play("SecretCafeInterior"); }, 1500); } } submitBtn.addEventListener("click", handleSubmit); submitBtn.addEventListener("touchend", function(e) { e.preventDefault(); handleSubmit(); }); } })(); </script> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #444; color: white; padding: 10px 22px; border-radius: 6px; display: inline-block; cursor: pointer; font-weight: bold;'>Leave</div>">> <<advancetime 2>> <<goto "Outskirts">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SecretCafeInnerRoom">> <style> @keyframes innerRoomGlow { 0%, 100% { opacity: 0.5; } 50% { opacity: 0.85; } } .inner-room-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 30%, rgba(201,169,255,0.06) 0%, transparent 60%); pointer-events: none; z-index: 0; animation: innerRoomGlow 6s ease-in-out infinite; } </style> <div class="inner-room-overlay"></div> <div style="background: #0a0410; min-height: 100vh; padding: 40px 20px; position: relative; z-index: 1;"> <h1 style="color: #c9a9ff; text-align: center; text-shadow: 0 0 12px rgba(201,169,255,0.5);">🕯️ The Hidden Room</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #c9a9ff; box-shadow: 0 0 30px rgba(201,169,255,0.3);"> <p style="color: #e0d4ff; font-size: 16px; line-height: 1.7;"> The door swings inward without a sound. The room beyond is small and warm, lit by the same violet candles you saw in the corridor, but here they burn steady, unwavering. The air smells of jasmine and something older, something that doesn't belong to any flower. The silhouette you glimpsed from the corridor stands closer now, near the back of the room, a shape that resolves and dissolves whenever you try to focus on it. </p> <p style="color: #b8a8d0; font-size: 15px; line-height: 1.6; margin-top: 14px; font-style: italic;"> Whoever (or whatever) is here, they are watching you. They have been watching you, perhaps, for a very long time. </p> </div> <<run setup.shrine.ensureState()>> <<if $bunBunSummoned>> <div style="padding: 20px; background: linear-gradient(135deg, #1a1528 0%, #0a0410 100%); border-radius: 12px; margin: 20px auto; max-width: 700px; border: 2px solid #6a4a9a; text-align: center;"> <p style="color: #b8a8d0; font-size: 15px; line-height: 1.6; font-style: italic; margin: 0 0 14px 0;">The shrine sits quiet now. The fifty-five small bowls are empty again, but the air feels heavier than before, as if something has stepped through and not entirely stepped back.</p> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6a4a9a 100%); color: white; padding: 10px 24px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 14px;'>Where she waits</div>">> <<goto "BunBunSummoned">> <</link>> </div> <<else>> <<set _totals = setup.shrine.totals()>> <<set _pct = _totals.all.required > 0 ? Math.floor((_totals.all.offered / _totals.all.required) * 100) : 0>> <style> .shrine-grid { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; justify-content: center; } .shrine-card { width: 145px; padding: 10px 8px; border-radius: 8px; display: flex; flex-direction: column; align-items: center; gap: 6px; box-sizing: border-box; min-height: 95px; } .shrine-card.offered { background: linear-gradient(135deg, #2a1f3a 0%, #1a1028 100%); border: 2px solid #ff8fc8; box-shadow: 0 0 8px rgba(255,143,200,0.3); } .shrine-card.offerable { background: linear-gradient(135deg, #2a1f3a 0%, #1a1028 100%); border: 2px solid #c9a9ff; box-shadow: 0 0 10px rgba(201,169,255,0.4); } .shrine-card.locked { background: #110818; border: 2px dashed #3a2a4a; opacity: 0.55; } .shrine-card .name { color: #e0d4ff; font-size: 12px; text-align: center; font-weight: bold; line-height: 1.3; } .shrine-card.locked .name { color: #6a5a78; font-weight: normal; } .shrine-card .status { font-size: 11px; color: #b8a8d0; text-align: center; font-style: italic; } .shrine-card.offered .status { color: #ff8fc8; font-style: normal; } .shrine-card.locked .status { color: #5a4a6a; } .shrine-progress-bar { width: 100%; max-width: 600px; height: 8px; background: #0d0518; border-radius: 4px; overflow: hidden; margin: 8px auto 0 auto; border: 1px solid #3a2a4a; } .shrine-progress-fill { height: 100%; background: linear-gradient(90deg, #c9a9ff 0%, #ff8fc8 100%); transition: width 0.4s ease; } .shrine-section-header { color: #c9a9ff; margin: 25px 0 6px 0; text-align: center; letter-spacing: 1px; } .shrine-section-count { color: #b8a8d0; font-size: 12px; text-align: center; margin: 0 0 10px 0; font-style: italic; } .shrine-soul-panel { display: flex; flex-direction: column; align-items: center; gap: 12px; margin: 14px auto 0 auto; max-width: 560px; } .shrine-soul-prompt { color: #d4c4f0; font-size: 14px; line-height: 1.6; text-align: center; font-style: italic; } .shrine-soul-card { width: 220px; padding: 18px; border-radius: 10px; display: flex; flex-direction: column; align-items: center; gap: 10px; box-sizing: border-box; } .shrine-soul-card.offerable { background: linear-gradient(135deg, #2a1f3a 0%, #1a0a28 100%); border: 2px solid #ff8fc8; box-shadow: 0 0 15px rgba(255,143,200,0.5), 0 0 30px rgba(201,169,255,0.3); } .shrine-soul-card.locked { background: #110818; border: 2px dashed #4a3a4a; opacity: 0.6; } .shrine-soul-card .name { color: #ff8fc8; font-size: 18px; font-weight: bold; letter-spacing: 1px; } .shrine-soul-card.locked .name { color: #6a5a78; } .shrine-soul-card .status { color: #6a5a78; font-size: 12px; font-style: italic; text-align: center; line-height: 1.4; } </style> <div style="padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border-radius: 15px; margin: 20px auto; max-width: 800px; border: 2px solid #c9a9ff; box-shadow: 0 0 25px rgba(201,169,255,0.2);"> <h2 style="color: #c9a9ff; text-align: center; margin: 0 0 12px 0; text-shadow: 0 0 10px rgba(201,169,255,0.5);">🐇 The Bunny Shrine</h2> <p style="color: #d4c4f0; font-size: 14px; line-height: 1.6; text-align: center; margin: 0 0 6px 0; font-style: italic;">What you took for a silhouette in the corridor was not a person at all. It is a low wooden altar, pelts and pale ribbons heaped along its edges, surrounded by fifty-five small clay bowls arranged in three concentric rings. Most of them are empty. The few that are not glow faintly, as though something inside them is awake.</p> <p style="color: #b8a8d0; font-size: 13px; line-height: 1.6; text-align: center; margin: 8px 0 0 0;">A part of you you cannot quite name knows what the bowls want. You can feel each offering being asked of you, one piece of yourself at a time.</p> <<if setup.shrine.has55Done() && !setup.shrine.hasSoulOffered()>> <p style="color: #ff8fc8; font-size: 14px; line-height: 1.6; text-align: center; margin: 12px 0 0 0; font-style: italic;">At the back of the altar, the small carved rabbit's eyes are no longer dark stone. They have begun to burn with a soft white-violet light, watching you steadily.</p> <<else>> <p style="color: #8a7aa0; font-size: 13px; line-height: 1.6; text-align: center; margin: 10px 0 0 0; font-style: italic;">At the back of the altar, half-buried in the heaped ribbons, sits a small carved rabbit. Its eyes are dark stone for now.</p> <</if>> <p style="color: #ff8fc8; font-size: 18px; text-align: center; margin: 16px 0 0 0; font-weight: bold;"><<= _totals.all.offered>> / <<= _totals.all.required>> offerings received</p> <div class="shrine-progress-bar"><div class="shrine-progress-fill" style="width: <<= _pct>>%;"></div></div> <h3 class="shrine-section-header">Physical</h3> <p class="shrine-section-count"><<= _totals.physical.offered>> / <<= _totals.physical.required>></p> <div class="shrine-grid"> <<for _trait range setup.shrine.requiredFor("physical")>> <<set _given = $shrineOfferings.physical.includes(_trait)>> <<set _has = $physicalTraits.includes(_trait)>> <<if _given>> <div class="shrine-card offered"> <div style="font-size: 18px;">✨</div> <div class="name"><<= _trait>></div> <div class="status">Offered</div> </div> <<elseif _has>> <<capture _trait>> <div class="shrine-card offerable"> <div class="name"><<= _trait>></div> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6a4a9a 100%); color: white; padding: 5px 10px; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 11px; box-shadow: 0 0 6px rgba(201,169,255,0.4);'>Offer</div>">> <<run setup.shrine.offerTrait("physical", _trait)>> <<if setup.shrine.isComplete()>> <<set $bunBunSummoned = true>> <<goto "BunBunSummoned">> <<else>> <<goto "SecretCafeInnerRoom">> <</if>> <</link>> </div> <</capture>> <<else>> <div class="shrine-card locked"> <div style="font-size: 18px; color: #4a3a5a;">○</div> <div class="name"><<= _trait>></div> <div class="status">Not yet</div> </div> <</if>> <</for>> </div> <h3 class="shrine-section-header">Mental</h3> <p class="shrine-section-count"><<= _totals.mental.offered>> / <<= _totals.mental.required>></p> <div class="shrine-grid"> <<for _trait range setup.shrine.requiredFor("mental")>> <<set _given = $shrineOfferings.mental.includes(_trait)>> <<set _has = $mentalTraits.includes(_trait)>> <<if _given>> <div class="shrine-card offered"> <div style="font-size: 18px;">✨</div> <div class="name"><<= _trait>></div> <div class="status">Offered</div> </div> <<elseif _has>> <<capture _trait>> <div class="shrine-card offerable"> <div class="name"><<= _trait>></div> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6a4a9a 100%); color: white; padding: 5px 10px; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 11px; box-shadow: 0 0 6px rgba(201,169,255,0.4);'>Offer</div>">> <<run setup.shrine.offerTrait("mental", _trait)>> <<if setup.shrine.isComplete()>> <<set $bunBunSummoned = true>> <<goto "BunBunSummoned">> <<else>> <<goto "SecretCafeInnerRoom">> <</if>> <</link>> </div> <</capture>> <<else>> <div class="shrine-card locked"> <div style="font-size: 18px; color: #4a3a5a;">○</div> <div class="name"><<= _trait>></div> <div class="status">Not yet</div> </div> <</if>> <</for>> </div> <h3 class="shrine-section-header">Skills</h3> <p class="shrine-section-count"><<= _totals.skills.offered>> / <<= _totals.skills.required>></p> <div class="shrine-grid"> <<for _trait range setup.shrine.requiredFor("skills")>> <<set _given = $shrineOfferings.skills.includes(_trait)>> <<set _has = $skills.includes(_trait)>> <<if _given>> <div class="shrine-card offered"> <div style="font-size: 18px;">✨</div> <div class="name"><<= _trait>></div> <div class="status">Offered</div> </div> <<elseif _has>> <<capture _trait>> <div class="shrine-card offerable"> <div class="name"><<= _trait>></div> <<link "<div style='background: linear-gradient(135deg, #c9a9ff 0%, #6a4a9a 100%); color: white; padding: 5px 10px; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 11px; box-shadow: 0 0 6px rgba(201,169,255,0.4);'>Offer</div>">> <<run setup.shrine.offerTrait("skills", _trait)>> <<if setup.shrine.isComplete()>> <<set $bunBunSummoned = true>> <<goto "BunBunSummoned">> <<else>> <<goto "SecretCafeInnerRoom">> <</if>> <</link>> </div> <</capture>> <<else>> <div class="shrine-card locked"> <div style="font-size: 18px; color: #4a3a5a;">○</div> <div class="name"><<= _trait>></div> <div class="status">Not yet</div> </div> <</if>> <</for>> </div> <<if setup.shrine.has55Done() && !setup.shrine.hasSoulOffered()>> <h3 class="shrine-section-header" style="margin-top: 30px; color: #ff8fc8;">A Final Offering</h3> <div class="shrine-soul-panel"> <div class="shrine-soul-prompt">The bowls have stopped ringing. The statue's eyes are watching. There is one more thing the shrine wants, something it would not name until now.</div> <<if setup.shrine.playerHasSoul()>> <div class="shrine-soul-card offerable"> <div class="name">Soul</div> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 7px 14px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 12px; box-shadow: 0 0 10px rgba(255,143,200,0.6);'>Offer your Soul</div>">> <<run setup.shrine.offerSoul()>> <<set $bunBunSummoned = true>> <<goto "BunBunSummoned">> <</link>> </div> <<else>> <div class="shrine-soul-card locked"> <div class="name">Soul</div> <div class="status">You do not yet have what the shrine wants.</div> </div> <</if>> </div> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); color: white; padding: 12px 28px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 15px; box-shadow: 0 0 12px rgba(106,74,154,0.4);'>Slip back into the corridor</div>">> <<goto "SecretCafeInterior">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BunBunSummoned">> <<run setup.shrine.ensureState()>> <style> @keyframes summonGlow { 0%, 100% { opacity: 0.5; transform: scale(1); } 50% { opacity: 0.95; transform: scale(1.04); } } .summon-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: radial-gradient(ellipse at 50% 40%, rgba(255,143,200,0.10) 0%, rgba(201,169,255,0.06) 30%, transparent 70%); pointer-events: none; z-index: 0; animation: summonGlow 5s ease-in-out infinite; } .bunbun-name-panel input[type="text"] { background: #0d0518; border: 2px solid #c9a9ff; color: #ff8fc8; font-family: "Courier New", monospace; font-size: 18px; font-weight: bold; text-align: center; width: 240px; padding: 10px; border-radius: 8px; letter-spacing: 2px; text-shadow: 0 0 6px rgba(255,143,200,0.3); } .bunbun-name-panel input[type="text"]:focus { outline: none; border-color: #ff8fc8; box-shadow: 0 0 12px rgba(255,143,200,0.5); } </style> <div class="summon-overlay"></div> <div style="background: #0a0410; min-height: 100vh; padding: 40px 20px; position: relative; z-index: 1;"> <h1 style="color: #ff8fc8; text-align: center; text-shadow: 0 0 18px rgba(255,143,200,0.5);">✨ She is Summoned</h1> <div style="padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border-radius: 15px; margin: 20px auto; max-width: 700px; border: 2px solid #ff8fc8; box-shadow: 0 0 35px rgba(255,143,200,0.35);"> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7;"> The last bowl fills. For a long second nothing happens, and then every candle in the room flares at once, not violet but white-gold, and the air shudders with a sound like a thousand soft footsteps. The pelts on the altar lift in a wind that isn’t there. The bowls ring softly against each other. </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin-top: 14px;"> From the back of the room, where the shrine’s shadow is deepest, something steps forward. Small. Pink-haired. Bunny-eared. She is exactly where she has always been, you realize, and you simply could not see her until now. She tilts her head and watches you with the patient, unsurprised look of someone who has been waiting a very long time. </p> <<if $bunBunNameLocked>> <p style="color: #ff8fc8; font-size: 16px; line-height: 1.7; margin-top: 14px; font-style: italic;"> She tilts her head at the sound of her name. <strong style="color: #ffc1e0;"><<= $bunBunChosenName>></strong> is here. </p> <<else>> <p style="color: #d4c4f0; font-size: 14px; line-height: 1.6; margin-top: 14px; font-style: italic;"> She does not speak yet. But she is waiting for you to give her a name. </p> <</if>> </div> <<if !$bunBunNameLocked>> <div class="bunbun-name-panel" style="padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border-radius: 15px; margin: 20px auto; max-width: 560px; border: 2px solid #c9a9ff; box-shadow: 0 0 20px rgba(201,169,255,0.25); text-align: center;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0; letter-spacing: 1px;">What will you call her?</h3> <p style="color: #d4c4f0; font-size: 13px; line-height: 1.6; margin: 0 0 16px 0; font-style: italic;">She has answered to "Bun Bun" for as long as she has waited here. You may keep that, or give her a new name. Once chosen, the name cannot be changed.</p> <div style="margin: 14px 0;"> <<textbox "_chosenName" "Bun Bun" autofocus>> </div> <div> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px 24px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 12px rgba(255,143,200,0.5); letter-spacing: 1px;'>Confirm her name</div>">> <<set _trim = (typeof _chosenName === "string") ? _chosenName.trim() : "">> <<if _trim === "">> <<run UI.alert("She needs a name.")>> <<else>> <<set $bunBunNamePending = _trim>> <<run Dialog.setup("Lock in her name?", "bun-bun-name-confirm")>> <<run Dialog.wiki(Story.get("BunBunNameConfirmDialog").processText())>> <<run Dialog.open()>> <</if>> <</link>> </div> </div> <</if>> <<if $bunBunNameLocked && !$bunBunSummonComplete>> <<if !$bunBunSummonStage>><<set $bunBunSummonStage = 1>><</if>> <div id="bunbun-summon-stage" style="margin-top: 26px;"> <<if $bunBunSummonStage === 1>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; max-width: 620px; margin: 0 auto; box-shadow: 0 0 22px rgba(201,169,255,0.22);"> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> She steps out of the corner of the room as if she had only ever been waiting for the right cue. Her eyes find yours and stay there. She does not look surprised. She does not look afraid. She looks, very specifically, found. </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "<<= $bunBunChosenName>>." She tries the name in her own mouth, careful, tasting the shape of it. "Yes. That fits. Thank you." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> Her voice is lower than you expected and much steadier. Crisp consonants. Soft vowels. A polish you cannot quite place except that it sounds like someone who has spent a long time practicing the sentence she is about to say. </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 16px 0;"> "I have been waiting for you a long while," she says. "Will you let me kneel for you, properly? Just the once. The rest you can sort out as we go." </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold; box-shadow: 0 0 12px rgba(255,143,200,0.45);'>Let her kneel</div>">> <<set $bunBunSummonStage = 2>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> </div> </div> <<elseif $bunBunSummonStage === 2>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; max-width: 620px; margin: 0 auto; box-shadow: 0 0 22px rgba(201,169,255,0.22);"> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> She crosses the small distance between you and goes down to her knees with a precision that is almost ceremonial. Spine straight. Ears forward. Hands folded one over the other, the way someone has practiced. She looks up at you and does not blink. </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "I came when you called. I will work for you, and beside you, and at your back. I will not be careless with you. Will you accept me?" </p> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.6; margin: 0 0 16px 0; font-style: italic;"> The shrine is quiet. The candles bow without wind. Whatever this room is, it is paying attention. </p> <p style="color: #b8a8d0; font-size: 13px; text-align: center; margin: 0 0 12px 0;">How do you accept her?</p> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 14px; font-weight: bold;'>Formal</div><div style='color: #b8a8d0; font-size: 12px; margin-top: 2px;'>You match her ceremony. The vow goes both ways.</div></div>">> <<set $bunBunSummonAcceptance = "formal">> <<set $bunBunSummonStage = 3>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 14px; font-weight: bold;'>Warm</div><div style='color: #b8a8d0; font-size: 12px; margin-top: 2px;'>You ask her to stand. You are not interested in distance.</div></div>">> <<set $bunBunSummonAcceptance = "warm">> <<set $bunBunSummonStage = 3>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 14px; font-weight: bold;'>Amused</div><div style='color: #b8a8d0; font-size: 12px; margin-top: 2px;'>You smile. She is being a bit dramatic. You like her already.</div></div>">> <<set $bunBunSummonAcceptance = "amused">> <<set $bunBunSummonStage = 3>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> </div> </div> <<elseif $bunBunSummonStage === 3>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; max-width: 620px; margin: 0 auto; box-shadow: 0 0 22px rgba(201,169,255,0.22);"> <<if $bunBunSummonAcceptance === "formal">> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "I accept you," you say, matching her quiet. "As mine. As <<= $bunBunChosenName>>. You came when I called. Stand at my back. Stand at my side. I will not be careless with you either." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> She closes her eyes for one long breath, and the line of her shoulders comes down a finger's width, the way only someone who has been carrying the wait for a very long time would let it. Yes, Master, she says, very simple. The word does not ask anything from you. It states a fact. </p> <<elseif $bunBunSummonAcceptance === "warm">> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "Stand up, please." You offer her your hand. "You don't have to do that part for me. You're already mine. Get up." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> Her face flickers through three different things in quick succession, none of which you can quite name, and then she takes your hand and rises. She does not let go for a long moment. Yes, she says, finally. Thank you, <<= $bunBunChosenName.length ? "you" : "you">>. The word she did not use, master, sits warm and unsaid between you anyway. </p> <<elseif $bunBunSummonAcceptance === "amused">> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "You absolute drama." You are laughing, a little. "Get up. You don't have to kneel for me. Honestly." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> She blinks once. Then her mouth does something that might be a smile and might be relief. "I am not entirely a drama," she says, getting to her feet with great dignity. "I have been practicing. Allow me one ceremony, sir. Madam. Whichever. The rest you can ruin at your leisure." </p> <<else>> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> You accept her, simply, and she rises. </p> <</if>> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 16px 0;"> She brushes the dust from her knees, a small efficient gesture, and looks at you with the same patient, unsurprised attention she has had since she stepped out of the corner. "Right," she says. "Where do we begin?" </p> <p style="color: #b8a8d0; font-size: 13px; text-align: center; margin: 0 0 12px 0;">What do you tell her?</p> <div style="display: grid; gap: 10px;"> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 14px; font-weight: bold;'>The cafe needs you</div><div style='color: #b8a8d0; font-size: 12px; margin-top: 2px;'>Practical. Put her to work. She will love that.</div></div>">> <<set $bunBunSummonFirstStep = "cafe">> <<set $bunBunSummonStage = 4>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 14px; font-weight: bold;'>Walk with me first</div><div style='color: #b8a8d0; font-size: 12px; margin-top: 2px;'>You owe her a moment that is not work.</div></div>">> <<set $bunBunSummonFirstStep = "walk">> <<set $bunBunSummonStage = 4>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 14px; font-weight: bold;'>Tell me about yourself</div><div style='color: #b8a8d0; font-size: 12px; margin-top: 2px;'>You want to know who you just summoned.</div></div>">> <<set $bunBunSummonFirstStep = "talk">> <<set $bunBunSummonStage = 4>> <<replace "#bunbun-summon-stage">><<include "BunBunSummoned">><</replace>> <</link>> </div> </div> <<elseif $bunBunSummonStage === 4>> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 14px; padding: 22px; max-width: 620px; margin: 0 auto; box-shadow: 0 0 22px rgba(201,169,255,0.22);"> <<if $bunBunSummonFirstStep === "cafe">> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "The cafe needs you," you tell her. "There's a kitchen and three other women trying to run it without anyone in proper charge. That's what I want from you first." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> Her ears come forward. Something close to delight crosses her face, although she controls it very fast. "Head Maid, then," she says, more for herself than for you. "Right. Yes. I can do that. I have ideas about the dinner shift already. May I begin tonight?" </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> You tell her tonight is fine. </p> <<elseif $bunBunSummonFirstStep === "walk">> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "Walk with me first," you tell her. "You've been waiting too long for me to send you straight to a job. The cafe will hold for an hour." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> She looks at you for a long beat, and the patient unsurprised expression she has had on this whole time finally cracks, just a little, into something younger and more open. "Yes," she says. "All right. Yes." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> She does not say thank you for it. She does not need to. The hand she gives you when you offer yours says it for her. </p> <<elseif $bunBunSummonFirstStep === "talk">> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 12px 0;"> "Tell me about yourself first," you say. "I just summoned you out of a shrine. I deserve at least a name, a country of origin, and the worst thing you ever did before you got stuck in here." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> Her mouth twitches. "<<= $bunBunChosenName>>, before you ask," she says. "Origin: a place I no longer remember well, which is probably for the best. Worst thing: I once let a man die who was trying to teach me something. He was a bad teacher. I think we can leave it there for tonight." </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> She watches you take that in. "There will be more," she adds. "Slowly. I do not like being inventoried all at once." </p> <<else>> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> You agree, simply, on a starting point. </p> <</if>> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 14px 0;"> She walks beside you to the corridor without looking back. The shrine room dims gently behind her, the candles snuffing themselves one by one, finished with their long job. She does not flinch when the last one goes out. She does not need to look. She is yours now. The room knows it. She knows it. So do you. </p> <p style="color: #ffd6ec; font-size: 16px; line-height: 1.7; margin: 0 0 18px 0; font-style: italic;"> The corridor accepts you both as you go. </p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); color: white; padding: 12px 28px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 15px; box-shadow: 0 0 12px rgba(106,74,154,0.4);'>Walk out together</div>">> <<set $bunBunSummonComplete = true>> <<set $bunBunSummonStage = 0>> <<goto "SecretCafeInterior">> <</link>> </div> </div> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); color: white; padding: 12px 28px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 15px; box-shadow: 0 0 12px rgba(106,74,154,0.4);'>Slip back into the corridor</div>">> <<goto "SecretCafeInterior">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="text-align: center; padding: 18px 14px; max-width: 480px; margin: 0 auto;"> <p style="color: #ffd6ec; font-size: 15px; line-height: 1.6; margin: 0 0 14px 0;"> You are about to name her <strong style="color: #ffb0d0;"><<= $bunBunNamePending>></strong>. </p> <p style="color: #c9a9ff; font-size: 13px; font-style: italic; margin: 0 0 22px 0;"> Once chosen, this name cannot be changed. </p> <div style="display: flex; gap: 14px; justify-content: center; flex-wrap: wrap;"> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; box-shadow: 0 0 10px rgba(255,143,200,0.4);'>Confirm</div>">> <<run setup.shrine.lockInBunBunName($bunBunNamePending)>> <<run Dialog.close()>> <<goto "BunBunSummoned">> <</link>> <<link "<div style='background: #2a1a3a; color: #d4c4f0; padding: 10px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; border: 1px solid #c9a9ff;'>Cancel</div>">> <<run Dialog.close()>> <</link>> </div> </div> <</nobr>>
<<run setup.bunBunTasks.ensureState()>><<set _bbMaster = (setup.identity && setup.identity.isPlayerMasterRecognized) ? setup.identity.isPlayerMasterRecognized() : true>><<if _bbMaster>><div style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin-bottom: 14px; background: #15101e; border-radius: 8px; border: 1px solid #51cf66;"><span style="color: #51cf66; font-size: 13px; font-weight: bold;">✓ She recognizes you as her master.</span></div><<else>><div style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin-bottom: 14px; background: #15101e; border-radius: 8px; border: 1px solid #6a5a78;"><span style="color: #b8a8d0; font-size: 13px;">✖ She does not recognize you in this body. (Tasks and training are unavailable.)</span></div><</if>><<set _bbAtCafe = (setup.bunBunPresence && setup.bunBunPresence.isAtCafe) ? setup.bunBunPresence.isAtCafe() : false>><<set _bbOnStaff = (setup.bunBunPresence && setup.bunBunPresence.isOnStaff) ? setup.bunBunPresence.isOnStaff() : false>><<if _bbOnStaff>><<if _bbAtCafe>><<set _bbAura = setup.bunBunPresence.getAuraPerMaid()>><<set _bbAuraPct = Math.round(_bbAura * 100)>><<set _bbOthers = setup.bunBunPresence.countOtherMaids()>><div style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin-bottom: 14px; background: #15101e; border-radius: 8px; border: 1px solid #c9a9ff;"><span style="color: #c9a9ff; font-size: 13px; font-weight: bold;">✨ Head Maid presence: +<<= _bbAuraPct>>% per other maid<<if _bbOthers === 0>> (no other maids on staff yet)<</if>></span></div><<else>><div style="display: flex; align-items: center; gap: 10px; padding: 8px 12px; margin-bottom: 14px; background: #15101e; border-radius: 8px; border: 1px solid #6a5a78;"><span style="color: #b8a8d0; font-size: 13px;">✨ Away on a task. Presence buff suspended.</span></div><</if>><</if>><<if setup.bunBunBio && setup.bunBunBio.getCurrentVibe>><<set _bbVibe = setup.bunBunBio.getCurrentVibe()>><<if _bbVibe>><p style="color: #b8a8d0; font-size: 12px; margin: 0 0 14px 0; font-style: italic; padding: 0 4px;">Right now she is <<= _bbVibe>></p><</if>><</if>> <<run setup.bunBunTasks.tickTasks()>> <!-- Pending rewards banner --> <<if $bunBunPendingRewards.notifications.length>> <div style="padding: 14px 18px; background: linear-gradient(135deg, #2a1f3a 0%, #1a0a28 100%); border: 2px solid #ff8fc8; border-radius: 10px; margin-bottom: 18px; box-shadow: 0 0 18px rgba(255,143,200,0.3);"> <h3 style="color: #ff8fc8; margin: 0 0 8px 0;">🐇 <<= $bunBunChosenName || "Bun Bun">>'s Trip Report</h3> <<for _bbn range $bunBunPendingRewards.notifications>> <p style="color: #d4c4f0; margin: 6px 0; font-size: 14px;"><<= _bbn>></p> <</for>> </div> <<run setup.bunBunTasks.drainPendingRewards()>> <</if>> <!-- Tasks panel: assign or active view --> <div style="background: #1a0f2a; border: 2px solid #c9a9ff; border-radius: 10px; padding: 15px; margin-bottom: 18px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🪣 <<= $bunBunChosenName || "Bun Bun">>'s Tasks</h3> <<set _bbActiveTask = setup.bunBunTasks.getActiveTask()>> <<if _bbActiveTask>> <p style="color: #d4c4f0; margin: 4px 0;">She's <<if _bbActiveTask.type === "fishing">>fishing at <<= setup.bunBunTasks._prettyLocation(_bbActiveTask.location)>><<else>>on a <<= _bbActiveTask.type>> task<</if>>.</p> <p style="color: #b8a8d0; font-size: 13px; font-style: italic; margin: 4px 0;">Back at <<= setup.bunBunTasks._formatClock(_bbActiveTask.endMin)>>.</p> <<link "<div style='display: inline-block; background: #4a2a4a; color: #d4c4f0; padding: 6px 14px; border-radius: 5px; cursor: pointer; font-size: 12px; margin-top: 6px;'>Recall her early (no rewards)</div>">> <<run setup.bunBunTasks.recallTask()>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <</link>> <<else>> <p style="color: #d4c4f0; font-size: 13px; margin: 4px 0;">She's at the cafe and ready for a task.</p> <<if !$bunBunTaskTabActive>><<set $bunBunTaskTabActive = ($bunBunFishing.rod ? "fishing" : "hourlyJob")>><</if>> <<set _bbTabs = [{id:"fishing", label:"Fishing"},{id:"hourlyJob", label:"Hourly Job"},{id:"sellFish", label:"Sell Fish"}]>> <div style="display: flex; gap: 6px; margin: 8px 0;"> <<for _bbtab range _bbTabs>> <<capture _bbtab>> <<if $bunBunTaskTabActive === _bbtab.id>> <span style="background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 4px 12px; border-radius: 5px; font-size: 12px; font-weight: bold;"><<= _bbtab.label>></span> <<else>> <<set _bbtabHtml = setup.bunBunTasks._tabHtml(_bbtab.label)>> <<link _bbtabHtml>> <<set $bunBunTaskTabActive = _bbtab.id>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <</link>> <</if>> <</capture>> <</for>> </div> <<if $bunBunTaskTabActive === "fishing">> <<if !$bunBunFishing.rod>> <p style="color: #888; font-style: italic; font-size: 12px;">She'll need a fishing rod before she can fish. Buy one in her gear panel below.</p> <<else>> <<set _bbAllowed = setup.bunBunTasks.allowedFishingLocations()>> <div style="margin: 6px 0;"> <select id="bunbunFishLocation" style="background: #0d0518; color: #d4c4f0; border: 1px solid #c9a9ff; border-radius: 4px; padding: 4px 8px; margin-right: 6px;"> <<for _bbloc range _bbAllowed>> <option @value="_bbloc"><<= setup.bunBunTasks._prettyLocation(_bbloc)>></option> <</for>> </select> <select id="bunbunFishHours" style="background: #0d0518; color: #d4c4f0; border: 1px solid #c9a9ff; border-radius: 4px; padding: 4px 8px;"> <option value="2">2 hours</option> <option value="4" selected>4 hours</option> <option value="6">6 hours</option> <option value="8">8 hours</option> </select> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 6px 14px; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 12px;'>Send her fishing</div>">> <<set _bbloc2 = document.getElementById("bunbunFishLocation").value>> <<set _bbhrs = parseInt(document.getElementById("bunbunFishHours").value, 10)>> <<set _bbres = setup.bunBunTasks.assignTask({ type: "fishing", location: _bbloc2, hours: _bbhrs })>> <<if _bbres.ok>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <<else>> <<run UI.alert(_bbres.reason)>> <</if>> <</link>> <</if>> <<elseif $bunBunTaskTabActive === "hourlyJob">> <<set _bbJobs = setup.bunBunTasks.availableHourlyJobs()>> <<set _bbStatMult = setup.bunBunTasks.hourlyJobStatMult()>> <p style="color: #b8a8d0; font-size: 12px; margin: 4px 0;">Pick a job and how long. Pay scales <<= Math.round(_bbStatMult * 100)>>% with her charisma + intelligence.</p> <div style="margin: 6px 0;"> <select id="bunbunJobName" style="background: #0d0518; color: #d4c4f0; border: 1px solid #c9a9ff; border-radius: 4px; padding: 4px 8px; margin-right: 6px; max-width: 220px;"> <<for _bbjob range _bbJobs>> <option @value="_bbjob"><<= _bbjob>> ($<<= setup.hourlyJobs[_bbjob].hourlyPay>>/hr)</option> <</for>> </select> <select id="bunbunJobHours" style="background: #0d0518; color: #d4c4f0; border: 1px solid #c9a9ff; border-radius: 4px; padding: 4px 8px;"> <option value="2">2 hours</option> <option value="4" selected>4 hours</option> <option value="6">6 hours</option> <option value="8">8 hours</option> </select> </div> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 6px 14px; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 12px;'>Send her to work</div>">> <<set _bbjobName = document.getElementById("bunbunJobName").value>> <<set _bbjobHrs = parseInt(document.getElementById("bunbunJobHours").value, 10)>> <<set _bbjobRes = setup.bunBunTasks.assignTask({ type: "hourlyJob", jobName: _bbjobName, hours: _bbjobHrs })>> <<if _bbjobRes.ok>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <<else>> <<run UI.alert(_bbjobRes.reason)>> <</if>> <</link>> <<elseif $bunBunTaskTabActive === "sellFish">> <<set _bbStorageCount = ($bunBunFishStorage || []).length>> <<set _bbStorageValue = 0>> <<for _bbf range ($bunBunFishStorage || [])>> <<set _bbStorageValue += (_bbf.basePrice || 0)>> <</for>> <<if _bbStorageCount === 0>> <p style="color: #888; font-style: italic; font-size: 12px;">Storage is empty. Send her fishing first.</p> <<else>> <p style="color: #b8a8d0; font-size: 12px; margin: 4px 0;">She will take all <<= _bbStorageCount>> fish to the docks. Estimated return: <span style="color: #ff8fc8;">$<<= _bbStorageValue>></span>. (1 hour.)</p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 6px 14px; border-radius: 5px; cursor: pointer; font-weight: bold; font-size: 12px;'>Send her to sell</div>">> <<set _bbsellRes = setup.bunBunTasks.assignTask({ type: "sellFish" })>> <<if _bbsellRes.ok>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <<else>> <<run UI.alert(_bbsellRes.reason)>> <</if>> <</link>> <</if>> <</if>> <</if>> </div> <!-- Gear panel --> <div style="background: #1a0f2a; border: 2px solid #c9a9ff; border-radius: 10px; padding: 15px; margin-bottom: 18px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🎣 <<= $bunBunChosenName || "Bun Bun">>'s Gear</h3> <<set _bbCurRod = $bunBunFishing.rod || 0>> <p style="color: #d4c4f0; font-size: 13px; margin: 4px 0;">Current rod: <<if _bbCurRod>>Tier <<= _bbCurRod>><<else>>None<</if>>. Fishing level: <<= $bunBunFishing.level || 1>> (<<= $bunBunFishing.xp || 0>> xp, <<= $bunBunFishing.catches || 0>> catches).</p> <<for _bbt = 1; _bbt <= 3; _bbt++>> <<capture _bbt>> <<if _bbCurRod < _bbt>> <div style="margin: 6px 0; padding: 6px 10px; background: #0d0518; border-radius: 4px;"> <span style="color: #d4c4f0; font-size: 13px;"><<= setup.bunBunTasks._rodNames[_bbt]>></span> <span style="color: #ff8fc8; font-size: 13px; margin-left: 8px;">$<<= setup.bunBunTasks._rodPrices[_bbt]>></span> <<if $money >= setup.bunBunTasks._rodPrices[_bbt]>> <<link "<span style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 11px; margin-left: 8px;'>Buy</span>">> <<set _bbBuy = setup.bunBunTasks.buyRod(_bbt)>> <<if _bbBuy.ok>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <<else>> <<run UI.alert(_bbBuy.reason)>> <</if>> <</link>> <<else>> <span style="color: #888; font-size: 11px; margin-left: 8px;">(need $<<= setup.bunBunTasks._rodPrices[_bbt] - $money>>)</span> <</if>> </div> <</if>> <</capture>> <</for>> <p style="color: #c9a9ff; font-size: 11px; font-style: italic; margin: 8px 0 0 0;">She does not need to eat or sleep. She just chooses to.</p> <p style="color: #6a5a78; font-size: 11px; font-style: italic; margin: 8px 0 0 0;">She can't use the Sunfish Rod (tier 4). It's reserved for you.</p> </div> <!-- Training panel --> <div style="background: #1a0f2a; border: 2px solid #c9a9ff; border-radius: 10px; padding: 15px; margin-bottom: 18px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">💪 <<= $bunBunChosenName || "Bun Bun">>'s Training</h3> <<if $bunBunTrainingResult>> <<set _bbtr = $bunBunTrainingResult>> <<set $bunBunTrainingResult = null>> <div style="background: linear-gradient(135deg, #2a1f3a 0%, #1a0a28 100%); border: 1px solid #ff8fc8; border-radius: 8px; padding: 10px 14px; margin-bottom: 10px;"> <p style="color: #ff8fc8; margin: 0 0 4px 0; font-size: 14px; font-weight: bold;"> <<if _bbtr.gain > 0>>+<<= _bbtr.gain>> <<= _bbtr.statName.charAt(0).toUpperCase() + _bbtr.statName.slice(1)>>!<<else>>No gain<</if>> <<if _bbtr.mismatched>> <span style="color: #b8a8d0; font-size: 12px; font-weight: normal;">(mismatched gift, half effect)</span><</if>> </p> <p style="color: #d4c4f0; font-size: 12px; margin: 0;">She accepts the <<= _bbtr.giftIcon>> <<= _bbtr.giftName>>.</p> </div> <</if>> <<if $bunBunTrainingFor>> <p style="color: #d4c4f0; font-size: 13px; margin: 4px 0 8px 0;">Pick a gift to train <strong style="color: #ff8fc8; text-transform: capitalize;"><<= $bunBunTrainingFor>></strong>. Matched gifts (highlighted) give full effect; mismatched give half (and cheap mismatches give 0).</p> <<set _bbgifts = setup.bunBunTraining.ownedGiftsSorted($bunBunTrainingFor)>> <<if !_bbgifts.length>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 8px 0;">No gifts in your inventory. Visit shops in town to stock up.</p> <<else>> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 8px; margin: 6px 0;"> <<for _bbg range _bbgifts>> <<capture _bbg>> <<set _bbproj = setup.bunBunTraining.projectedGain($bunBunTrainingFor, _bbg.id)>> <<set _bbCheck = setup.bunBunTraining.canTrain($bunBunTrainingFor, _bbg.id)>> <div style="background: #15101e; border: 1px solid #3a2a4a; border-radius: 6px; padding: 8px;"> <<if _bbg.matched>> <div style="color: #d4c4f0; font-size: 12px; margin-bottom: 4px;"> <<= _bbg.icon>> <<= _bbg.name>> <span style="color: #888;">x<<= _bbg.qty>></span> </div> <div style="color: #ff8fc8; font-size: 11px; margin-bottom: 6px;"> <<= _bbg.tier>> | +<<= _bbproj.gain>> stat | $<<= _bbproj.fee>> </div> <<else>> <div style="color: #8a7a98; font-size: 12px; margin-bottom: 4px;"> <<= _bbg.icon>> <<= _bbg.name>> <span style="color: #555;">x<<= _bbg.qty>></span> </div> <div style="color: #6a5a78; font-size: 11px; margin-bottom: 6px;"> <<= _bbg.tier>> | +<<= _bbproj.gain>> stat (mismatched) | $<<= _bbproj.fee>> </div> <</if>> <<if _bbCheck.ok>> <<link "<span style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 11px;'>Give</span>">> <<set _bbResult = setup.bunBunTraining.trainStat($bunBunTrainingFor, _bbg.id)>> <<if _bbResult.ok>> <<set $bunBunTrainingResult = _bbResult>> <<else>> <<run UI.alert(_bbResult.reason)>> <</if>> <<set $bunBunTrainingFor = null>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <</link>> <<else>> <span style="color: #6a5a78; font-size: 11px; font-style: italic;"><<= _bbCheck.reason>></span> <</if>> </div> <</capture>> <</for>> </div> <</if>> <div style="margin-top: 10px;"> <<link "<span style='display: inline-block; background: #4a2a4a; color: #d4c4f0; padding: 5px 14px; border-radius: 5px; cursor: pointer; font-size: 12px;'>Cancel</span>">> <<set $bunBunTrainingFor = null>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <</link>> </div> <<else>> <p style="color: #b8a8d0; font-size: 12px; margin: 0 0 8px 0;">Spend money plus a gift to raise a stat (cap 999). Gifts also bond her.</p> <<for _bbst range setup.bunBunTraining.STATS>> <<capture _bbst>> <<set _bbCur = setup.bunBunTraining.getStat(_bbst)>> <<set _bbPct = Math.min(100, Math.floor((_bbCur - setup.bunBunTraining.STAT_BASE) / (setup.bunBunTraining.STAT_CAP - setup.bunBunTraining.STAT_BASE) * 100))>> <div style="display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid #2a1a3a;"> <span style="color: #d4c4f0; font-size: 13px; min-width: 100px; text-transform: capitalize;"><<= _bbst>></span> <div style="flex: 1; height: 8px; background: #0d0518; border-radius: 4px; overflow: hidden; position: relative; min-width: 60px;"> <div style="width: <<= _bbPct>>%; height: 100%; background: linear-gradient(90deg, #c9a9ff 0%, #ff8fc8 100%); border-radius: 4px;"></div> </div> <span style="color: #b8a8d0; font-size: 12px; min-width: 80px; text-align: right;"><<= _bbCur>> / <<= setup.bunBunTraining.STAT_CAP>></span> <<if _bbCur >= setup.bunBunTraining.STAT_CAP>> <span style="color: #6a5a78; font-size: 11px; font-style: italic; min-width: 60px; text-align: center;">Maxed</span> <<else>> <<link "<span style='display: inline-block; background: linear-gradient(135deg, #c9a9ff 0%, #ff8fc8 100%); color: #1a0a28; padding: 3px 10px; border-radius: 4px; cursor: pointer; font-weight: bold; font-size: 11px;'>Train</span>">> <<set $bunBunTrainingFor = _bbst>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <</link>> <</if>> </div> <</capture>> <</for>> <</if>> </div> <!-- Storage bin panel --> <div style="background: #1a0f2a; border: 2px solid #c9a9ff; border-radius: 10px; padding: 15px; margin-bottom: 20px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🪣 <<= $bunBunChosenName || "Bun Bun">>'s Storage Bin (<<= $bunBunFishStorage.length>> / <<= $bunBunStorageCap>>)</h3> <<if !$bunBunFishStorage.length>> <p style="color: #888; font-style: italic; font-size: 13px;">Empty.</p> <<else>> <<for _bbi = 0; _bbi < $bunBunFishStorage.length; _bbi++>> <<capture _bbi>> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #3a2a4a; align-items: center;"> <span style="color: #d4c4f0; font-size: 13px;"><<= $bunBunFishStorage[_bbi].name>> (<<= $bunBunFishStorage[_bbi].rarity>>) - $<<= $bunBunFishStorage[_bbi].basePrice>></span> <span> <<link "<span style='color: #c9a9ff; font-size: 11px;'>Take</span>">><<run setup.bunBunTasks.takeFish(_bbi)>><<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>><</link>> <span style="color: #555;"> | </span> <<link "<span style='color: #ff8fc8; font-size: 11px;'>Sell</span>">><<run setup.bunBunTasks.sellFish(_bbi)>><<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>><</link>> </span> </div> <</capture>> <</for>> <div style="margin-top: 10px; text-align: right;"> <<link "<span style='display: inline-block; background: #4a2a7a; color: white; padding: 4px 12px; border-radius: 4px; cursor: pointer; font-size: 12px;'>Sell All</span>">> <<run setup.bunBunTasks.sellAllFish()>> <<replace "#bunbun-panels-root">><<include "BunBunCafePanels">><</replace>> <</link>> </div> <</if>> </div>
<<nobr>> <<set _key = $currentMaidScene>> <<set _variant = $currentMaidSceneVariant || "firstNight">> <<set _inhabitedMaid = (setup.identity && setup.identity.getInhabitedMaid) ? setup.identity.getInhabitedMaid() : null>> <div style="background: linear-gradient(180deg, #0d0a14 0%, #1a0a28 50%, #0d0a14 100%); min-height: 100vh; padding: 20px; color: #d4c4f0;"> <div style="max-width: 720px; margin: 0 auto; padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0f0a1a 100%); border-radius: 15px; border: 2px solid #c9a9ff; box-shadow: 0 0 25px rgba(201,169,255,0.25);"> <<if _variant === "player" && _inhabitedMaid>> <p style="color: #ff8fc8; font-size: 13px; font-style: italic; margin: 0 0 12px 0; padding: 8px 12px; background: #2a1f3a; border-left: 3px solid #ff8fc8; border-radius: 4px;"> Your consciousness rides shotgun in <<= _inhabitedMaid>>'s body. The skin is hers. The wanting is yours. The other woman in the room reads only the body, not the visitor inside it. </p> <</if>> <<if _key === "Bun Bun_Clover">><<include "MaidSex_BunBun_Clover">><<elseif _key === "Bun Bun_Mochi">><<include "MaidSex_BunBun_Mochi">><<elseif _key === "Bun Bun_Ren">><<include "MaidSex_BunBun_Ren">><<elseif _key === "Clover_Mochi">><<include "MaidSex_Clover_Mochi">><<elseif _key === "Clover_Ren">><<include "MaidSex_Clover_Ren">><<elseif _key === "Mochi_Ren">><<include "MaidSex_Mochi_Ren">><<else>> <p style="color: #888;">No scene selected.</p> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); border: 2px solid #c9a9ff; color: #ffffff; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Back to the cafe</div>">> <<set $currentMaidScene = null>> <<set $currentMaidSceneVariant = null>> <<goto "PufferfishManage">> <</link>> </div> </div> </div> <</nobr>>
<h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">Bun Bun and Clover</h2> <<if _variant === "casual">> <p>Closing time. Clover hooks a finger in the back of Bun Bun's collar without saying a word, and Bun Bun, who has been the one in charge of every small thing today, lets herself be turned around and pulled in. The kitchen lights are still on. Clover's mouth tastes like coffee and something warmer. They don't make it upstairs. The prep counter is wiped down twice a day for a reason, Bun Bun thinks, distantly, with Clover's hand already inside her uniform.</p> <p>It's quick and easy and it leaves them both grinning. Clover wipes the counter again on the way out.</p> <<else>> <p>Bun Bun is the last one in the cafe most nights, and most nights Clover stays a little longer than she has to. Tonight she finally stops pretending it's about the inventory.</p> <p>"You work harder than anyone I've ever known," Clover says, leaning against the doorway of the storeroom. Her arms are folded under her chest, which is a deliberate framing on Clover. "It's not flattering. It's a problem."</p> <p>Bun Bun looks up from the clipboard. Her ears are pinned back the way they go when she's deciding whether to bristle or bend. "I've been told."</p> <p>"Put the clipboard down."</p> <p>"I have three more lines."</p> <p>"Put it down, Bun Bun."</p> <p>She does, because the voice Clover uses is the one no one in this cafe has ever told no. Clover steps in and closes the door with her foot.</p> <p>What follows is patient and thorough. Clover undresses Bun Bun the way she does most things, with broad sure hands and zero hurry, and Bun Bun lets it happen because for once the body doing the work isn't her own. Clover kisses the inside of one wrist, then the other, then the place where the bunny's pulse stays rabbit-fast under all that discipline. "Breathe," she says. Bun Bun breathes.</p> <p>Clover's chest is hot against Bun Bun's mouth and there is, when she gets there, a slow generous slide of milk that Bun Bun was not braced for. She makes a small surprised sound and Clover laughs low. "I know. Take what you need. There's plenty."</p> <p>Bun Bun does. The discipline of her whole body that made her the head maid of this cafe goes liquid for a minute, and Clover holds her through it, fingers in the short fur at the back of her neck, voice murmuring nothing that needs to be remembered.</p> <p>Then Bun Bun, because she is who she is, turns the room around. Clover, who has been in charge of the holding, lets herself be set on the prep counter and worked over by a mouth that is precise and demanding and astonishingly good at its job. "Oh," Clover says, and "oh, sweetheart," and after a while she stops talking entirely.</p> <p>They lock up together, much later. The cafe is dark and faintly warm. Clover walks Bun Bun to the door of the staff stairs and kisses her once, slowly, and says, "Tomorrow. After close. I'm not asking."</p> <p>"I wasn't going to argue," Bun Bun says.</p> <</if>>
<h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">Bun Bun and Mochi</h2> <<if _variant === "casual">> <p>Mochi tucks herself into Bun Bun's side after the dinner rush, and Bun Bun, who is supposed to be balancing the tills, lets the calculator close with a small click. They go upstairs without comment. Mochi is curled into Bun Bun's lap before the door is fully shut, not asking for anything, just there, and Bun Bun strokes her hair while the small body in her arms gets slowly warmer.</p> <p>It turns into more, the way it does. Mochi's mouth is soft and she follows direction beautifully. Bun Bun says, "Good girl," very quietly, and Mochi shudders and nods and keeps going.</p> <<else>> <p>It is Mochi's fault, in the end, but only because she is the one who finally stops pretending. She brings Bun Bun a cup of tea after closing, the way she does most evenings, and tonight when she sets it down she doesn't move away.</p> <p>"Mochi." Bun Bun doesn't look up from the inventory. "What is it?"</p> <p>"I don't know. I'm sorry. I just. Wanted to be near you for a minute."</p> <p>Bun Bun sets the pen down. She looks up at the small pink-haired maid standing very still and very pink-faced beside her chair, and something in Bun Bun's chest, which has been forty kinds of practical all day, gets quiet.</p> <p>"Come here," she says.</p> <p>Mochi does. She climbs into Bun Bun's lap because that is the only place she wanted to be, and tucks her head under Bun Bun's chin, and breathes.</p> <p>"Is this all right?" Mochi whispers.</p> <p>"Yes."</p> <p>"Can I kiss you?"</p> <p>"Yes."</p> <p>The kiss is the smallest possible thing at first. Mochi has clearly been thinking about it for a long time. She pulls back, eyes huge. Bun Bun catches her face with both hands and kisses her again, slow, claiming, the way she does anything that becomes her job to do well.</p> <p>Upstairs is closer than the storeroom. They make it as far as the bed.</p> <p>Mochi is shaking a little when Bun Bun gets her uniform open, and Bun Bun, who knows the look of someone bracing for a thing they want too much to be calm about, slows down. She kisses every place her hands move. She tells Mochi she is good, twice, and Mochi makes a small wrecked sound the second time and stops shaking.</p> <p>"Tell me what you need," Bun Bun says, mouth at Mochi's collarbone.</p> <p>"You. Just. Anything. Whatever you say."</p> <p>Bun Bun says quite a few things, in the next hour. Mochi follows every one. She is, it turns out, exactly as devoted as she looks, and Bun Bun rewards every shy yes with patient careful hands and a mouth that knows what it's doing. Mochi cries a little at the end, not unhappy, and Bun Bun holds her through it, and when she finally goes still in Bun Bun's arms she says, very small, "I've been wanting that for so long."</p> <p>"I know," Bun Bun says. "Me too."</p> <</if>>
<h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">Bun Bun and Ren</h2> <<if _variant === "casual">> <p>They've stopped pretending it's a competition. It used to be, briefly, in a way that involved both of them ending up flushed and arguing about whose technique was better. These days they skip the argument and go straight to a draw.</p> <p>Tonight Ren beats her at it again, which surprises neither of them. Bun Bun spends the morning walking carefully and pretends not to notice Ren's smug look. Ren spends the morning being unbearable and Bun Bun spends the afternoon wiping it off her with one truly devastating fifteen-minute lunch break in the supply closet.</p> <p>They are a horrible disgrace to the establishment. They both think it's hilarious.</p> <<else>> <p>Ren has been circling for weeks, the way she does. Bun Bun has been refusing to look at her, the way she does. It comes to a head, predictably, the night the cafe is empty after a slow shift and they are the last two on the floor.</p> <p>"Are we doing this or not," Ren says, perched on a stool, legs crossed, eyes on Bun Bun like she has all night.</p> <p>Bun Bun keeps wiping the same patch of counter. "Doing what."</p> <p>"Don't."</p> <p>Bun Bun sets the cloth down. "Fine. What are your terms."</p> <p>"You don't get to top me."</p> <p>"You don't get to top me either."</p> <p>"So we're at an impasse."</p> <p>"Apparently."</p> <p>Ren laughs. It's the real one, the one almost no one has heard. "God, you're insufferable. Get over here."</p> <p>The kiss is a fight. Both of them are too proud to give first. Ren bites Bun Bun's lower lip and Bun Bun digs both hands into Ren's hair and yanks just hard enough for Ren to make a sound she'll deny later. They knock over a stool. They knock over Ren's purse. They end up on the office floor because the office is the only door that locks.</p> <p>Neither of them tops, in the end. They wear each other out. Ren's pride and Bun Bun's discipline blur into the same exhausted thing, and somewhere around the second hour Ren says, ragged, "Truce," and Bun Bun says, equally ragged, "Truce," and they finally just pull each other down and let it be slow and even and good.</p> <p>Ren falls asleep with her head on Bun Bun's stomach. Bun Bun discovers, with a kind of bemused horror, that she is going to let her stay there. The kitsune is heavier than she looks and her hair smells faintly of incense and she is, despite every public thing she has ever said, soft when she's asleep.</p> <p>Bun Bun strokes her hair anyway. They will both pretend nothing has happened in the morning. It will not work.</p> <</if>>
<h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">Clover and Mochi</h2> <<if _variant === "casual">> <p>It becomes a habit. Mochi finishes her shift looking thin and small around the edges, the way she does after a long day, and Clover wordlessly takes her by the wrist and walks her into the back. The break room couch is generous enough for both of them. Clover does most of the work and Mochi melts gratefully into her.</p> <p>"Better?" Clover asks afterwards, brushing Mochi's hair back.</p> <p>"Better," Mochi mumbles into Clover's chest. She's already nearly asleep.</p> <<else>> <p>Mochi has had a bad day. A regular yelled at her, a tray broke, Bun Bun watched the whole thing and didn't intervene because the regular was wrong and Mochi handled it correctly, but Mochi cried in the back office afterwards anyway. She is small. She does not absorb things gracefully.</p> <p>Clover finds her there an hour after close, knees up to her chest on the office couch, pretending she hasn't been crying.</p> <p>"Sweetheart," Clover says, soft.</p> <p>"I'm fine."</p> <p>"Hush. Come here."</p> <p>Mochi looks up, and her face does the thing it does, the held-it-in-too-long thing, and Clover crosses the room and sits down and pulls her in. Mochi cries against the warm soft expanse of her properly this time. Clover doesn't say anything stupid. She just holds her and rubs slow circles on her back.</p> <p>After a while the crying tapers. Mochi sniffs and presses her face harder into Clover's chest and says, very small, "You smell so good."</p> <p>Clover laughs, quiet. "Thank you, kitten."</p> <p>"Can I." Mochi's voice is muffled. "Is it weird if."</p> <p>"What do you want, honey."</p> <p>"To be close. Like. Closer."</p> <p>Clover kisses the top of her head. Then, when Mochi tilts her face up, she kisses her mouth, slow and easy and not at all in a hurry. Mochi makes a small relieved sound, like something heavy has gone down.</p> <p>Clover takes her time. She is older and broader and warmer and she has done this enough to know that Mochi needs to be held more than she needs anything fast. So she undresses her slowly, kisses every freckle she finds, lets Mochi hide her face in her neck when it gets too much. When Mochi shyly asks, mouth against Clover's ear, if she could, please, taste the milk, Clover laughs and says, "Of course you can, sweetheart," and guides Mochi's mouth to her breast like the most natural thing in the world.</p> <p>Mochi falls into a contented small puddle there. Clover strokes her hair with one hand and her thigh with the other, and when Mochi's hips start moving against her own without permission, Clover slips a hand down between them and finishes her gently and thoroughly while she nurses, the way you'd quiet a fussy child by giving her three good things at once.</p> <p>Mochi falls asleep on her chest afterwards. Clover, holding her, decides she's not moving for at least an hour, and possibly not at all.</p> <</if>>
<h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">Clover and Ren</h2> <<if _variant === "casual">> <p>It's still mostly an argument, every time. Ren says something cutting. Clover says something cutting back. They end up against the staff-room wall trying to win a fight neither of them is willing to lose by giving the other an inch of softness, and somewhere in there it becomes a different kind of fight, and somewhere in there it becomes the good kind, and they leave the staff room half an hour later both walking carefully and refusing to make eye contact for the rest of the shift.</p> <p>The whole cafe knows. The whole cafe is being polite about it. Bun Bun has the only smile.</p> <<else>> <p>The night it finally happens, Ren says something specifically calibrated to wound Clover, and Clover, who is not a woman to be wounded by Ren on her own floor, hands the rag off to Mochi and tells her, calm, "Cover the front. We'll be five minutes."</p> <p>It is not five minutes. Ren is already in the staff room when Clover gets there, one hip cocked, eyebrow up. "Going to lecture me?"</p> <p>"No."</p> <p>"Going to fire me?"</p> <p>"No."</p> <p>"Then what, exactly, are we doing?"</p> <p>Clover crosses the room and kisses her. It is not a friendly kiss. Ren makes an outraged sound against her mouth and then, because she cannot stand to be outdone, kisses her back harder.</p> <p>"You think you're going to win this," Ren says, breathless.</p> <p>"I know I am."</p> <p>"You think your tits are going to win it for you."</p> <p>"They usually do, sweetheart."</p> <p>Ren laughs, furious, and shoves Clover up against the locker bank, and Clover, who is twice Ren's body weight in the relevant places, lets her do it for about three seconds before she rotates them and pins her in turn. Ren's pulse is jumping in her throat. Her pupils are blown.</p> <p>"Tell me to stop," Clover says, even-voiced, hand at Ren's waist.</p> <p>"Don't you dare," Ren says.</p> <p>It happens fast and graceless and exactly as competitive as you'd expect from two women too proud to back down from a thing. Ren scratches Clover's shoulders. Clover bites Ren's neck. Neither of them does any of it gently. But somewhere in there it stops being a fight and becomes something else, slower, less articulate, and Ren is the first to break, gasping into Clover's mouth, "Don't stop, don't stop, please don't stop," and Clover, who has wanted to hear Ren say please for years, doesn't.</p> <p>Afterwards Ren rebuttons her uniform with shaking hands and says, "If you tell anyone about this I'll kill you."</p> <p>"Mm hmm."</p> <p>"Clover. I mean it."</p> <p>"I know you do, sweetheart." Clover smooths Ren's collar back into place, gentle now that the fight is over. "Same time tomorrow?"</p> <p>Ren glares at her for a long second. "Fine."</p> <</if>>
<h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">Mochi and Ren</h2> <<if _variant === "casual">> <p>Mochi has stopped being nervous about it. Mostly. Ren still gets the small shiver out of her every time she leans in to whisper instructions in her ear during a slow shift, and Mochi still goes that pretty pink color she goes, but afterwards, in Ren's room, Mochi has gotten very confident about a few specific things, and Ren, who did not expect the kitten to learn this fast, has been pleasantly surprised most evenings of the past week.</p> <p>"Good girl," Ren says, hand in Mochi's hair, and Mochi smiles around her like a cat with cream.</p> <<else>> <p>Ren has been flirting with Mochi for weeks the way Ren flirts: low-stakes, carefully calibrated, plausibly deniable. Mochi has been responding the way Mochi responds: by going pink and dropping things. It is, in Ren's opinion, the cutest possible failure mode in a coworker, and she has not been about to let it go.</p> <p>So tonight, after the close, when Mochi stays late to help her restock the wine fridge, Ren does the predictable thing. She lets her hand brush Mochi's at the same time she leans in to reach a high shelf. Mochi freezes.</p> <p>"Sorry," Mochi whispers.</p> <p>"For what, kitten?"</p> <p>"I don't know. Just. Sorry."</p> <p>Ren turns and looks at her. Mochi, two shelves shorter and very pink, looks back. The wine fridge hums.</p> <p>"Mochi," Ren says, gentle for her. "Do you want to come upstairs with me."</p> <p>"Yes," Mochi says, immediately, and then claps her hands over her mouth.</p> <p>"Good answer," Ren says, and takes her hand.</p> <p>Upstairs, Ren is very patient. She does not rush Mochi. She kisses her standing in the middle of the room until Mochi stops shaking. She undresses her the way you'd unwrap a present you've been looking forward to, and she tells her, more than once, that she is gorgeous and that there is no part of this that has to go any further than Mochi wants it to.</p> <p>Mochi wants all of it. She just doesn't know how to ask. Ren teaches her how to ask. Ren teaches her, also, what to do with her mouth and her hands and a few other things, and Mochi turns out to be a fast learner, the way some Werecats are, and somewhere in the middle of the second round it stops being lessons and becomes something Mochi is leading, a little, and Ren is laughing into her hair, delighted.</p> <p>"There you are," Ren says, much later, hand on Mochi's cheek. "Knew you were in there."</p> <p>Mochi, sleepy and well-loved and pinker than she has ever been, smiles and bites Ren's thumb softly.</p> <p>"Can I come back tomorrow?"</p> <p>"Kitten." Ren tucks her in and kisses her forehead. "You can come back every night."</p> <</if>>
<<nobr>> <<set _maidName = "Mochi">> <div style="background: linear-gradient(180deg, #0d0a14 0%, #1a0a28 50%, #0d0a14 100%); min-height: 100vh; padding: 20px; color: #d4c4f0;"> <div style="max-width: 720px; margin: 0 auto; padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0f0a1a 100%); border-radius: 15px; border: 2px solid #ff8fc8; box-shadow: 0 0 25px rgba(255,143,200,0.25);"> <<set _isCerberus = $activeTransformation === "Cerberus">> <<if _isCerberus>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <</if>> <h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">A Quiet Evening with Mochi</h2> <<if _isCerberus>> <p>Mochi closes the cafe early when she sees you waiting, and then she sees the rest of you, the three heads on their three necks, and she goes very still with the dish towel half-wrung in her hands. She doesn't scream. She doesn't even step back. She just stares, breath caught, while a slow blush climbs all the way to her ears.</p> <p>"Oh," she breathes. "Oh, there's, there's three of you."</p> <p><span @style="'color: ' + _cCenter + ';'"><<if _pCenter.kind>><<print _nCenter>> smiles gently, giving her all the time in the world to decide. "Hi, Mochi. It's still me. All of me."<<elseif _pCenter.flirty>><<print _nCenter>> tips a warm, teasing smile her way. "Three times the trouble. Is that a yes?"<<elseif _pCenter.dominant>><<print _nCenter>> holds her gaze steadily. "Hi. Come here, sweet thing."<<else>><<print _nCenter>> meets her eyes softly. "Hi. It's alright. It's me."<</if>></span></p> <p>She takes one shy step closer, then another, and finally she laughs, wet and delighted and embarrassed all at once. "I've been thinking about you all day," she admits, "and now there's more of you to think about."</p> <p> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.bitchy>><<print _nLeft>> smirks. "Took you long enough to stop staring."<<elseif _pLeft.confident>><<print _nLeft>> leans in close, sure of herself. "Then let us make it worth the wait."<<elseif _pLeft.energetic>><<print _nLeft>> perks up eagerly. "Upstairs, upstairs, come on!"<<else>><<print _nLeft>> dips down to brush her cheek. "We've been thinking about you too."<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> hangs back almost as shy as Mochi herself, watching her with quiet wonder.<<elseif _pRight.awkward>><<print _nRight>> fumbles for words and just manages, "You're, you look really nice tonight," which makes her giggle.<<elseif _pRight.kind>><<print _nRight>> murmurs softly, "Only as much as you want, okay? We've got all night."<<else>><<print _nRight>> presses gently to her temple, sharing in the warmth.<</if>></span> </p> <p>"Take me upstairs," she whispers, to all three of you at once. "Please."</p> <p>You do. The staff stairs are dark and narrow, and Mochi keeps a hand fisted in your sleeve the whole way up, glancing between your three faces like she can't believe her luck. In her room she stops at the foot of the bed and stands very still and lets <<print _nCenter>> guide her out of her clothes while the other two watch over her, the part she has been wanting all day, the part where she doesn't have to decide.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> takes the lead, voice low and certain, telling her exactly how good she's being.<<elseif _pCenter.kind>><<print _nCenter>> kisses every place she trembles, patient and unhurried.<<else>><<print _nCenter>> sets the pace, slow and tender, mouth warm against her throat.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.flirty>><<print _nLeft>> nips and teases at the curve of her shoulder until she gasps. "Louder, sweetheart."<<elseif _pLeft.dominant>><<print _nLeft>> growls soft praise into her ear. "You're allowed to be loud. We want to hear you."<<else>><<print _nLeft>> traces kisses along her jaw, drawing out the smallest sounds.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> presses gentle worship to the small of her back, content to follow the others.<<elseif _pRight.kind>><<print _nRight>> whispers reassurance against her skin every time she shivers. "You're perfect. We've got you."<<else>><<print _nRight>> adds her own slow attention, sharing her between the three of you.<</if>></span> </p> <p>Mochi is so eager and so shy, all at once, and she has never in her life been the sole focus of so much attention. She makes the smallest sounds, like she is afraid of being too loud, and all three heads tell her, in their own ways, that she is allowed to be loud, and after a minute she is, a little, then a lot, gasping and trembling and following your every cue. When you ask her what she wants she says, "Whatever you want," and when <<print _nCenter>> pushes back gently and tells her she's allowed to want things, she goes pink to the ears and admits, in a tiny voice, three specific requests, one whispered to each of you, all of which the three of you are happy to fulfill in detail.</p> <p>Afterwards she curls into the middle of you like a small warm comma, one hand still resting on each of the outer heads as if to keep them close, and falls asleep with her ear pressed to your heart. The cafe sign is still on outside. You will worry about it in the morning.</p> <<else>> <p>Mochi closes the cafe early when she sees you waiting. She doesn't say so but you can tell, by the way she takes her apron off slowly and folds it twice, that she has been thinking about this all day.</p> <p>"Hi," she says, very small, when she finally turns around.</p> <p>"Hi."</p> <p>"I'm so glad you came."</p> <p>You take her hand. She tucks her face into your neck and stays there for a long moment, breathing you in, before she dares to look up. Then she does, and her eyes are huge and pink-tinged and she is the bravest thing you have ever seen.</p> <p>"Take me upstairs," she whispers.</p> <p>You do. The staff stairs are dark. Mochi keeps both hands on yours the whole way up. In her room she stops at the foot of the bed and stands very still and lets you undress her, which is what she has been wanting all day, the part where she doesn't have to decide.</p> <p>You go slowly. You kiss every place she trembles. Mochi makes the smallest sounds, like she is afraid of being too loud, and you tell her she is allowed to be loud, and after a minute she is, a little, gasping wetly into your mouth as you find the places she wants you most.</p> <p>She is so eager and so shy, all at once. She follows your every cue. When you ask her what she wants she says, "Whatever you want," and when you push back gently and tell her she's allowed to want things, she goes pink to the ears and admits, in a tiny voice, three specific requests, all of which you are happy to fulfill in detail.</p> <p>Afterwards she curls into you like a small warm comma and falls asleep with her ear pressed to your heart. The cafe sign is still on outside. You will worry about it in the morning.</p> <</if>> <<run setup.advancetime ? setup.advancetime(120) : (State.variables.timeInMinutes = (State.variables.timeInMinutes || 0) + 120)>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); border: 2px solid #c9a9ff; color: #ffffff; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Slip out before dawn</div>">> <<goto "PufferfishManage">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0d0a14 0%, #1a0a28 50%, #0d0a14 100%); min-height: 100vh; padding: 20px; color: #d4c4f0;"> <div style="max-width: 720px; margin: 0 auto; padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0f0a1a 100%); border-radius: 15px; border: 2px solid #ff8fc8; box-shadow: 0 0 25px rgba(255,143,200,0.25);"> <<set _isCerberus = $activeTransformation === "Cerberus">> <<if _isCerberus>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <</if>> <h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">A Long Hour with Ren</h2> <<if _isCerberus>> <p>Ren is waiting for you in the staff lounge, one ankle crossed over the other on the back of the couch, sipping something dark out of a coffee cup. She doesn't look up when you walk in. She doesn't have to. "Lock the door," she says, "all three of you, if it takes all three of you," and only then does she glance over, taking in the three heads on their three necks without so much as a blink. "Well. That is going to make my night more interesting."</p> <p>You lock the door. You sit, because she tells you to, and Ren sets the cup down with the deliberate slowness of a woman who has all night and slides off the couch and steps between your knees. She studies all three faces in turn, reading each one, deciding how she is going to take it apart.</p> <p><span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> holds her gaze, unimpressed by the theater. "You sent for me."<<elseif _pCenter.flirty>><<print _nCenter>> gives her a slow, teasing smile. "You sent for me. All of me, apparently."<<else>><<print _nCenter>> meets her eyes evenly. "You sent for me."<</if>></span></p> <p>"I sent a hint," Ren says, smiling. "A strong one. I do like watching you read me. Tonight, though, I get to read you. Three times over." She unbuttons her uniform one button at a time, in no rush at all, watching each face to learn what each one gives away.</p> <p> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> bristles at being handled, jaw tight, and Ren only smiles wider and tips her gently aside with two fingers. "No. Tonight you sit. Tonight I work."<<elseif _pLeft.bitchy>><<print _nLeft>> sneers, "You think you can manage all of us?" and Ren answers by catching her under the chin and kissing the smart mouth quiet.<<elseif _pLeft.confident>><<print _nLeft>> meets her stare for stare, certain she can outlast her, which Ren takes as a personal challenge.<<else>><<print _nLeft>> leans into her hand the moment she offers it.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> goes pliant under the first brush of her mouth, already melting, and Ren hums approval against her throat.<<elseif _pRight.awkward>><<print _nRight>> doesn't know where to look and ends up staring at the ceiling until Ren turns her face back to hers with a fingertip. "Eyes on me, sweetheart."<<elseif _pRight.flirty>><<print _nRight>> plays right along, nuzzling into her palm with a grin. "Work away."<<else>><<print _nRight>> lets her tilt her wherever she likes, watching her with quiet interest.<</if>></span> </p> <p>When she finally lowers herself into your lap she is unhurried, and she kisses each head in turn like she has all night, because she does. She undresses you while she works, hands clever and patient, and when any of the three of you tries to take some of it back she catches your wrists and pins them down with a low, amused, "No. Tonight you sit. Tonight I work. That goes for all of you."</p> <p>So you sit. And she works. Ren is, as advertised, sexually skilled in a way that feels more like devotion than performance, and now she has three times the canvas. She maps each head by its own nature. She figures out, across a slow patient hour, exactly which combinations undo each one, and then she does each of them, in order, attentive to all three at once.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> fights to stay composed and loses, by degrees, until she is saying her name with no particular dignity.<<elseif _pCenter.professional>><<print _nCenter>> tries to keep her face neutral and fails utterly under her patient hands.<<else>><<print _nCenter>> comes apart slow and helpless, exactly the way she planned.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>>, so proud a moment ago, breaks into ragged gasps despite herself while Ren watches, satisfied.<<elseif _pLeft.bitchy>><<print _nLeft>> runs out of clever things to say and settles for swearing softly into her hair.<<elseif _pLeft.energetic>><<print _nLeft>> strains toward her, greedy and loud, and she rewards her for every honest sound.<<else>><<print _nLeft>> trembles under her, undone.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> melts entirely, following wherever she leads, grateful and slack-jawed.<<elseif _pRight.awkward>><<print _nRight>> stops fumbling at last and just feels, mouth open, every shy worry forgotten.<<elseif _pRight.kind>><<print _nRight>> whispers her name like thanks each time she pulls another sound out of her.<<else>><<print _nRight>> goes boneless and pliant against her.<</if>></span> </p> <p>Afterwards she stretches out against the middle of you, finally still, one hand resting up to keep each outer head close, and lets you stroke her hair with whichever of the three of you can still manage it. "There," she murmurs, smug as a cat with three saucers of cream. "That wasn't so hard."</p> <<else>> <p>Ren is waiting for you in the staff lounge, one ankle crossed over the other on the back of the couch, sipping something dark out of a coffee cup. She doesn't look up when you walk in.</p> <p>"Lock the door," she says.</p> <p>You do.</p> <p>"Sit."</p> <p>You do that too. Ren sets the cup down with the deliberate slowness of a woman who has all night, and slides off the couch, and steps between your knees without ever quite touching you. You can smell her perfume. You can hear her breathing.</p> <p>"You came," she says. "I wasn't sure you would."</p> <p>"You sent for me."</p> <p>"I sent a hint."</p> <p>"It was a strong hint."</p> <p>"Mm." She smiles. "I do like watching you read me."</p> <p>She unbuttons her uniform one button at a time. She is in no rush. She watches your face as she does it, gauging exactly when your breathing shifts, and adjusts her pace to keep you exactly there. Ren has been doing this longer than you have been able to sit still, and you can tell.</p> <p>When she finally lowers herself into your lap she is unhurried. She kisses you like she has all night. She undresses you while she does it, hands clever and unrushed, and when you try to take any of it back she catches your wrists and pins them against the couch with a low, amused, "No. Tonight you sit. Tonight I work."</p> <p>So you sit. And she works. Ren is, as advertised, sexually skilled in a way that feels more like devotion than performance. She maps you. She figures out, in the space of a slow patient hour, exactly which combinations make you come apart, and then she does each of them, in order, until you are trembling and slack-jawed and saying her name with no particular dignity. She watches the whole time, satisfied.</p> <p>Afterwards she curls against you, finally still, and lets you stroke her hair. "There," she murmurs. "That wasn't so hard."</p> <</if>> <<run setup.advancetime ? setup.advancetime(120) : (State.variables.timeInMinutes = (State.variables.timeInMinutes || 0) + 120)>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); border: 2px solid #c9a9ff; color: #ffffff; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Leave her smug and well-pleased</div>">> <<goto "PufferfishManage">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #0d0a14 0%, #1a0a28 50%, #0d0a14 100%); min-height: 100vh; padding: 20px; color: #d4c4f0;"> <div style="max-width: 720px; margin: 0 auto; padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0f0a1a 100%); border-radius: 15px; border: 2px solid #ff8fc8; box-shadow: 0 0 25px rgba(255,143,200,0.25);"> <<set _isCerberus = $activeTransformation === "Cerberus">> <<if _isCerberus>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <</if>> <h2 style="color: #ff8fc8; text-align: center; margin: 0 0 18px 0;">An Hour in Clover's Arms</h2> <<if _isCerberus>> <p>Clover is in the office when you come in, and she takes one look at the three of you and stands up, and that's the end of the office work for the night. "Oh, sweetheart," she says, taking in all three heads on their three necks without a flicker of alarm, the way she takes in everything, like it is simply one more thing to gather up and hold. "Oh, all three of you. Come here." And that's all the warning you get before she has you, all of her, soft and warm and half a foot taller than you remembered, folding every head against her at once.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> means to stay in charge of this and gets out, "I came to see you," in a level voice before she lets Clover tuck her under her chin.<<elseif _pCenter.flirty>><<print _nCenter>> grins up at her. "You missed me. All of me."<<else>><<print _nCenter>> presses into the warmth of her without a word.<</if>></span> </p> <p>"I did miss you," she says, easy and certain, and walks the three of you backwards, slow, until your back hits the wall. She just looks at each face in turn, smiling the way she does, like you are the best small thing that has happened to her this week, three times over. Then she gathers each head close and gentles it her own way.</p> <p> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> bristles at being handled, jaw set, and Clover only smiles and cradles her anyway, patient as the tide, until the set jaw goes soft against her palm. "There. I've got you. You don't have to run anything tonight."<<elseif _pLeft.bitchy>><<print _nLeft>> opens her mouth to say something sharp, and Clover kisses her warm and slow until whatever it was dissolves into a grudging little sigh.<<elseif _pLeft.awkward>><<print _nLeft>> doesn't know what to do with this much tenderness and goes pink and quiet, and Clover soothes her with one hand at her cheek. "Shh. You're alright. I've got you."<<else>><<print _nLeft>> leans into her the moment she offers, eyes already half-closed.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.flirty>><<print _nRight>> nuzzles into the warm slope of her and teases, "Is there enough of you to go around?" and Clover laughs low. "Always, sweetheart."<<elseif _pRight.submissive>><<print _nRight>> melts the instant she draws her in, going pliant and grateful against her warmth.<<elseif _pRight.awkward>><<print _nRight>> stammers something and loses the words halfway, and Clover hushes her gently into the crook of her neck.<<else>><<print _nRight>> settles where Clover puts her, watching her with quiet trust.<</if>></span> </p> <p>She kisses each head the way she does everything, generous and unhurried and with her whole self, and you stop thinking about the office immediately, all three of you. She undresses you on the office couch with the careless competence of a woman who has done this many times. She undresses herself afterwards because she likes you to watch. There is a great deal of her. She is comfortable with all of it, and with all of you.</p> <p>"Come here, all of you," she says, drawing the three heads down across her chest, and there is more than enough of her to gather every mouth to where she is offering. The slow warm slide of her milk is exactly what she is gently demanding each of you take, one head and then the next and then the first again, never hurried, never short. She strokes whichever hair her free hand can reach while you nurse, her other hand between your legs, patient, knowing.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>>, so determined to stay in command, gives it up by slow degrees and just nurses, slack and quiet, exactly as Clover meant her to.<<else>><<print _nCenter>> goes warm and boneless against her, every thought gone soft.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>>, so proud a moment ago, breaks into soft helpless sounds against her, every edge worn smooth.<<elseif _pLeft.bitchy>><<print _nLeft>> runs clean out of sharp things to say and just drinks, eyes closed, finally quiet.<<elseif _pLeft.awkward>><<print _nLeft>>, shy a moment ago, forgets to be shy at all, mouth soft, every worry gentled out of her.<<else>><<print _nLeft>> nurses slow and content, undone by her warmth.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.flirty>><<print _nRight>> has nothing teasing left in her, just a low grateful hum against her skin as she works you to the first crest.<<elseif _pRight.submissive>><<print _nRight>> follows wherever she leads, grateful and slack-jawed, melting as she works you to the first crest.<<elseif _pRight.kind>><<print _nRight>> murmurs a soft thanks into her warmth each time she pulls another sound out of you.<<else>><<print _nRight>> goes pliant and quiet, drinking her in.<</if>></span> </p> <p>She doesn't stop stroking when she works you to the first crest, doesn't stop when she works you to the second, just murmurs, "Yes, sweethearts, that's it, all of you, just like that," and lets every head fall apart against her at once without ever losing the rhythm of her hand.</p> <p>By the time she finally lets you up, all three of you are wrung out and milk-drunk and barely able to form a single sentence between you. Clover smiles, lazy and satisfied, and pulls a blanket over the whole tangle of you on the office couch.</p> <p>"Sleep," she says, one hand cupped to keep each outer head close. "I'll be right here."</p> <<else>> <p>Clover is in the office when you come in, and she takes one look at you and stands up, and that's the end of the office work for the night. "Oh, sweetheart," she says, and that's all the warning you get before she's holding you, all of her, soft and warm and half a foot taller than you remembered she was.</p> <p>"Hi," she murmurs, mouth at your hair.</p> <p>"Hi."</p> <p>"You came to see me."</p> <p>"I did."</p> <p>She walks you backwards, slow, easy, until your back hits the wall, and there she stops and just looks at you for a moment, smiling the way she does, like you are the best small thing that has happened to her this week. Then she kisses you. Clover kisses like she does everything, generous and unhurried and with her whole self, and you stop thinking about the office immediately.</p> <p>She undresses you on the office couch with the careless competence of a woman who has done this many times. She undresses herself afterwards because she likes you to watch. There is a great deal of her. She is comfortable with all of it.</p> <p>"Come here," she says, pulling you down across her chest, and when you put your mouth where she is offering, the slow warm slide of her milk is exactly what she is gently demanding you take. She strokes your hair while you nurse. Her other hand is between your legs, patient, knowing, and she doesn't stop stroking your hair when she works you to the first crest, doesn't stop when she works you to the second, just murmurs, "Yes, sweetheart, that's it, just like that," and lets you fall apart against her without ever once losing the rhythm of her hand.</p> <p>By the time she finally lets you up, you are wrung out and milk-drunk and barely able to form sentences. Clover smiles, lazy and satisfied, and pulls a blanket over both of you on the office couch.</p> <p>"Sleep," she says. "I'll be right here."</p> <</if>> <<run setup.advancetime ? setup.advancetime(150) : (State.variables.timeInMinutes = (State.variables.timeInMinutes || 0) + 150)>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); border: 2px solid #c9a9ff; color: #ffffff; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Sleep against her chest</div>">> <<goto "PufferfishManage">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _master = (setup.identity && setup.identity.isPlayerMasterRecognized) ? setup.identity.isPlayerMasterRecognized() : true>> <div style="background: linear-gradient(180deg, #0d0a14 0%, #1a0a28 50%, #0d0a14 100%); min-height: 100vh; padding: 20px; color: #d4c4f0;"> <div style="max-width: 720px; margin: 0 auto; padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0f0a1a 100%); border-radius: 15px; border: 2px solid #c9a9ff; box-shadow: 0 0 25px rgba(201,169,255,0.25);"> <<set _isCerberus = $activeTransformation === "Cerberus">> <<if _isCerberus>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <</if>> <<if _master>> <h2 style="color: #c9a9ff; text-align: center; margin: 0 0 18px 0;">Bun Bun, Devoted</h2> <<if _isCerberus>> <p>Bun Bun is waiting for you in your room when you arrive. She is on her knees by the bed, posture perfect, hands folded in her lap, ears tipped forward. She looks up when you walk in, and her breath catches at the three heads on their three necks, but she does not flinch and she does not break her posture. She simply waits, eyes moving from one face to the next, to be told.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> speaks first, low and certain. "Stand up."<<elseif _pCenter.flirty>><<print _nCenter>> gives her a slow smile. "Stand up, sweet thing. All of us want a look at you."<<else>><<print _nCenter>> meets her eyes evenly. "Stand up."<</if>></span> </p> <p>She stands, a little out of breath already, just from the discipline of the wait. She does not ask which of you she belongs to tonight. She has decided it is all of you.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.kind>><<print _nCenter>> takes her face in both hands and kisses her slow and gentle, the way she likes it. "Good girl. Hands at your sides until I say."<<elseif _pCenter.dominant>><<print _nCenter>> takes her face in both hands and kisses her deep and deliberate. "Hands at your sides. You wait for me."<<else>><<print _nCenter>> takes her face in both hands and kisses her slow and deliberate, the way she likes it. "Hands down until I say."<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.bitchy>><<print _nLeft>> tips her chin up with two fingers and smirks. "Look at you, already trembling. Pathetic. Keep it up."<<elseif _pLeft.dominant>><<print _nLeft>> turns her head with a hand at her jaw and claims her mouth next, hungry and possessive. "Mine too. Hold still."<<elseif _pLeft.flirty>><<print _nLeft>> leans down to murmur at her ear, "You waited so prettily for us," and grazes her teeth along the lobe until she shivers.<<else>><<print _nLeft>> presses a slow kiss to the corner of her mouth, taking her turn.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.kind>><<print _nRight>> brushes her cheek and soothes, "You're doing so well. We've got you, all of us."<<elseif _pRight.submissive>><<print _nRight>> nuzzles softly at her temple, gentler than the others, content to share.<<elseif _pRight.confident>><<print _nRight>> tilts her face up by the chin and studies her like something earned. "Yes. You'll do nicely for all three of us."<<else>><<print _nRight>> kisses along her throat, slow, taking her own measure of her.<</if>></span> </p> <p>"You may," <<print _nCenter>> murmurs against her mouth, and she makes a small relieved sound and her hands come up at last, careful, reverent, reaching to hold whatever of you she can. There is more of you than she is used to, and she takes to that quickly, a hand at one waist, her mouth turned up to another, ears flushed pink.</p> <p>It goes the way Bun Bun likes it to go. You lead, all three of you, and she follows. You undress her piece by piece between the three of you and she lets you, lets you take in every inch of the discipline-built body she has spent so long shaping, and when you finally lay her down on the bed she says, very quietly, "Master," to each face in turn, and the word lands somewhere warm in all of you.</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> sets the pace and makes her wait, telling her in a low steady voice exactly how good she is being.<<elseif _pCenter.kind>><<print _nCenter>> takes her apart slow and patient, kissing every place she trembles.<<else>><<print _nCenter>> takes her apart slowly, deliberate, drawing it out the way she likes.<</if>></span><br> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.dominant>><<print _nLeft>> makes her ask for it, twice, growling soft praise each time she begs. "Again. Properly this time."<<elseif _pLeft.bitchy>><<print _nLeft>> makes her beg and laughs low when she does. "Look how needy. Ask nicer."<<elseif _pLeft.flirty>><<print _nLeft>> teases her right to the edge and holds her there, grinning. "Not yet. Ask me again."<<else>><<print _nLeft>> works her higher, unhurried, making her wait for it.<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.kind>><<print _nRight>> whispers reassurance against her skin the whole time. "You're allowed. Whenever you're ready. We've got you."<<elseif _pRight.submissive>><<print _nRight>> presses worship to the line of her hip, following the others' lead.<<else>><<print _nRight>> adds her own slow attention, sharing her between the three of you.<</if>></span> </p> <p>You make her wait. You make her ask, twice, before you give her what she has been begging for since you walked in, and when you finally do, she comes apart with her mouth pressed against one shoulder and a hand fisted at another, gasping the word like a prayer she is finally allowed to speak to all three of you at once.</p> <p>Afterwards she curls into the middle of you, smaller than she ever lets herself look in public, one hand resting up to keep each outer head close. "Thank you," she whispers, to each face in turn. "Thank you. Thank you." You stroke her ears with whichever of you can still manage it until she goes quiet.</p> <p>"Stay with me tonight," she says, almost too low to catch. "All of you."</p> <p>"We will," <<print _nCenter>> tells her.</p> <<else>> <p>Bun Bun is waiting for you in your room when you arrive. She is on her knees by the bed, posture perfect, hands folded in her lap, ears tipped forward. She does not say hello. She just looks up at you when you walk in and waits to be told.</p> <p>"Stand up," you say, because you can tell that's what she is waiting for.</p> <p>She stands. She is a little out of breath already, just from the discipline of the wait. You take her face in both hands and kiss her, slow, deliberate, the way she likes you to. Her eyes flutter shut. Her hands stay at her sides until you give her permission.</p> <p>"You may," you murmur against her mouth, and she makes a small relieved sound and her hands come up at last, careful, reverent, on your hips.</p> <p>It goes the way Bun Bun likes it to go. You lead. She follows. You undress her piece by piece and she lets you, lets you take in every inch of the discipline-built body she has spent so long shaping, and when you finally lay her down on the bed she says, very quietly, "Master," and the word lands somewhere warm in your chest.</p> <p>You take her apart slowly. You make her wait. You make her ask, twice, before you give her what she has been begging for since you walked in, and when you finally do, she comes apart with her mouth pressed against your shoulder, gasping your name like a prayer she is finally allowed to speak.</p> <p>Afterwards she curls against your chest, smaller than she ever lets herself look in public. "Thank you," she whispers. "Thank you. Thank you." You stroke her ears until she goes quiet.</p> <p>"Stay with me tonight," she says, almost too low to catch.</p> <p>"I will."</p> <</if>> <<else>> <<set _maidName = (setup.identity && setup.identity.getInhabitedMaid) ? setup.identity.getInhabitedMaid() : null>> <h2 style="color: #c9a9ff; text-align: center; margin: 0 0 18px 0;">Bun Bun, Curious</h2> <<if _isCerberus>> <p>Bun Bun opens the door. Her ears tilt at the wrong angle for a second, the way they always do when she is trying to place something she half-knows, and then her gaze travels up the three necks to the three faces above them and stops. She does not slam the door. She tips her head, more puzzled than afraid, and her eyes move slowly from one head to the next.</p> <p>"<<if _maidName>><<= _maidName>><<else>>You<</if>>," she says, careful. "You feel different tonight. All three of you."</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.flirty>><<print _nCenter>> gives her a slow, teasing smile. "Different is one word for it. Let us in?"<<elseif _pCenter.dominant>><<print _nCenter>> holds her gaze, unhurried. "Different. Let us in."<<else>><<print _nCenter>> meets her eyes softly. "Different. But not unkind. May we come in?"<</if>></span> </p> <p>You step into her room, and she lets you in, all three of you, and when you reach for her she comes the way the body she's looking at always comes to her, easy, familiar. Her hands are on your waist before she's quite decided whether to let them be, and her eyes keep flicking up, fascinated, to the faces she half-recognizes.</p> <p>"You smell like someone I know," she murmurs, mouth at one throat, then turning to the next. "But you also smell like someone I don't. Three someones. I can't decide."</p> <p> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.bitchy>><<print _nLeft>> smirks and tips her chin up. "Then stop trying to decide and pay attention."<<elseif _pLeft.confident>><<print _nLeft>> leans in, sure of herself. "Don't decide. Just be curious."<<elseif _pLeft.flirty>><<print _nLeft>> brushes her mouth along the edge of her ear. "Don't decide. We won't tell."<<else>><<print _nLeft>> murmurs against her jaw, "Don't decide. Just tonight."<</if>></span><br> <span @style="'color: ' + _cRight + ';'"><<if _pRight.awkward>><<print _nRight>> manages, a little shy, "We're, um, strangers tonight. If you want," which makes her smile against her skin.<<elseif _pRight.kind>><<print _nRight>> soothes gently, "Only as much as you want, okay? We'll be whoever you need tonight."<<else>><<print _nRight>> nuzzles in close. "Strangers, then. Just for tonight."<</if>></span> </p> <p>"Mm." She kisses each of you in turn. It is not the way she kisses her master. It is gentler, more exploratory, a woman trying to work out a puzzle with her mouth, three times over. "Just for tonight, then. We'll be strangers. You'll forgive me if I'm a little curious."</p> <p>What follows is curious indeed. Bun Bun, without the discipline she usually wears, is softer. Slower. She maps the body you are wearing, and the three heads atop it, as if she has never quite seen any of it from this angle, and you, riding inside it, feel things from inside that the body's owner would have known how to ask for and you, only borrowing, do not. Bun Bun figures most of it out anyway, learning each head as she goes, what makes one go quiet and another go greedy. She is good at this. She likes the puzzle, and now there is three times as much of it.</p> <p>It is good. It is not what she gives her master. But it is good in its own way, the way a stranger you trust can be, and afterwards she curls against the body you have borrowed, one hand drifting up to rest against each outer head, and says, very softly, "I should miss him. I'm not sure I do, tonight, with all of you here. Is that bad?"</p> <p> <span @style="'color: ' + _cCenter + ';'"><<if _pCenter.kind>><<print _nCenter>> murmurs into her hair, "No. Not bad at all."<<else>><<print _nCenter>> tells her, mouth at her hair, "No."<</if>></span> </p> <p>"Good," she murmurs, half-asleep already. "Stay. All of you."</p> <<else>> <p>Bun Bun opens the door. Her ears tilt at the wrong angle for a second, the way they always do when she is trying to place something she half-knows.</p> <p>"<<if _maidName>><<= _maidName>><<else>>You<</if>>," she says, careful. "You feel different tonight."</p> <p>You don't answer with words. You step into her room, and she lets you in, and when you reach for her she comes the way the body she's looking at always comes to her, easy, familiar. Her hands are on your waist before she's quite decided whether to let them be.</p> <p>"You smell like someone I know," she murmurs, mouth at your throat. "But you also smell like someone I don't. I can't decide."</p> <p>"Don't decide," you tell her.</p> <p>"Mm." She kisses you. It is not the way she kisses her master. It is gentler, more exploratory, a woman trying to work out a puzzle with her mouth. "Just for tonight, then. We'll be strangers. You'll forgive me if I'm a little curious."</p> <p>What follows is curious indeed. Bun Bun, without the discipline she usually wears around you, is softer. Slower. She maps the body you are wearing as if she has never quite seen it from this angle, and you, riding inside it, feel things from inside that the body's owner would have known how to ask for and you, only borrowing, do not. Bun Bun figures most of it out anyway. She is good at this. She likes the puzzle.</p> <p>It is good. It is not what she gives her master. But it is good in its own way, the way a stranger you trust can be, and afterwards she curls against the body you have borrowed and says, very softly, "I should miss him. I'm not sure I do, tonight. Is that bad?"</p> <p>"No," you tell her, mouth at her hair.</p> <p>"Good," she murmurs, half-asleep already. "Stay."</p> <</if>> <</if>> <<run setup.advancetime ? setup.advancetime(150) : (State.variables.timeInMinutes = (State.variables.timeInMinutes || 0) + 150)>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); border: 2px solid #c9a9ff; color: #ffffff; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Sleep beside her</div>">> <<goto "PufferfishManage">> <</link>> </div> </div> </div> <</nobr>>
<<run setup.maidBonds && setup.maidBonds.ensureState && setup.maidBonds.ensureState()>> <<set _scenes = (setup.maidBonds && setup.maidBonds.drainNotifications) ? setup.maidBonds.drainNotifications() : []>> <<set _vignettes = (setup.maidBonds && setup.maidBonds.drainVignettes) ? setup.maidBonds.drainVignettes() : []>> <<set _inhabited = (setup.identity && setup.identity.getInhabitedMaid) ? setup.identity.getInhabitedMaid() : null>> <<if (_scenes && _scenes.length) || (_vignettes && _vignettes.length)>> <div style="padding: 14px 18px; background: linear-gradient(135deg, #2a1f3a 0%, #1a0a28 100%); border: 2px solid #ff8fc8; border-radius: 10px; margin-bottom: 18px; box-shadow: 0 0 18px rgba(255,143,200,0.3);"> <h3 style="color: #ff8fc8; margin: 0 0 8px 0;">📝 Cafe Notes</h3> <<for _v range _vignettes>> <p style="color: #d4c4f0; font-size: 13px; margin: 6px 0; font-style: italic;"><<= _v.text>></p> <</for>> <<for _s range _scenes>> <<capture _s>> <div style="display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 0; border-top: 1px solid #3a2a4a;"> <span style="color: #d4c4f0; font-size: 13px; flex: 1;"><<= _s.text>></span> <<link "<span style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 4px 10px; border-radius: 4px; font-weight: bold; font-size: 11px;'>Read what happened</span>">> <<set $currentMaidScene = _s.pairKey>> <<set $currentMaidSceneVariant = _s.sceneId>> <<goto "MaidSceneViewer">> <</link>> </div> <</capture>> <</for>> </div> <</if>> <!-- Maid Bonds grid (only shown when at least two canonical maids are hired) --> <<set _hiredMaidSet = []>> <<set _cafeStaffList = ($cafeOwnership && $cafeOwnership.staff) ? $cafeOwnership.staff : []>> <<for _staff range _cafeStaffList>> <<if setup.maidBonds.MAIDS.indexOf(_staff.name) !== -1 && _hiredMaidSet.indexOf(_staff.name) === -1>> <<run _hiredMaidSet.push(_staff.name)>> <</if>> <</for>> <<if _hiredMaidSet.length >= 2>> <div style="background: #1a0f2a; border: 2px solid #c9a9ff; border-radius: 10px; padding: 15px; margin-bottom: 18px;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">💕 Maid Bonds</h3> <p style="color: #b8a8d0; font-size: 12px; margin: 0 0 10px 0; font-style: italic;">How the maids on your staff feel about each other.</p> <<for _pk range setup.maidBonds.PAIRS>> <<capture _pk>> <<set _rel = State.variables.npcToNpcRelationships[_pk]>> <<set _names = _pk.split("_")>> <<if _hiredMaidSet.indexOf(_names[0]) !== -1 && _hiredMaidSet.indexOf(_names[1]) !== -1>> <<set _pts = _rel ? _rel.points : 0>> <<set _typeName = _rel ? (_rel.typeName || _rel.type || "Strangers") : "Strangers">> <<set _color = _rel ? (_rel.color || "#888") : "#888">> <<set _pct = Math.max(0, Math.min(100, Math.floor(_pts / 4)))>> <div style="display: flex; align-items: center; gap: 10px; padding: 6px 0; border-bottom: 1px solid #2a1a3a;"> <span style="color: #d4c4f0; font-size: 13px; min-width: 150px;"><<= _names[0]>> & <<= _names[1]>></span> <div style="flex: 1; height: 8px; background: #0d0518; border-radius: 4px; overflow: hidden; min-width: 60px;"> <div style="width: <<= _pct>>%; height: 100%; background: linear-gradient(90deg, #c9a9ff 0%, #ff8fc8 100%); border-radius: 4px;"></div> </div> <span style="color: <<= _color>>; font-size: 12px; min-width: 90px; text-align: right; text-transform: capitalize;"><<= _typeName>></span> <<if _rel && _rel.sexualUnlocked>> <span style="color: #ff8fc8; font-size: 11px; min-width: 50px; text-align: center;" title="Sexual relationship unlocked">💞</span> <<else>> <span style="min-width: 50px;"> </span> <</if>> </div> <</if>> <</capture>> <</for>> </div> <</if>> <!-- Inhabiting-maid sex card: when player is in a maid body, show partners she has unlocked --> <<if _inhabited>> <<set _inhabKey = _inhabited>> <<set _partners = []>> <<for _ip range setup.maidBonds.PAIRS>> <<if _ip.indexOf(_inhabKey) !== -1>> <<set _ipRel = State.variables.npcToNpcRelationships[_ip]>> <<if _ipRel && _ipRel.sexualUnlocked>> <<set _other = _ip.split("_")[0] === _inhabKey ? _ip.split("_")[1] : _ip.split("_")[0]>> <<run _partners.push({ name: _other, key: _ip })>> <</if>> <</if>> <</for>> <<if _partners.length>> <div style="background: linear-gradient(135deg, #2a1a4a 0%, #1a0a28 100%); border: 2px solid #ff8fc8; border-radius: 10px; padding: 15px; margin-bottom: 18px;"> <h3 style="color: #ff8fc8; margin: 0 0 8px 0;">💞 In <<= _inhabKey>>'s skin</h3> <p style="color: #d4c4f0; font-size: 13px; margin: 0 0 8px 0; font-style: italic;">She has lovers. They are waiting for the body you are wearing.</p> <div style="display: flex; flex-direction: column; gap: 6px;"> <<for _p range _partners>> <<capture _p>> <<link "<div style='background: #15101e; border: 1px solid #ff8fc8; color: #d4c4f0; padding: 8px 14px; border-radius: 6px; cursor: pointer; font-size: 13px;'>Visit <<= _p.name>> tonight</div>">> <<set $currentMaidScene = _p.key>> <<set $currentMaidSceneVariant = "player">> <<goto "MaidSceneViewer">> <</link>> <</capture>> <</for>> </div> </div> <</if>> <</if>> <!-- Player-maid sex cards (lover tier required) --> <<set _romanceLevels = State.variables.npcRomance || {}>> <<set _maids = ["Mochi", "Ren", "Clover", "Bun Bun"]>> <<set _availableMaids = []>> <<for _m range _maids>> <<set _r = _romanceLevels[_m]>> <<if _r && _r.points >= 350>> <<run _availableMaids.push(_m)>> <</if>> <</for>> <<if _availableMaids.length>> <div style="background: #1a0f2a; border: 2px solid #ff8fc8; border-radius: 10px; padding: 15px; margin-bottom: 18px;"> <h3 style="color: #ff8fc8; margin: 0 0 8px 0;">💕 Spend the night with</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _am range _availableMaids>> <<capture _am>> <<set _passageName = "PlayerSex_" + (_am === "Bun Bun" ? "BunBun" : _am)>> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 8px 14px; border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: bold;'><<= _am>></div>">> <<goto _passageName>> <</link>> <</capture>> <</for>> </div> </div> <</if>>
<<run setup.bunBunSleep.ensureState()>> <<set _s = State.variables.bunBunSleepState>> <div style="background: linear-gradient(180deg, #0d0a14 0%, #1a0a28 50%, #0d0a14 100%); min-height: 100vh; padding: 20px; color: #d4c4f0;"> <div id="bunbun-sleep-root" style="max-width: 720px; margin: 0 auto; padding: 25px; background: linear-gradient(135deg, #1a0f2a 0%, #0f0a1a 100%); border-radius: 15px; border: 2px solid #c9a9ff; box-shadow: 0 0 25px rgba(201,169,255,0.25);"> <<if !_s.currentScenario>> <<run setup.bunBunSleep.startScene()>> <<set _s = State.variables.bunBunSleepState>> <</if>> <<if !_s.currentMood>> <<include "BunBunSleepMoodPicker">> <<else>> <<include "BunBunSleepBeat">> <</if>> </div> </div>
<<set _s = State.variables.bunBunSleepState>> <<set _flavorOpenerObj = setup.bunBunSleep.FLAVOR_OPENERS[_s.flavor] || setup.bunBunSleep.FLAVOR_OPENERS.master>> <<set _intro = setup.bunBunSleep.getScenarioIntro(_s.currentScenario)>> <h2 style="color: #ff8fc8; text-align: center; margin: 0 0 12px 0;"><<= setup.bunBunSleep.SCENARIO_TITLES[_s.currentScenario]>></h2> <<if _s.flavor === "maid">> <p style="color: #ff8fc8; font-size: 13px; font-style: italic; margin: 0 0 14px 0; padding: 8px 12px; background: #2a1f3a; border-left: 3px solid #ff8fc8; border-radius: 4px;">Your consciousness rides shotgun in <<= setup.identity.getInhabitedMaid()>>'s body. The skin is hers. The wanting is yours. She reads only the body.</p> <<elseif _s.flavor === "stranger">> <p style="color: #ff8fc8; font-size: 13px; font-style: italic; margin: 0 0 14px 0; padding: 8px 12px; background: #2a1f3a; border-left: 3px solid #ff8fc8; border-radius: 4px;">She does not know your old self. She fell for the body you are wearing now. Tonight goes on those terms.</p> <</if>> <<if _intro>> <p style="color: #d4c4f0; font-size: 14px; line-height: 1.6; margin: 0 0 14px 0; font-style: italic;"><<= _intro>></p> <</if>> <p style="color: #b8a8d0; font-size: 13px; margin: 0 0 14px 0;">How do you want this to go?</p> <div style="display: grid; gap: 10px;"> <<for _opt range setup.bunBunSleep.getMoodOptions()>> <<capture _opt>> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 8px; padding: 12px 16px; cursor: pointer;'><div style='color: #ff8fc8; font-size: 15px; font-weight: bold;'><<= _opt.label>></div><div style='color: #b8a8d0; font-size: 12px; margin-top: 3px;'><<= _opt.blurb>></div></div>">> <<run setup.bunBunSleep.setMood(_opt.id)>> <<replace "#bunbun-sleep-root">><<include "BunBunSleepBeat">><</replace>> <</link>> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 18px;"> <<link "<div style='display: inline-block; color: #888; padding: 6px 14px; cursor: pointer; font-size: 12px;'>Not tonight, actually</div>">> <<set State.variables.bunBunSleepState.currentScenario = null>> <<set State.variables.bunBunSleepState.currentMood = null>> <<goto "StudioBedroom">> <</link>> </div>
<<set _s = State.variables.bunBunSleepState>> <<set _beat = setup.bunBunSleep.getCurrentBeat()>> <<if !_beat>> <<include "BunBunSleepClosing">> <<else>> <h3 style="color: #c9a9ff; margin: 0 0 6px 0; text-align: center;"><<= _beat.header>></h3> <<if _s._lastProse>> <div style="background: #15101e; border: 1px solid #3a2a4a; border-radius: 8px; padding: 12px 16px; margin-bottom: 14px;"> <p style="color: #d4c4f0; font-size: 14px; line-height: 1.65; margin: 0;"><<= _s._lastProse>></p> </div> <</if>> <p style="color: #b8a8d0; font-size: 13px; margin: 8px 0 8px 0; text-align: center;">What do you do?</p> <div style="display: grid; gap: 8px;"> <<for _act range _beat.actions>> <<capture _act>> <<set _isSoul = !!_act.soulmate>> <<if _isSoul>> <<link "<div style='background: linear-gradient(135deg, #2a1a4a 0%, #1a0a28 100%); border: 1px solid #ff8fc8; border-radius: 6px; padding: 10px 14px; cursor: pointer;'><span style='color: #ff8fc8; font-size: 13px;'>💞 <<= _act.label>></span></div>">> <<set _result = setup.bunBunSleep.takeAction(_act.id)>> <<set State.variables.bunBunSleepState._lastProse = _result.prose>> <<replace "#bunbun-sleep-root">><<include "BunBunSleepBeat">><</replace>> <</link>> <<else>> <<link "<div style='background: #15101e; border: 1px solid #c9a9ff; border-radius: 6px; padding: 10px 14px; cursor: pointer;'><span style='color: #d4c4f0; font-size: 13px;'><<= _act.label>></span></div>">> <<set _result = setup.bunBunSleep.takeAction(_act.id)>> <<set State.variables.bunBunSleepState._lastProse = _result.prose>> <<replace "#bunbun-sleep-root">><<include "BunBunSleepBeat">><</replace>> <</link>> <</if>> <</capture>> <</for>> </div> <</if>>
<<set _s = State.variables.bunBunSleepState>> <<set _result = setup.bunBunSleep.endScene()>> <<if _s._lastProse>> <div style="background: #15101e; border: 1px solid #3a2a4a; border-radius: 8px; padding: 12px 16px; margin-bottom: 14px;"> <p style="color: #d4c4f0; font-size: 14px; line-height: 1.65; margin: 0;"><<= _s._lastProse>></p> </div> <</if>> <<set State.variables.bunBunSleepState._lastProse = null>> <div style="background: linear-gradient(135deg, #2a1f3a 0%, #1a0a28 100%); border: 1px solid #ff8fc8; border-radius: 8px; padding: 14px 18px; margin-bottom: 18px; box-shadow: 0 0 12px rgba(255,143,200,0.2);"> <p style="color: #d4c4f0; font-size: 14px; line-height: 1.65; margin: 0;"><<= _result.closing>></p> </div> <<run advanceTime(480)>> <<run setup.removeDebuff && setup.removeDebuff("exhaustion")>> <<run setup.removeDebuff && setup.removeDebuff("dive_injury")>> <<if !setup.hasSleepImmunity || !setup.hasSleepImmunity()>> <<run setup.addBuff && setup.addBuff("well_rested", 480)>> <</if>> <div style="text-align: center; margin-top: 18px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #6a4a9a 0%, #4a2a7a 100%); border: 2px solid #c9a9ff; color: #ffffff; padding: 10px 24px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Wake up</div>">> <<goto "StudioBedroom">> <</link>> </div>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <<set _sm = $miningLastSummary>> <div style="background: #1a1a1a; padding: 20px; min-height: 100vh;"> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #3a2a10; border: 2px solid #8a6a3a; color: #d4a060; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Quarry</div>">><<goto "IndustrialOutskirts">><</link>></div> <div style="background: #2a1f10; border: 3px solid #8a6a3a; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #d4a060; margin: 0 0 10px 0;">⛏ Outskirts Quarry</h2> <p style="color: #ccc; margin: 0;">A scaffolded shaft on the edge of the industrial yards. Three levels of stone to dig through. Watch for gas pockets.</p> </div> <<if $miningFlags && $miningFlags.starterJustGifted>> <div style="background: #3a2a1a; border: 2px solid #d4a060; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #ffd080; margin: 0 0 6px 0;">🎁 Site foreman tosses you a Rusty Pickaxe</h3> <p style="color: #d4c4a0; margin: 0; font-size: 13px;">"Take it. Too many in the shed. Whatever you find is yours."</p> </div> <<run delete State.variables.miningFlags.starterJustGifted>> <</if>> <<if _sm>> <div style="background: <<if _sm.ejected>>#3a1a1a<<else>>#1a3a1a<</if>>; border: 2px solid <<if _sm.ejected>>#c06060<<else>>#6aa66a<</if>>; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <<if _sm.ejected>> <h3 style="color: #ff8a8a; margin: 0 0 6px 0;">⚠ Forced out by <<= _sm.hazardLabel>></h3> <p style="color: #f0d0d0; margin: 0; font-size: 13px;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <<else>> <h3 style="color: #aae88a; margin: 0 0 6px 0;">✓ Run complete (Floor <<= _sm.floorReached>>)</h3> <p style="color: #d0f0d0; margin: 0; font-size: 13px;">Banked: <<= setup.mining._fmtLoot(_sm.banked)>></p> <</if>> </div> <<run State.variables.miningLastSummary = null>> <</if>> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 4px 0;"><strong>Mining:</strong> Lvl <<= $miningSkill.level>> (<<= $miningSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None<</if>></p> <<set _en = Math.floor(setup.mining._currentEnergy())>><<set _enMax = setup.mining._maxEnergy()>><<set _enPct = _en / _enMax>> <<set _enColor = _enPct <= 0.2 ? "#ff8080" : (_enPct <= 0.5 ? "#ffc060" : "#80f0c0")>> <<set _wellRested = typeof setup.hasBuff === "function" && setup.hasBuff("well_rested")>> <<set _exhausted = setup.mining.isExhausted()>> <<set _strikeCost = setup.mining._energyPerStrike()>> <p style="color: #ccc; margin: 4px 0;"><strong>⚡ Energy:</strong> <span style="color: <<= _enColor>>;"><<= _en>> / <<= _enMax>></span> <span style="color: #888; font-size: 12px;">(each strike costs <<= _strikeCost>>)</span></p> <<if _wellRested>><p style="color: #80f0c0; margin: 4px 0; font-size: 13px;">😴 <strong>Well Rested</strong>: strikes cost <<= _strikeCost>> energy instead of <<= setup.mining.ENERGY_PER_STRIKE>>.</p><</if>> <<if _exhausted>><p style="color: #ff8080; margin: 4px 0; font-size: 13px;">⚠ <strong>Exhausted</strong>: too tired to mine. Sleep at home for 6+ hours to clear.</p><</if>> </div> <<set _tfb = setup.mining.getActiveTfBuffs()>> <<if _tfb.sources && _tfb.sources.length>> <div style="background: #2a1a3a; border: 2px solid #c080ff; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #d4a0ff; margin: 0 0 8px 0;">✨ Active Transformation Buffs</h3> <<for _tf range _tfb.sources>> <<if setup.mining.TF_BUFFS[_tf]>> <p style="color: #e8d0ff; margin: 4px 0; font-size: 13px;">• <<= setup.mining.TF_BUFFS[_tf].label>></p> <</if>> <</for>> </div> <</if>> <<set _foods = Object.keys(setup.mining.MINING_FOODS).filter(function(id){ return $giftInventory && ($giftInventory[id] || 0) > 0; })>> <<if _foods.length || _en < _enMax>> <div style="background: #1a2a1a; border: 2px solid #6aa66a; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #aae88a; margin: 0 0 8px 0;">🍴 Restore Energy</h3> <p style="color: #888; font-size: 12px; margin: 0 0 8px 0; font-style: italic;">Eat a snack or sleep 8+ hours at home to refill.</p> <<if _foods.length>> <<for _f range _foods>> <<capture _f>> <<set _amt = setup.mining.MINING_FOODS[_f]>> <<set _name = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].name) || _f>> <<set _icon = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].icon) || "🍴">> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a2a; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _icon>> <<= _name>> (×<<= $giftInventory[_f]>>), +<<= _amt>> energy</span> <<link "Eat">><<run setup.mining.eatForEnergy(_f)>><<goto "OutskirtsQuarryEntrance">><</link>> </div> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 4px 0;">No energy-restoring food on hand.</p> <</if>> </div> <</if>> <<if _eq && !_exhausted && _en >= _strikeCost>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='background: #4a3a1a; border: 3px solid #d4a060; color: #ffd080; padding: 18px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 17px; display: inline-block;'>⛏ Enter the Mine</div>">> <<set _r = setup.mining.startRun("outskirtsQuarry")>> <<if _r.ok>><<goto "MiningGrid">><</if>> <</link>> </div> <<elseif _eq && _exhausted>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too exhausted to mine. Go sleep first.</p> <<elseif _eq>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too tired to swing. Eat or sleep before mining.</p> <</if>> <p style="color: #888; font-style: italic; font-size: 12px; text-align: center;">Each strike costs 3 minutes + <<= _strikeCost>> energy. Numbers on stone tiles show how many hazards are adjacent. Climb out anytime to bank your haul.</p> </div> <</nobr>>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <<set _sm = $miningLastSummary>> <<set _gate = setup.mining.canEnterMine("sandcutMine")>> <div style="background: #1a1208; padding: 20px; min-height: 100vh;"> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #3a2a10; border: 2px solid #c2953a; color: #e0b860; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Mine</div>">><<goto "Desert">><</link>></div> <div style="background: #2a1f10; border: 3px solid #c2953a; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #e0b860; margin: 0 0 10px 0;">🏜 Sandcut Mine</h2> <p style="color: #d4c08c; margin: 0;">A wind-scoured shaft that bores down into hot sandstone. Six floors of brittle stone and shifting sand. Watch for cave-ins.</p> </div> <<if _sm && _sm.mineId === "sandcutMine">> <div style="background: <<if _sm.ejected>>#3a1a1a<<else>>#1a3a1a<</if>>; border: 2px solid <<if _sm.ejected>>#c06060<<else>>#6aa66a<</if>>; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <<if _sm.ejected>> <h3 style="color: #ff8a8a; margin: 0 0 6px 0;">⚠ Forced out by <<= _sm.hazardLabel>></h3> <p style="color: #f0d0d0; margin: 0; font-size: 13px;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <<else>> <h3 style="color: #aae88a; margin: 0 0 6px 0;">✓ Run complete (Floor <<= _sm.floorReached>>)</h3> <p style="color: #d0f0d0; margin: 0; font-size: 13px;">Banked: <<= setup.mining._fmtLoot(_sm.banked)>></p> <</if>> </div> <<run State.variables.miningLastSummary = null>> <</if>> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 4px 0;"><strong>Mining:</strong> Lvl <<= $miningSkill.level>> (<<= $miningSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None<</if>></p> <<set _en = Math.floor(setup.mining._currentEnergy())>><<set _enMax = setup.mining._maxEnergy()>><<set _enPct = _en / _enMax>> <<set _enColor = _enPct <= 0.2 ? "#ff8080" : (_enPct <= 0.5 ? "#ffc060" : "#80f0c0")>> <<set _wellRested = typeof setup.hasBuff === "function" && setup.hasBuff("well_rested")>> <<set _exhausted = setup.mining.isExhausted()>> <<set _strikeCost = setup.mining._energyPerStrike()>> <p style="color: #ccc; margin: 4px 0;"><strong>⚡ Energy:</strong> <span style="color: <<= _enColor>>;"><<= _en>> / <<= _enMax>></span> <span style="color: #888; font-size: 12px;">(each strike costs <<= _strikeCost>>)</span></p> <<if _wellRested>><p style="color: #80f0c0; margin: 4px 0; font-size: 13px;">😴 <strong>Well Rested</strong>: strikes cost <<= _strikeCost>> energy instead of <<= setup.mining.ENERGY_PER_STRIKE>>.</p><</if>> <<if _exhausted>><p style="color: #ff8080; margin: 4px 0; font-size: 13px;">⚠ <strong>Exhausted</strong>: too tired to mine. Sleep at home for 6+ hours to clear.</p><</if>> </div> <<set _tfb = setup.mining.getActiveTfBuffs()>> <<if _tfb.sources && _tfb.sources.length>> <div style="background: #2a1a3a; border: 2px solid #c080ff; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #d4a0ff; margin: 0 0 8px 0;">✨ Active Transformation Buffs</h3> <<for _tf range _tfb.sources>> <<if setup.mining.TF_BUFFS[_tf]>> <p style="color: #e8d0ff; margin: 4px 0; font-size: 13px;">• <<= setup.mining.TF_BUFFS[_tf].label>></p> <</if>> <</for>> </div> <</if>> <<set _foods = Object.keys(setup.mining.MINING_FOODS).filter(function(id){ return $giftInventory && ($giftInventory[id] || 0) > 0; })>> <<if _foods.length || _en < _enMax>> <div style="background: #1a2a1a; border: 2px solid #6aa66a; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #aae88a; margin: 0 0 8px 0;">🍴 Restore Energy</h3> <p style="color: #888; font-size: 12px; margin: 0 0 8px 0; font-style: italic;">Eat a snack or sleep 8+ hours at home to refill.</p> <<if _foods.length>> <<for _f range _foods>> <<capture _f>> <<set _amt = setup.mining.MINING_FOODS[_f]>> <<set _name = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].name) || _f>> <<set _icon = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].icon) || "🍴">> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a2a; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _icon>> <<= _name>> (×<<= $giftInventory[_f]>>), +<<= _amt>> energy</span> <<link "Eat">><<run setup.mining.eatForEnergy(_f)>><<goto "SandcutMineEntrance">><</link>> </div> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 4px 0;">No energy-restoring food on hand.</p> <</if>> </div> <</if>> <<if !_gate.ok>> <div style="background: #2a1a1a; border: 2px solid #c06060; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: center;"> <p style="color: #ffc8c8; margin: 0; font-size: 14px;">⚠ <<= _gate.reason>></p> </div> <<elseif _eq && !_exhausted && _en >= _strikeCost>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='background: #4a3a1a; border: 3px solid #c2953a; color: #ffd080; padding: 18px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 17px; display: inline-block;'>⛏ Enter the Mine</div>">> <<set _r = setup.mining.startRun("sandcutMine")>> <<if _r.ok>><<goto "MiningGrid">><</if>> <</link>> </div> <<elseif _eq && _exhausted>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too exhausted to mine. Go sleep first.</p> <<elseif _eq>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too tired to swing. Eat or sleep before mining.</p> <</if>> <p style="color: #888; font-style: italic; font-size: 12px; text-align: center;">Each strike costs 3 minutes + <<= _strikeCost>> energy. Numbers on stone tiles show how many hazards are adjacent. Climb out anytime to bank your haul.</p> </div> <</nobr>>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <<set _sm = $miningLastSummary>> <<set _gate = setup.mining.canEnterMine("cragsideQuarry")>> <div style="background: #0a0f1a; padding: 20px; min-height: 100vh;"> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #1a2030; border: 2px solid #8B9DAF; color: #a8b8c8; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Quarry</div>">><<goto "Mountains">><</link>></div> <div style="background: #1a2030; border: 3px solid #8B9DAF; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #a8b8c8; margin: 0 0 10px 0;">⛰ Cragside Quarry</h2> <p style="color: #c8d0d8; margin: 0;">A vertical shaft cut into the granite of the high mountains. Eight floors of cold stone laced with veins of silver and emerald. Watch for falling rocks.</p> </div> <<if _sm && _sm.mineId === "cragsideQuarry">> <div style="background: <<if _sm.ejected>>#3a1a1a<<else>>#1a3a1a<</if>>; border: 2px solid <<if _sm.ejected>>#c06060<<else>>#6aa66a<</if>>; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <<if _sm.ejected>> <h3 style="color: #ff8a8a; margin: 0 0 6px 0;">⚠ Forced out by <<= _sm.hazardLabel>></h3> <p style="color: #f0d0d0; margin: 0; font-size: 13px;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <<else>> <h3 style="color: #aae88a; margin: 0 0 6px 0;">✓ Run complete (Floor <<= _sm.floorReached>>)</h3> <p style="color: #d0f0d0; margin: 0; font-size: 13px;">Banked: <<= setup.mining._fmtLoot(_sm.banked)>></p> <</if>> </div> <<run State.variables.miningLastSummary = null>> <</if>> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 4px 0;"><strong>Mining:</strong> Lvl <<= $miningSkill.level>> (<<= $miningSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None<</if>></p> <<set _en = Math.floor(setup.mining._currentEnergy())>><<set _enMax = setup.mining._maxEnergy()>><<set _enPct = _en / _enMax>> <<set _enColor = _enPct <= 0.2 ? "#ff8080" : (_enPct <= 0.5 ? "#ffc060" : "#80f0c0")>> <<set _wellRested = typeof setup.hasBuff === "function" && setup.hasBuff("well_rested")>> <<set _exhausted = setup.mining.isExhausted()>> <<set _strikeCost = setup.mining._energyPerStrike()>> <p style="color: #ccc; margin: 4px 0;"><strong>⚡ Energy:</strong> <span style="color: <<= _enColor>>;"><<= _en>> / <<= _enMax>></span> <span style="color: #888; font-size: 12px;">(each strike costs <<= _strikeCost>>)</span></p> <<if _wellRested>><p style="color: #80f0c0; margin: 4px 0; font-size: 13px;">😴 <strong>Well Rested</strong>: strikes cost <<= _strikeCost>> energy instead of <<= setup.mining.ENERGY_PER_STRIKE>>.</p><</if>> <<if _exhausted>><p style="color: #ff8080; margin: 4px 0; font-size: 13px;">⚠ <strong>Exhausted</strong>: too tired to mine. Sleep at home for 6+ hours to clear.</p><</if>> </div> <<set _tfb = setup.mining.getActiveTfBuffs()>> <<if _tfb.sources && _tfb.sources.length>> <div style="background: #2a1a3a; border: 2px solid #c080ff; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #d4a0ff; margin: 0 0 8px 0;">✨ Active Transformation Buffs</h3> <<for _tf range _tfb.sources>> <<if setup.mining.TF_BUFFS[_tf]>> <p style="color: #e8d0ff; margin: 4px 0; font-size: 13px;">• <<= setup.mining.TF_BUFFS[_tf].label>></p> <</if>> <</for>> </div> <</if>> <<set _foods = Object.keys(setup.mining.MINING_FOODS).filter(function(id){ return $giftInventory && ($giftInventory[id] || 0) > 0; })>> <<if _foods.length || _en < _enMax>> <div style="background: #1a2a1a; border: 2px solid #6aa66a; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #aae88a; margin: 0 0 8px 0;">🍴 Restore Energy</h3> <p style="color: #888; font-size: 12px; margin: 0 0 8px 0; font-style: italic;">Eat a snack or sleep 8+ hours at home to refill.</p> <<if _foods.length>> <<for _f range _foods>> <<capture _f>> <<set _amt = setup.mining.MINING_FOODS[_f]>> <<set _name = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].name) || _f>> <<set _icon = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].icon) || "🍴">> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a2a; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _icon>> <<= _name>> (×<<= $giftInventory[_f]>>), +<<= _amt>> energy</span> <<link "Eat">><<run setup.mining.eatForEnergy(_f)>><<goto "CragsideQuarryEntrance">><</link>> </div> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 4px 0;">No energy-restoring food on hand.</p> <</if>> </div> <</if>> <<if !_gate.ok>> <div style="background: #2a1a1a; border: 2px solid #c06060; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: center;"> <p style="color: #ffc8c8; margin: 0; font-size: 14px;">⚠ <<= _gate.reason>></p> </div> <<elseif _eq && !_exhausted && _en >= _strikeCost>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='background: #2a3a4a; border: 3px solid #8B9DAF; color: #d8e0f0; padding: 18px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 17px; display: inline-block;'>⛏ Enter the Mine</div>">> <<set _r = setup.mining.startRun("cragsideQuarry")>> <<if _r.ok>><<goto "MiningGrid">><</if>> <</link>> </div> <<elseif _eq && _exhausted>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too exhausted to mine. Go sleep first.</p> <<elseif _eq>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too tired to swing. Eat or sleep before mining.</p> <</if>> <p style="color: #888; font-style: italic; font-size: 12px; text-align: center;">Each strike costs 3 minutes + <<= _strikeCost>> energy. Numbers on stone tiles show how many hazards are adjacent. Climb out anytime to bank your haul.</p> </div> <</nobr>>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <<set _sm = $miningLastSummary>> <<set _gate = setup.mining.canEnterMine("frostspire")>> <div style="background: #08111c; padding: 20px; min-height: 100vh;"> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #102030; border: 2px solid #7ec8e3; color: #aee0f5; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Spire</div>">><<goto "Mountains">><</link>></div> <div style="background: #102030; border: 3px solid #7ec8e3; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #aee0f5; margin: 0 0 10px 0;">❄ Frostspire</h2> <p style="color: #c8e0f0; margin: 0;">An ice-bound shaft hammered into the highest peak. Ten floors of frozen rock that bleed cold like a wound. Razor-sharp ice shards lurk in the dark.</p> </div> <<if _sm && _sm.mineId === "frostspire">> <div style="background: <<if _sm.ejected>>#3a1a1a<<else>>#1a3a1a<</if>>; border: 2px solid <<if _sm.ejected>>#c06060<<else>>#6aa66a<</if>>; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <<if _sm.ejected>> <h3 style="color: #ff8a8a; margin: 0 0 6px 0;">⚠ Forced out by <<= _sm.hazardLabel>></h3> <p style="color: #f0d0d0; margin: 0; font-size: 13px;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <<else>> <h3 style="color: #aae88a; margin: 0 0 6px 0;">✓ Run complete (Floor <<= _sm.floorReached>>)</h3> <p style="color: #d0f0d0; margin: 0; font-size: 13px;">Banked: <<= setup.mining._fmtLoot(_sm.banked)>></p> <</if>> </div> <<run State.variables.miningLastSummary = null>> <</if>> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 4px 0;"><strong>Mining:</strong> Lvl <<= $miningSkill.level>> (<<= $miningSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None<</if>></p> <<set _en = Math.floor(setup.mining._currentEnergy())>><<set _enMax = setup.mining._maxEnergy()>><<set _enPct = _en / _enMax>> <<set _enColor = _enPct <= 0.2 ? "#ff8080" : (_enPct <= 0.5 ? "#ffc060" : "#80f0c0")>> <<set _wellRested = typeof setup.hasBuff === "function" && setup.hasBuff("well_rested")>> <<set _exhausted = setup.mining.isExhausted()>> <<set _strikeCost = setup.mining._energyPerStrike()>> <p style="color: #ccc; margin: 4px 0;"><strong>⚡ Energy:</strong> <span style="color: <<= _enColor>>;"><<= _en>> / <<= _enMax>></span> <span style="color: #888; font-size: 12px;">(each strike costs <<= _strikeCost>>)</span></p> <<if _wellRested>><p style="color: #80f0c0; margin: 4px 0; font-size: 13px;">😴 <strong>Well Rested</strong>: strikes cost <<= _strikeCost>> energy instead of <<= setup.mining.ENERGY_PER_STRIKE>>.</p><</if>> <<if _exhausted>><p style="color: #ff8080; margin: 4px 0; font-size: 13px;">⚠ <strong>Exhausted</strong>: too tired to mine. Sleep at home for 6+ hours to clear.</p><</if>> </div> <<set _tfb = setup.mining.getActiveTfBuffs()>> <<if _tfb.sources && _tfb.sources.length>> <div style="background: #2a1a3a; border: 2px solid #c080ff; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #d4a0ff; margin: 0 0 8px 0;">✨ Active Transformation Buffs</h3> <<for _tf range _tfb.sources>> <<if setup.mining.TF_BUFFS[_tf]>> <p style="color: #e8d0ff; margin: 4px 0; font-size: 13px;">• <<= setup.mining.TF_BUFFS[_tf].label>></p> <</if>> <</for>> </div> <</if>> <<set _foods = Object.keys(setup.mining.MINING_FOODS).filter(function(id){ return $giftInventory && ($giftInventory[id] || 0) > 0; })>> <<if _foods.length || _en < _enMax>> <div style="background: #1a2a1a; border: 2px solid #6aa66a; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #aae88a; margin: 0 0 8px 0;">🍴 Restore Energy</h3> <p style="color: #888; font-size: 12px; margin: 0 0 8px 0; font-style: italic;">Eat a snack or sleep 8+ hours at home to refill.</p> <<if _foods.length>> <<for _f range _foods>> <<capture _f>> <<set _amt = setup.mining.MINING_FOODS[_f]>> <<set _name = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].name) || _f>> <<set _icon = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].icon) || "🍴">> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a2a; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _icon>> <<= _name>> (×<<= $giftInventory[_f]>>), +<<= _amt>> energy</span> <<link "Eat">><<run setup.mining.eatForEnergy(_f)>><<goto "FrostspireEntrance">><</link>> </div> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 4px 0;">No energy-restoring food on hand.</p> <</if>> </div> <</if>> <<if !_gate.ok>> <div style="background: #2a1a1a; border: 2px solid #c06060; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: center;"> <p style="color: #ffc8c8; margin: 0; font-size: 14px;">⚠ <<= _gate.reason>></p> </div> <<elseif _eq && !_exhausted && _en >= _strikeCost>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='background: #1a4060; border: 3px solid #7ec8e3; color: #e0f4ff; padding: 18px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 17px; display: inline-block;'>⛏ Enter the Mine</div>">> <<set _r = setup.mining.startRun("frostspire")>> <<if _r.ok>><<goto "MiningGrid">><</if>> <</link>> </div> <<elseif _eq && _exhausted>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too exhausted to mine. Go sleep first.</p> <<elseif _eq>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too tired to swing. Eat or sleep before mining.</p> <</if>> <p style="color: #888; font-style: italic; font-size: 12px; text-align: center;">Each strike costs 3 minutes + <<= _strikeCost>> energy. Numbers on stone tiles show how many hazards are adjacent. Climb out anytime to bank your haul.</p> </div> <</nobr>>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <<set _sm = $miningLastSummary>> <<set _gate = setup.mining.canEnterMine("magmaheartHollow")>> <div style="background: #1a0500; padding: 20px; min-height: 100vh;"> <!-- Sunfish Cuff: Eye Stone discovery (one-time, requires Cuff Band) --> <<run setup.sunfishCuff.ensureState()>> <<if $cuffPieces && $cuffPieces.band && !$cuffPieces.eye>> <div style="background: linear-gradient(135deg, #1a0500 0%, #2a0f08 100%); border: 2px solid #ffb380; border-radius: 14px; padding: 22px; margin-bottom: 18px; box-shadow: 0 0 24px rgba(255,179,128,0.3);"> <p style="color: #ffd5c0; line-height: 1.7; margin: 0 0 12px 0;">Heat presses against your face as you step into the chamber. Something glints in the magma seam at the wall, lodged where the rock has not yet flowed over it.</p> <p style="color: #ffd5c0; line-height: 1.7; margin: 0 0 12px 0;">You ease the stone out with your pickaxe haft. It is round, hot to the touch, and has a single dark pupil suspended at its center. The Eye Stone of the Sunfish Cuff. The light bends around it.</p> <p style="color: #ffb380; font-weight: bold; text-align: center; margin: 0;">You found the Eye Stone.</p> </div> <<run setup.sunfishCuff.grantPiece("eye")>> <</if>> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #2a0500; border: 2px solid #ff5722; color: #ff8a65; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Hollow</div>">><<goto "Volcano">><</link>></div> <div style="background: #2a0f00; border: 3px solid #ff5722; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #ff8a65; margin: 0 0 10px 0;">🌋 Magmaheart Hollow</h2> <p style="color: #ffd5c0; margin: 0;">A glowing crack in the volcano's heart, opened by ancient smiths and lost for centuries. Fourteen floors of obsidian and mithril, threaded with rivers of liquid stone. Lava bursts mark every breath.</p> </div> <<if _sm && _sm.mineId === "magmaheartHollow">> <div style="background: <<if _sm.ejected>>#3a1a1a<<else>>#1a3a1a<</if>>; border: 2px solid <<if _sm.ejected>>#c06060<<else>>#6aa66a<</if>>; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <<if _sm.ejected>> <h3 style="color: #ff8a8a; margin: 0 0 6px 0;">⚠ Forced out by <<= _sm.hazardLabel>></h3> <p style="color: #f0d0d0; margin: 0; font-size: 13px;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <<else>> <h3 style="color: #aae88a; margin: 0 0 6px 0;">✓ Run complete (Floor <<= _sm.floorReached>>)</h3> <p style="color: #d0f0d0; margin: 0; font-size: 13px;">Banked: <<= setup.mining._fmtLoot(_sm.banked)>></p> <</if>> </div> <<run State.variables.miningLastSummary = null>> <</if>> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 4px 0;"><strong>Mining:</strong> Lvl <<= $miningSkill.level>> (<<= $miningSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP)</p> <p style="color: #ccc; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None<</if>></p> <<set _en = Math.floor(setup.mining._currentEnergy())>><<set _enMax = setup.mining._maxEnergy()>><<set _enPct = _en / _enMax>> <<set _enColor = _enPct <= 0.2 ? "#ff8080" : (_enPct <= 0.5 ? "#ffc060" : "#80f0c0")>> <<set _wellRested = typeof setup.hasBuff === "function" && setup.hasBuff("well_rested")>> <<set _exhausted = setup.mining.isExhausted()>> <<set _strikeCost = setup.mining._energyPerStrike()>> <p style="color: #ccc; margin: 4px 0;"><strong>⚡ Energy:</strong> <span style="color: <<= _enColor>>;"><<= _en>> / <<= _enMax>></span> <span style="color: #888; font-size: 12px;">(each strike costs <<= _strikeCost>>)</span></p> <<if _wellRested>><p style="color: #80f0c0; margin: 4px 0; font-size: 13px;">😴 <strong>Well Rested</strong>: strikes cost <<= _strikeCost>> energy instead of <<= setup.mining.ENERGY_PER_STRIKE>>.</p><</if>> <<if _exhausted>><p style="color: #ff8080; margin: 4px 0; font-size: 13px;">⚠ <strong>Exhausted</strong>: too tired to mine. Sleep at home for 6+ hours to clear.</p><</if>> </div> <<set _tfb = setup.mining.getActiveTfBuffs()>> <<if _tfb.sources && _tfb.sources.length>> <div style="background: #2a1a3a; border: 2px solid #c080ff; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #d4a0ff; margin: 0 0 8px 0;">✨ Active Transformation Buffs</h3> <<for _tf range _tfb.sources>> <<if setup.mining.TF_BUFFS[_tf]>> <p style="color: #e8d0ff; margin: 4px 0; font-size: 13px;">• <<= setup.mining.TF_BUFFS[_tf].label>></p> <</if>> <</for>> </div> <</if>> <<set _foods = Object.keys(setup.mining.MINING_FOODS).filter(function(id){ return $giftInventory && ($giftInventory[id] || 0) > 0; })>> <<if _foods.length || _en < _enMax>> <div style="background: #1a2a1a; border: 2px solid #6aa66a; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #aae88a; margin: 0 0 8px 0;">🍴 Restore Energy</h3> <p style="color: #888; font-size: 12px; margin: 0 0 8px 0; font-style: italic;">Eat a snack or sleep 8+ hours at home to refill.</p> <<if _foods.length>> <<for _f range _foods>> <<capture _f>> <<set _amt = setup.mining.MINING_FOODS[_f]>> <<set _name = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].name) || _f>> <<set _icon = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].icon) || "🍴">> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a2a; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _icon>> <<= _name>> (×<<= $giftInventory[_f]>>), +<<= _amt>> energy</span> <<link "Eat">><<run setup.mining.eatForEnergy(_f)>><<goto "MagmaheartHollowEntrance">><</link>> </div> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 4px 0;">No energy-restoring food on hand.</p> <</if>> </div> <</if>> <<if !_gate.ok>> <div style="background: #2a1a1a; border: 2px solid #c06060; border-radius: 8px; padding: 12px; margin-bottom: 15px; text-align: center;"> <p style="color: #ffc8c8; margin: 0; font-size: 14px;">⚠ <<= _gate.reason>></p> </div> <<elseif _eq && !_exhausted && _en >= _strikeCost>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='background: #4a1500; border: 3px solid #ff5722; color: #ffe0c0; padding: 18px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 17px; display: inline-block;'>⛏ Enter the Mine</div>">> <<set _r = setup.mining.startRun("magmaheartHollow")>> <<if _r.ok>><<goto "MiningGrid">><</if>> <</link>> </div> <<elseif _eq && _exhausted>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too exhausted to mine. Go sleep first.</p> <<elseif _eq>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too tired to swing. Eat or sleep before mining.</p> <</if>> <p style="color: #888; font-style: italic; font-size: 12px; text-align: center;">Each strike costs 3 minutes + <<= _strikeCost>> energy. Numbers on stone tiles show how many hazards are adjacent. Climb out anytime to bank your haul.</p> </div> <</nobr>>
<<nobr>> <<if setup.slime && setup.slime.isActivityBlocked("mine")>><<goto "SlimeBlocked">><</if>> <<if !$miningRun>><<run var sum = State.variables.miningLastSummary; var mid = sum && sum.mineId ? sum.mineId : "outskirtsQuarry"; SugarCube.Engine.play(setup.mining._entrancePassageFor(mid));>><<else>> <div id="mining-page" style="background: #1a1a1a; padding: 20px; min-height: 100vh;"></div> <<script>>setTimeout(function(){ setup.mining._mountGridPage(); }, 0);<</script>> <</if>> <</nobr>>
<<nobr>> <<set _sm = $miningLastSummary>> <div style="background: #1a1a1a; padding: 20px; min-height: 100vh;"> <div style="background: #3a1010; border: 3px solid #c06060; border-radius: 12px; padding: 30px; margin-bottom: 20px; text-align: center;"> <h2 style="color: #ff8080; margin: 0 0 12px 0; font-size: 22px;">⚠ Forced Out!</h2> <p style="color: #ffc8c8; font-size: 16px; margin: 0;"><<if _sm && _sm.hazardLabel>><<= _sm.hazardLabel>><<else>>A hazard<</if>> hit before you could react. You scrambled out, dropping half your haul.</p> <<if _sm && _sm.partialBank>> <p style="color: #ffe0e0; font-size: 14px; margin: 12px 0 0 0;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <</if>> </div> <div style="text-align: center;"> <<link "<div style='background: #2a2a2a; border: 3px solid #8a6a3a; color: #d4c4a0; padding: 15px 25px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Return to mine entrance</div>">> <<run var sum = State.variables.miningLastSummary; var mineDef = sum && sum.mineId ? setup.mining.mines[sum.mineId] : null; var target = (mineDef && mineDef.entrancePassage) || "OutskirtsQuarryEntrance"; SugarCube.Engine.play(target);>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <div style="background: #1a1a1a; padding: 20px; min-height: 100vh;"> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #2a1f10; border: 2px solid #c89060; color: #ffc080; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Forge</div>">><<goto "IndustrialOutskirts">><</link>></div> <div style="background: #2a1f10; border: 3px solid #c89060; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #ffc080; margin: 0 0 10px 0;">🔨 The Forge</h2> <p style="color: #d4c4a0; margin: 0;">A blast of dry heat hits you the moment you step in. Anvils, smelter, racks of half-finished tools. The smith glances up: "Bring me ore. Walk out with something useful."</p> </div> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #ccc; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP) | <strong>Mining:</strong> Lvl <<= $miningSkill.level>></p> <p style="color: #ccc; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None<</if>></p> </div> <div style="background: #1a1a2a; border: 2px solid #6080a0; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #80c0ff; margin: 0 0 10px 0;">⚒ Smelter</h3> <<set _hasOre = false>> <<for _ore range setup.forge.SMELTABLE_ORES>> <<capture _ore>> <<set _qty = ($oreInventory[_ore] || 0)>> <<if _qty > 0>> <<set _hasOre = true>> <div style="display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid #2a3a5a;"> <span style="color: #d4c4a0;"><<= setup.mining._prettyName(_ore)>> ore: <strong style="color: #ffd080;"><<= _qty>></strong></span> <span style="font-size: 13px;"> <<link "Smelt 1">><<run setup.forge.smelt(_ore, 1)>><<goto "Forge">><</link>> <<if _qty >= 5>> | <<link "Smelt 5">><<run setup.forge.smelt(_ore, 5)>><<goto "Forge">><</link>><</if>> <<if _qty >= 1>> | <<link "Smelt all">><<run setup.forge.smelt(_ore, ($oreInventory[_ore] || 0))>><<goto "Forge">><</link>><</if>> </span> </div> <</if>> <</capture>> <</for>> <<if !_hasOre>> <p style="color: #888; font-style: italic; font-size: 13px;">No raw ore to smelt. Bring some from the mines.</p> <</if>> <<set _ingotKeys = Object.keys($ingotInventory || {}).filter(function(k){ return ($ingotInventory[k] || 0) > 0; })>> <<if _ingotKeys.length>> <p style="color: #888; font-size: 12px; margin-top: 10px;"><strong>Ingot stock:</strong> <<for _k range _ingotKeys>><<= $ingotInventory[_k]>> <<= setup.mining._prettyName(_k)>>; <</for>> </p> <</if>> </div> <div style="background: #2a1f10; border: 2px solid #c89060; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #ffc080; margin: 0 0 10px 0;">⛏ Craft a Pickaxe</h3> <<for _id range ["ironPickaxe", "steelPickaxe", "mithrilPickaxe"]>> <<capture _id>> <<set _r = setup.forge.recipes[_id]>> <<set _can = setup.forge.canCraft(_id)>> <<set _pred = setup.forge.predictQuality(_id)>> <<set _adj = setup.forge._adjustedMats(_r)>> <div style="background: #1a1a1a; border: 1px solid #555; border-radius: 6px; padding: 10px; margin-bottom: 8px;"> <div style="display: flex; justify-content: space-between; align-items: center; gap: 10px;"> <div style="flex: 1;"> <strong style="color: #ffd080;"><<= _r.label>></strong> <span style="color: #888; font-size: 11px;"> (Crafting Lvl <<= _r.levelReq>>+)</span> <br><span style="color: #b8a0a0; font-size: 11px;">Predicted strikes: <<= _pred.strikesMin>>–<<= _pred.strikesMax>> | sockets: <<= _pred.socketCount>></span> <br><span style="color: #888; font-size: 11px;">Cost: <<set _ingotKeysC = Object.keys(_adj.ingots)>> <<for _k range _ingotKeysC>><<= _adj.ingots[_k]>> <<= setup.mining._prettyName(_k)>> ingot<<if _adj.ingots[_k] > 1>>s<</if>><<if _k !== _ingotKeysC[_ingotKeysC.length-1] || Object.keys(_adj.gems).length>>, <</if>><</for>> <<set _gemKeysC = Object.keys(_adj.gems)>> <<for _k range _gemKeysC>><<= _adj.gems[_k]>> <<= setup.mining._prettyName(_k)>><<if _k !== _gemKeysC[_gemKeysC.length-1]>>, <</if>><</for>> </span> </div> <div style="text-align: right; min-width: 80px;"> <<if _can.ok>> <<link "<div style='background: #4a3a1a; border: 2px solid #d4a060; color: #ffd080; padding: 6px 14px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Craft</div>">><<run setup.forge.craft(_id)>><<goto "Forge">><</link>> <<else>> <span style="color: #888; font-size: 10px; font-style: italic;"><<= _can.reason>></span> <</if>> </div> </div> </div> <</capture>> <</for>> </div> <div style="background: #2a1f1a; border: 2px solid #d4a060; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #ffd080; margin: 0 0 10px 0;">🔧 Craft a Pickaxe Head</h3> <<for _id range ["heavyHead", "preciseHead", "reinforcedHead"]>> <<capture _id>> <<set _r = setup.forge.recipes[_id]>> <<set _can = setup.forge.canCraft(_id)>> <<set _adj = setup.forge._adjustedMats(_r)>> <div style="background: #1a1a1a; border: 1px solid #555; border-radius: 6px; padding: 10px; margin-bottom: 8px;"> <div style="display: flex; justify-content: space-between; align-items: center; gap: 10px;"> <div style="flex: 1;"> <strong style="color: #ffd080;"><<= _r.label>></strong> <span style="color: #888; font-size: 11px;"> (Crafting Lvl <<= _r.levelReq>>+)</span> <br><span style="color: #888; font-size: 11px;">Cost: <<set _ingotKeysH = Object.keys(_adj.ingots)>> <<for _k range _ingotKeysH>><<= _adj.ingots[_k]>> <<= setup.mining._prettyName(_k)>> ingot<<if _adj.ingots[_k] > 1>>s<</if>>; <</for>> <<set _oreKeysH = Object.keys(_adj.ore)>> <<for _k range _oreKeysH>><<= _adj.ore[_k]>> <<if _k === "any">>raw ore (any)<<else>><<= setup.mining._prettyName(_k)>> ore<</if>>; <</for>> <<set _cgKeysH = Object.keys(_adj.cutGems)>> <<for _k range _cgKeysH>><<= _adj.cutGems[_k]>> <<if _k === "any">>cut gem (any)<<else>><<= setup.mining._prettyName(_k)>><</if>>; <</for>> </span> </div> <div style="text-align: right; min-width: 80px;"> <<if _can.ok>> <<link "<div style='background: #4a3a1a; border: 2px solid #d4a060; color: #ffd080; padding: 6px 14px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Craft</div>">><<run setup.forge.craft(_id)>><<goto "Forge">><</link>> <<else>> <span style="color: #888; font-size: 10px; font-style: italic;"><<= _can.reason>></span> <</if>> </div> </div> </div> <</capture>> <</for>> </div> <<if _eq>> <div style="background: #1a2a1a; border: 2px solid #6aa66a; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #aae88a; margin: 0 0 10px 0;">🛠 Equipped: <<= _eq.name>></h3> <p style="color: #d0f0d0; margin: 4px 0; font-size: 13px;">Strikes per run: <strong><<= setup.mining._currentDurability()>></strong> | Sockets: <strong><<= _eq.sockets>></strong></p> <<if _eq.masterBonus>> <p style="color: #ffd080; margin: 4px 0; font-size: 12px;">★ Master Craftsman bonus: <<= _eq.masterBonus>></p> <</if>> <p style="color: #d0f0d0; margin: 8px 0 4px 0; font-size: 13px;"><strong>Slotted heads:</strong></p> <<if _eq.slottedHeads && _eq.slottedHeads.length>> <<for _hid range _eq.slottedHeads>> <<capture _hid>> <<set _head = $pickaxeHeads.find(function(h){ return h.id === _hid; })>> <<if _head>> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a2a; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _head.name>></span> <<link "Unslot">><<run setup.mining.unslotHead(_eq.id, _hid)>><<goto "Forge">><</link>> </div> <</if>> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 12px; margin: 4px 0;">No heads slotted.</p> <</if>> <<set _availHeads = ($pickaxeHeads || []).filter(function(h){ return _eq.slottedHeads.indexOf(h.id) === -1; })>> <<if _availHeads.length && _eq.slottedHeads.length < _eq.sockets>> <p style="color: #d0f0d0; margin: 10px 0 4px 0; font-size: 13px;"><strong>Available heads to slot (<<= _eq.sockets - _eq.slottedHeads.length>> slot<<if _eq.sockets - _eq.slottedHeads.length > 1>>s<</if>> open):</strong></p> <<for _h range _availHeads>> <<capture _h>> <div style="display: flex; justify-content: space-between; padding: 4px 8px; font-size: 13px;"> <span style="color: #d0f0d0;"><<= _h.name>></span> <<link "Slot">> <<set _s = setup.mining.slotHead(_eq.id, _h.id)>> <<if _s.ok>><<goto "Forge">><</if>> <</link>> </div> <</capture>> <</for>> <<elseif _availHeads.length && _eq.slottedHeads.length >= _eq.sockets>> <p style="color: #888; font-style: italic; font-size: 12px;">All sockets full. Unslot one to swap.</p> <</if>> </div> <</if>> <<if $pickaxes.length > 1>> <div style="background: #2a2a2a; border: 1px solid #555; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #d4c4a0; margin: 0 0 10px 0;">⛏ Pickaxe Rack</h3> <<for _p range $pickaxes>> <<capture _p>> <<if _p.id !== $equippedPickaxe>> <div style="display: flex; justify-content: space-between; padding: 6px 8px; border-bottom: 1px solid #444; font-size: 13px;"> <span style="color: #ccc;"><<= _p.name>> (<<= _p.baseStrikes + _p.qualityBonus>> strikes, <<= _p.sockets>> socket<<if _p.sockets > 1>>s<</if>>)</span> <<link "Equip">><<run setup.mining.equipPickaxe(_p.id)>><<goto "Forge">><</link>> </div> <</if>> <</capture>> <</for>> </div> <</if>> <div style="background: #2a2a1a; border: 2px solid #909040; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #d4d480; margin: 0 0 10px 0;">🪓 Spare Pickaxe Heads</h3> <<set _spareHeads = ($pickaxeHeads || []).filter(function(h){ return h && !setup.mining._isHeadSlotted(h.id); })>> <<if _spareHeads.length>> <<for _h range _spareHeads>> <<capture _h>> <<set _mainIngot = setup.mining.HEAD_MAIN_INGOT[_h.type] || "">> <div style="display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid #3a3a1a;"> <span style="color: #e0e0a0;"><<= _h.name>> <span style="color: #888; font-size: 12px;">(re-smelt returns 1 <<= _mainIngot>> ingot)</span></span> <span style="font-size: 13px;"> <<link "Re-smelt">><<run setup.mining.resmeltHead(_h.id)>><<goto "Forge">><</link>> | <<link "Discard">><<run setup.mining.discardHead(_h.id)>><<goto "Forge">><</link>> </span> </div> <</capture>> <</for>> <<else>> <p style="color: #888; font-style: italic; font-size: 13px;">No spare heads. Unslotted heads will appear here for re-smelting or discarding.</p> <</if>> </div> <div style="background: #1a2a1f; border: 2px solid #b09040; border-radius: 10px; padding: 15px; margin-bottom: 15px;"> <h3 style="color: #ffc060; margin: 0 0 10px 0;">💎 Sell Ingots</h3> <<set _hasIngotForSale = false>> <<for _ingot range Object.keys(setup.mining.INGOT_BASE_PRICES)>> <<capture _ingot>> <<set _iqty = ($ingotInventory[_ingot] || 0)>> <<set _iprice = setup.mining.INGOT_BASE_PRICES[_ingot] || 0>> <<if _iqty > 0 && _iprice > 0>> <<set _hasIngotForSale = true>> <div style="display: flex; justify-content: space-between; align-items: center; padding: 6px 8px; border-bottom: 1px solid #4a3a1a;"> <span style="color: #e0d4a0;"><<= setup.mining._prettyName(_ingot)>> ingot: <strong style="color: #ffd080;"><<= _iqty>></strong> <span style="color: #888; font-size: 12px;">($<<= _iprice>> ea)</span></span> <span style="font-size: 13px;"> <<link "Sell 1">><<run setup.mining.sellIngot(_ingot, 1)>><<goto "Forge">><</link>> <<if _iqty >= 5>> | <<link "Sell 5">><<run setup.mining.sellIngot(_ingot, 5)>><<goto "Forge">><</link>><</if>> <<if _iqty >= 1>> | <<link "Sell all">><<run setup.mining.sellIngot(_ingot, ($ingotInventory[_ingot] || 0))>><<goto "Forge">><</link>><</if>> </span> </div> <</if>> <</capture>> <</for>> <<if !_hasIngotForSale>> <p style="color: #888; font-style: italic; font-size: 13px;">No ingots on hand to sell.</p> <</if>> </div> <p style="color: #888; font-size: 11px; text-align: center; font-style: italic;">Each smelt = 30 in-game min. Each craft = 60 min. Quality scales with Crafting level + traits.</p> </div> <</nobr>>
<<nobr>> <<if !$visitedLocations>><<set $visitedLocations = []>><</if>> <<if !$visitedLocations.includes("IndustrialOutskirts")>><<run $visitedLocations.push("IndustrialOutskirts")>><</if>> <<set $lastLocation = "IndustrialOutskirts">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #aaa; text-align: center;">🏭 Industrial District</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2a2a2a 0%, #1a1a1a 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #888;"> <p style="color: white; font-size: 18px; margin: 0;">Smokestacks lean against a slate sky. The roads turn to gravel and rail. This is where the city's raw work happens. Ore goes in, tools come out, and workers nod to each other without speaking. The quarry shaft sits on the far end, its scaffolding creaking with every gust of wind.</p> </div> <h2 style="color: #aaa;">Locations</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Public transit hub.</p> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Bus Stop</div>">> <<run advanceTime(5)>> <<goto "BusStop">> <</link>> </div> <div style="border: 3px solid #c89060; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffc080; margin: 0 0 10px 0;">🔨 The Forge</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Smelt raw ore into ingots and craft pickaxes & pickaxe heads.</p> <<link "<div style='background: #c89060; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter the Forge</div>">> <<run advanceTime(5)>> <<goto "Forge">> <</link>> </div> <div style="border: 3px solid #8a6a3a; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d4a060; margin: 0 0 10px 0;">⛏ Outskirts Quarry</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A scaffolded mineshaft. Three floors of stone and ore, with gas pockets to dodge.</p> <<link "<div style='background: #8a6a3a; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go to Quarry</div>">> <<run advanceTime(10)>> <<goto "OutskirtsQuarryEntrance">> <</link>> </div> </div> <h2 style="color: #aaa;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;"> <div style="border: 3px solid #5ca4e8; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #5ca4e8; margin: 0 0 10px 0;">🏪 Commercial District</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Back to the shops and offices.</p> <<link "<div style='background: #5ca4e8; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Commercial District</div>">> <<run advanceTime(15)>> <<goto "CommercialDistrict">> <</link>> </div> <div style="border: 3px solid #4a4a4a; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #888; margin: 0 0 10px 0;">🌾 Outskirts</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Back to the rural roads and fields.</p> <<link "<div style='background: #4a4a4a; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel to Outskirts</div>">> <<run advanceTime(15)>> <<goto "Outskirts">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<run setup.mining.ensureState()>> <<set _eq = setup.mining.getEquippedPickaxe()>> <<set _sm = $miningLastSummary>> <div style="background: #0a1a2a; padding: 20px; min-height: 100vh;"> <div style="text-align: center; margin-bottom: 15px;"><<link "<div style='display: inline-block; background: #0f1f30; border: 2px solid #4080a0; color: #80c0e0; padding: 8px 22px; border-radius: 8px; cursor: pointer; font-weight: bold; font-size: 14px;'>← Leave the Hollow</div>">><<goto "UnderWaterCave">><</link>></div> <div style="background: #102540; border: 3px solid #4080a0; border-radius: 10px; padding: 20px; margin-bottom: 15px;"> <h2 style="color: #80c0e0; margin: 0 0 10px 0;">🌊 Tide Hollow</h2> <p style="color: #b8d8e8; margin: 0;">A flooded chamber deep beneath the underwater cave. Five levels of coral-encrusted stone, lit only by the bioluminescent glints of trapped pearls. Watch the water line.</p> </div> <<if _sm>> <div style="background: <<if _sm.ejected>>#3a1a1a<<else>>#1a3a1a<</if>>; border: 2px solid <<if _sm.ejected>>#c06060<<else>>#6aa66a<</if>>; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <<if _sm.ejected>> <h3 style="color: #ff8a8a; margin: 0 0 6px 0;">⚠ Forced out by <<= _sm.hazardLabel>></h3> <p style="color: #f0d0d0; margin: 0; font-size: 13px;">Salvaged: <<= setup.mining._fmtLoot(_sm.partialBank, _sm.savedFraction || 0.5)>></p> <<else>> <h3 style="color: #aae88a; margin: 0 0 6px 0;">✓ Run complete (Floor <<= _sm.floorReached>>)</h3> <p style="color: #d0f0d0; margin: 0; font-size: 13px;">Banked: <<= setup.mining._fmtLoot(_sm.banked)>></p> <</if>> </div> <<run State.variables.miningLastSummary = null>> <</if>> <div style="background: #1a2a3a; border: 1px solid #4080a0; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <p style="color: #b8d8e8; margin: 4px 0;"><strong>Mining:</strong> Lvl <<= $miningSkill.level>> (<<= $miningSkill.xp>> XP)</p> <p style="color: #b8d8e8; margin: 4px 0;"><strong>Crafting:</strong> Lvl <<= $craftingSkill.level>> (<<= $craftingSkill.xp>> XP)</p> <p style="color: #b8d8e8; margin: 4px 0;"><strong>Equipped:</strong> <<if _eq>><<= _eq.name>>, <<= setup.mining._currentDurability()>> strikes per run<<else>>None. Visit the Forge first<</if>></p> <<set _en = Math.floor(setup.mining._currentEnergy())>><<set _enMax = setup.mining._maxEnergy()>><<set _enPct = _en / _enMax>> <<set _enColor = _enPct <= 0.2 ? "#ff8080" : (_enPct <= 0.5 ? "#ffc060" : "#80f0c0")>> <<set _wellRested = typeof setup.hasBuff === "function" && setup.hasBuff("well_rested")>> <<set _exhausted = setup.mining.isExhausted()>> <<set _strikeCost = setup.mining._energyPerStrike()>> <p style="color: #b8d8e8; margin: 4px 0;"><strong>⚡ Energy:</strong> <span style="color: <<= _enColor>>;"><<= _en>> / <<= _enMax>></span> <span style="color: #6080a0; font-size: 12px;">(each strike costs <<= _strikeCost>>)</span></p> <<if _wellRested>><p style="color: #80f0c0; margin: 4px 0; font-size: 13px;">😴 <strong>Well Rested</strong>: strikes cost <<= _strikeCost>> energy.</p><</if>> <<if _exhausted>><p style="color: #ff8080; margin: 4px 0; font-size: 13px;">⚠ <strong>Exhausted</strong>: sleep at home for 6+ hours.</p><</if>> </div> <<set _tfb = setup.mining.getActiveTfBuffs()>> <<if _tfb.sources && _tfb.sources.length>> <div style="background: #1a2540; border: 2px solid #80a0ff; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #80c0ff; margin: 0 0 8px 0;">✨ Active Transformation Buffs</h3> <<for _tf range _tfb.sources>> <<if setup.mining.TF_BUFFS[_tf]>> <p style="color: #b8d8e8; margin: 4px 0; font-size: 13px;">• <<= setup.mining.TF_BUFFS[_tf].label>></p> <</if>> <</for>> </div> <</if>> <<set _foods = Object.keys(setup.mining.MINING_FOODS).filter(function(id){ return $giftInventory && ($giftInventory[id] || 0) > 0; })>> <<if _foods.length>> <div style="background: #102540; border: 2px solid #4080a0; border-radius: 8px; padding: 12px; margin-bottom: 15px;"> <h3 style="color: #80c0e0; margin: 0 0 8px 0;">🍴 Restore Energy</h3> <<for _f range _foods>> <<capture _f>> <<set _amt = setup.mining.MINING_FOODS[_f]>> <<set _name = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].name) || _f>> <<set _icon = (setup.giftItems && setup.giftItems[_f] && setup.giftItems[_f].icon) || "🍴">> <div style="display: flex; justify-content: space-between; padding: 4px 8px; border-bottom: 1px solid #2a4a5a; font-size: 13px;"> <span style="color: #b8d8e8;"><<= _icon>> <<= _name>> (×<<= $giftInventory[_f]>>), +<<= _amt>> energy</span> <<link "Eat">><<run setup.mining.eatForEnergy(_f)>><<goto "TideHollowEntrance">><</link>> </div> <</capture>> <</for>> </div> <</if>> <<if _eq && !_exhausted && _en >= _strikeCost>> <div style="text-align: center; margin: 20px 0;"> <<link "<div style='background: #103040; border: 3px solid #80c0e0; color: #b8d8e8; padding: 18px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 17px; display: inline-block;'>🌊 Enter the Hollow</div>">> <<set _r = setup.mining.startRun("tideHollow")>> <<if _r.ok>><<goto "MiningGrid">><</if>> <</link>> </div> <<elseif _eq && _exhausted>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too exhausted to mine. Go sleep first.</p> <<elseif _eq>> <p style="color: #ff8080; text-align: center; font-style: italic; font-size: 13px;">Too tired to swing. Eat or sleep before mining.</p> <</if>> <p style="color: #6080a0; font-style: italic; font-size: 12px; text-align: center;">Hazards here are flood pockets. They swamp a floor without warning. Reinforced head ignores the first hit.</p> </div> <</nobr>>
<<nobr>> <<run setup.sunfishCuff.ensureState()>> <<set $cuffTempleDiscovered = true>> <<set $lastLocation = "JungleSunfishTemple">> <div style="background: #1a1a2a; min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a9ff; text-align: center; text-shadow: 0 0 18px rgba(201,169,255,0.4);">🐟 Sunfish Temple</h1> <div style="background: linear-gradient(135deg, #1a0f2a 0%, #0a0410 100%); border: 2px solid #c9a9ff; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">Cool air smelling of moss and old stone. Mola carved everywhere. The reliefs follow you with their flat eyes as you cross the worn floor.</p> <p style="color: #ddd; line-height: 1.7; margin: 0;">In the center of the chamber a stone plinth rises waist-high, ringed by four shallow notches in the stone around it.</p> </div> <<if !$cuffPieces.band>> <div style="background: #2a2a2a; border: 2px solid #d4c4f0; border-radius: 12px; padding: 18px; margin-bottom: 18px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">On the plinth lies a bare metal band. No setting, no stone. The hinge still works when you nudge it. The metal is cold and pale and feels heavier than it should.</p> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #c9a9ff 0%, #6e4ea8 100%); color: white; padding: 12px 26px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Take the Band</div>">> <<run setup.sunfishCuff.grantPiece("band")>> <<goto "JungleSunfishTemple">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; border: 2px solid #6e4ea8; border-radius: 12px; padding: 18px; margin-bottom: 18px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">The plinth is empty now. The Band is in your bag.</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">Four reliefs ring the plinth, each leaning toward a different quarter of the world.</p> <ul style="color: #c9a9ff; line-height: 1.8; margin: 0; padding-left: 22px;"> <li>A round disc, half-submerged. Its face is etched with branching coral.</li> <li>A tall fin, stylized like a quill. A book is folded behind it.</li> <li>A crescent below, paired with a wave. The crescent is hollow, waiting to be filled.</li> <li>A small eye, bordered by tongues of flame.</li> </ul> </div> <</if>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #2a3a3a; border: 2px solid #2ecc71; color: #2ecc71; padding: 10px 22px; border-radius: 8px; cursor: pointer; font-weight: bold;'>← Leave the temple</div>">> <<advancetime 15>> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.sunfishCuff.ensureState()>> <div style="background: #001020; min-height: 100vh; padding: 20px;"> <h1 style="color: #4fc3f7; text-align: center; text-shadow: 0 0 18px rgba(79,195,247,0.4);">🌊 Dive Deeper</h1> <div style="background: linear-gradient(135deg, #001a30 0%, #00091a 100%); border: 2px solid #4fc3f7; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #cce5ff; line-height: 1.7; margin: 0 0 12px 0;">You hold the Band against your chest and kick down past the bright color of the reef into colder water. Pressure hums in your ears. The hum the Band has been making is louder here, in time with your pulse.</p> <p style="color: #cce5ff; line-height: 1.7; margin: 0 0 12px 0;">A coral shelf opens. Beneath it, a chamber of pale stone framed by waving anemones. Sand drifts off something pale and round. You scrape it free.</p> <p style="color: #cce5ff; line-height: 1.7; margin: 0 0 12px 0;">A flat disc the size of your palm, etched with the body and small eye of a sunfish. The Disc Amulet. The empty notches in the Cuff Band suddenly make geometric sense.</p> <p style="color: #4fc3f7; line-height: 1.7; margin: 0; font-weight: bold; text-align: center;">You found the Disc Amulet.</p> </div> <<run setup.sunfishCuff.grantPiece("amulet")>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #4fc3f7; color: white; padding: 12px 26px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Surface</div>">> <<goto "CoralReef">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.sunfishCuff.ensureState()>> <<set _roisinSpot = setup.sunfishCuff.getRoisinCurrentLocation()>> <<set _cuffSizes = ["flat masculine","flat","small","medium","large","huge","gigantic"]>> <<set _cuffPreChest = ($possessionPreState && $possessionPreState.bodyParts && $possessionPreState.bodyParts.chest) || "medium">> <<set _cuffPreButt = ($possessionPreState && $possessionPreState.bodyParts && $possessionPreState.bodyParts.butt) || "medium">> <<set _cuffPreGenitals = ($possessionPreState && $possessionPreState.bodyParts && $possessionPreState.bodyParts.genitals) || "tight vagina">> <<set _cuffPreGender = ($possessionPreState && $possessionPreState.gender) || "female">> <<set _cuffChestDelta = 5 - _cuffSizes.indexOf(_cuffPreChest)>> <<set _cuffButtDelta = 4 - _cuffSizes.indexOf(_cuffPreButt)>> <div class="cuff-container"> <!-- STAGE 1: The Pulse (0s) --> <div class="cuff-section" style="--delay: 0s;"> <p>The artifact feels warm against your skin. Not warm like metal left in the sun. Warm like something alive. You can feel a heartbeat inside the Eye Stone, slow and steady, ticking against the inside of your wrist.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>You close the band around your wrist and the catch clicks once. The stone at its center flares pink and violet. A column of soft light pours up your arm and slams into your chest like an open hand.</p> </div> <div class="cuff-section" style="--delay: 1.6s;"> <p>You gasp. Your knees buckle. The artifact does not hurt you. It is just enormous. A current of someone else's pulse pours through every vein, every nerve, every cell, hot and oceanic and undeniable. Your vision goes pink at the edges. When you blink, you can see her heartbeat moving under your own skin, glowing threads racing along your arms like living tape wraps.</p> </div> <div class="cuff-section" style="--delay: 2.4s;"> <p class="cuff-section-emphasis">Then the slipping begins.</p> </div> <!-- STAGE 2: The Untether (6s) --> <<timed 6s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <p>Your body folds. You see it from above. Yourself, slack on the floor of your home, mouth a little open, eyes half-closed. The version of you you have always been. A small, fond pang for it goes through whatever you are now.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>You are weightless. You are a thread. The artifact has hold of you and the artifact is pulling.</p> </div> <</timed>> <!-- STAGE 3: The Crossing (12s) --> <<timed 12s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <p>The walls peel away. You are airborne. Sunfish City unfolds beneath you in one bright glance: rooftops, harbor, the curve of the coast, the small bright corners where everything happens.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>The artifact pulls you toward her like a tide pulls a boat. There is no resisting. There is no need to resist. The Eye Stone knows whose body it answers to and it will not let you stray.</p> </div> <</timed>> <!-- STAGE 4: The Mirror (18s) --> <<timed 18s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <p>You hit her body the way a hand hits skin. Soft. Then in. You slide through the back of her neck and her ribcage flares around you. Her pulse swallows yours. It is so much louder than your own ever was.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>Her body claims you. Or you claim her. The distinction stops mattering between one breath and the next. Your eyes drop. You have to see what you are now.</p> </div> <div class="cuff-section" style="--delay: 1.6s;"> <p>Roisin's hands move before you tell them to. Calloused, sure, the leather of her fingerless gloves cinched at the knuckles. They find the bottom of her tape wrap and peel it up her ribs so you can look. Your jaw drops. So does the wrap.</p> <div class="cuff-section-image"> <img src="Images/Transformation/Roisin.webp" alt="Roisin Sullivan" onerror="this.style.display='none';"> </div> </div> <div class="cuff-section" style="--delay: 2.6s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. Look at me."</p> <p>Her voice. Yours now. Smooth and Gaelic, low at the back of the throat. The sound of it comes out of your own mouth and the heat under it is yours too.</p> </div> <div class="cuff-section" style="--delay: 3.6s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"She walks around like this all day. Tits packed under a wrap, abs you could grate cheese on, those shorts barely keeping her ass in. No wonder she struts."</p> </div> <div class="cuff-section" style="--delay: 4.6s;"> <p>You lift the wrap higher. Her chest rolls free of it for a breath and the weight is unreal. Heavy. Warm. Hers. Yours. Her nipples hit the air and stiffen fast enough to short out the back of your skull. Heat slides down her stomach and pools low and slow between her thighs.</p> </div> <div class="cuff-section" style="--delay: 5.6s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Oh. Oh, you are a problem. I am keeping you on for a while."</p> <p>Her smirk fits your mouth like it was waiting. You tilt her head, let your eyes drag down the carved line of her abs, and a low sound goes out of her throat that you absolutely meant this time.</p> </div> <</timed>> <!-- STAGE 5: The Reshaping (26s) --> <<timed 26s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <p>Her body teaches you what it is. Sensations crowd in faster than you can name them. The serious weight of her chest pulling against the tape wrap. Nipples already stiff under the pressure. Damp skin slick under the tape from her morning run. The thick clutch of her thighs where the denim cuts in. The carved-out plates of her abs flexing with every breath.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>The brim of her cap shading your eyes. The high ponytail tugging at the back of your scalp. Calluses on her knuckles from a heavy bag. Salt and something musky at the back of her teeth. A low ache between her hips that has been building for days, and a hunger she does not let herself eat for. A smirk her face wants to settle into without asking.</p> </div> <div class="cuff-section" style="--delay: 1.6s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Hells. Every step, the wrap is fighting her tits and the wrap is losing."</p> </div> <div class="cuff-section" style="--delay: 2.4s;"> <p>You roll your shoulders and her tits roll with them. The tape strains. The seam of the shorts shifts. The ache between her hips notches one beat hotter and you have to put a gloved hand on the wall to steady yourself.</p> </div> <div class="cuff-section" style="--delay: 3.2s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. She has been walking around like this all morning. The poor stubborn thing has been ignoring it."</p> </div> <<if _cuffChestDelta >= 2 || _cuffChestDelta <= -2 || _cuffButtDelta >= 2 || _cuffButtDelta <= -2>> <div class="cuff-section" style="--delay: 4s;"> <<if _cuffChestDelta >= 2>> <p>Your chest used to be <<= _cuffPreChest>>. It is not anymore. Hers is huge. Full. Hanging heavy off her ribs and only the tape wrap holding her down. Your shoulders pull forward to take the new weight. You feel them swing against each other when she shifts her stance. The mass of it is intoxicating. You are nowhere near used to it yet.</p> <<elseif _cuffChestDelta <= -2>> <p>Your chest used to be <<= _cuffPreChest>>. Hers is smaller, denser, lifted by sport. Substantial but tighter than what you remember. Less swing. More strain against the tape that binds it. The proportions feel athletic in a way yours never were.</p> <</if>> <<if _cuffButtDelta >= 2>> <p>Her ass is more than you ever carried. The denim cuts deep into thick muscle that flares wider than your hips ever did. You feel its weight when she walks. A heavy, deliberate sway you do not know how to do yet. You will. Her body knows the rhythm. You only have to step inside it.</p> <<elseif _cuffButtDelta <= -2>> <p>Her ass is smaller than what you used to fill out. Tighter, harder, all training. The shorts sit differently on this frame, held up by muscle instead of softness. The shape is athletic in a way yours was not.</p> <</if>> </div> <</if>> <</timed>> <!-- STAGE 6: The Memories (36s) --> <<timed 36s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <p>Her memories fold into yours like cards into a deck. The Friday she sat at the docks alone with a six-pack and counted the boats. The first time she broke a board cleanly with her fist. The names she has for the people she lifts with at the gym, half affection, half mockery. Her mother's voice. The way Revna laughs at her, fond, tired.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>A locked drawer in her bedside table that she never opens but never throws out. Two passcodes she will never write down. A face she pictures when she touches herself. A small, secret tally of slights she keeps and will never tell anyone.</p> </div> <div class="cuff-section" style="--delay: 1.6s;"> <p>You know her now the way she knows herself. More, maybe, because she has had to look away from some of it. You do not.</p> </div> <div class="cuff-section" style="--delay: 2.4s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Oh, Roisin. You secretive thing. Look at all that you have been carrying."</p> </div> <div class="cuff-section" style="--delay: 3.2s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"The drawer. The face. The little tally. I am keeping every bit of it."</p> </div> <</timed>> <!-- STAGE 7: The Heat (44s) --> <<timed 44s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <<if _cuffPreGender === "male">> <p>You notice it before anything else. The shape between your legs is gone. There is no cock at the front of you. There is something soft and warm folded at the base of you instead, and it is Roisin's, and it is now also yours. You shift your hips just to be sure. The seam of her shorts moves against it and a small sound goes out of her mouth that you did not mean to make.</p> <<elseif _cuffPreGender === "female">> <p>You notice it right away. You have lived in a body like this your whole life, but this is not your body. The shape between your legs is the same kind as yours and it is not yours — it is Roisin's. The proportions are different. The way she holds the weight of it is different. The seam of her shorts catches differently. You shift your hips just to feel it move, and it does not move the way you are used to.</p> <<else>> <p>You notice it right away. The shape between your legs has narrowed and simplified into something soft and folded and warm at the base of you, and it is entirely Roisin's now. You shift your hips to feel it. The seam of her shorts moves against it and a small sound goes out of her mouth that you did not mean to make.</p> <</if>> </div> <div class="cuff-section" style="--delay: 0.4s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Oh. Oh that is something else entirely."</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p>It is unmistakable. This pussy is Roisin's, not yours. It belongs to a body she has built and used herself, and it is yours now. The folds are slick. The seam is warm. There is a low fullness deep behind it that pulses in time with her heartbeat. Her wetness is real and it is yours to feel. Every shift of her hips presses another small wave of it through you, and it is good. It is so much better than you expected. You did not know Roisin's body would feel this nice from the inside.</p> </div> <div class="cuff-section" style="--delay: 1.2s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"You filthy thing. You have been wet for hours. Have you been ignoring this all morning?"</p> </div> <div class="cuff-section" style="--delay: 1.6s;"> <p>Her body is hungry and her body is yours. A low ache that has been building for days because she does not let herself eat for it. The tape wrap pressing on already stiff nipples. The seam of the shorts riding warm against her cunt with every step she does not take. She has been carrying it the whole shift. Her pulse drops a beat lower in her belly. Her breath catches once. Her thighs press together. Hers. Yours.</p> </div> <div class="cuff-section" style="--delay: 2.4s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"All right, girl. We are going to take care of you. After we have a little fun."</p> </div> <</timed>> <!-- STAGE 8: Settle in (52s) --> <<timed 52s>> <div class="cuff-divider"></div> <div class="cuff-section" style="--delay: 0s;"> <p>You roll her shoulders. They set the way hers always set, ready for a fight that might never come. You roll her wrist. Her thumb slides up the inside of her own thigh the way she does when she is bored. Her body knows the moves. You do not have to teach it anything. You only have to let it run.</p> </div> <div class="cuff-section" style="--delay: 0.8s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Right then. Roisin Sullivan. Let us see what is left of your day."</p> </div> <div class="cuff-section" style="--delay: 1.6s;"> <p>Her smirk fits your mouth without asking. Her stance settles into your hips. The artifact warms once at her wrist as if to confirm the bargain. Whatever she has, you have. Whatever she can do, you can do. Whatever she would never tell anyone, you already know.</p> <div class="cuff-section-image"> <img src="Images/NPCs/StaticNPCs/Roisin_Sullivan.webp" alt="Roisin Sullivan" onerror="this.style.display='none';"> </div> </div> <div class="cuff-section" style="--delay: 2.4s;"> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"And I am very, very glad to be you."</p> </div> <</timed>> <!-- STAGE 9: Step Into Her Day (60s) --> <<timed 60s>> <div class="cuff-section" style="--delay: 0s; text-align: center;"> <p style="color: #c9a9ff; font-style: italic; font-size: 14px; margin: 0 0 18px 0;">Take her body somewhere.</p> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 14px 32px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 16px; box-shadow: 0 0 20px rgba(255,143,200,0.5); border: 2px solid #c9a9ff; letter-spacing: 1px;'>Step into her day</div>">> <<goto _roisinSpot>> <</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <div style="background: radial-gradient(ellipse at center, #1a0a28 0%, #000 75%); min-height: 100vh; padding: 30px 20px;"> <div style="max-width: 720px; margin: 0 auto; color: #ddd; line-height: 1.7;"> <h1 style="color: #c9a9ff; text-align: center;">🪟 Casing Your Own House</h1> <<set _bodyHome = $possessionBodyLocation || "StudioApartment">> <p>You drift through the streets in Roisin's stride and stop at an address you know better than anyone. Your own door. Your own porch light. Your own body somewhere behind that door, slumped where the artifact left it. You did not come back. You came around.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Right then. Let us see if Roisin's hands are as good as her record says."</p> <<set _stealthChance = 50>> <<set _hasLP = $skills && $skills.includes("Lock Picking")>> <<if _hasLP>><<set _stealthChance = _stealthChance + 25>><</if>> <<set _hasCombat = $skills && ($skills.includes("Combat") || $skills.includes("Martial Arts"))>> <<if _hasCombat>><<set _stealthChance = _stealthChance + 5>><</if>> <<set _hasAth = $physicalTraits && $physicalTraits.includes("Athletic")>> <<if _hasAth>><<set _stealthChance = _stealthChance + 5>><</if>> <<if _stealthChance > 95>><<set _stealthChance = 95>><</if>> <div style="background: #2a1a3e; padding: 16px; border-radius: 10px; border: 1px solid #6e4ea8; margin: 18px 0;"> <p style="color: #c9a9ff; margin: 0 0 6px 0; font-weight: bold;">Roisin's hands work the lock.</p> <p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Stealth skill: 50% base</p> <<if _hasLP>><p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Lock Picking: +25%</p><<else>><p style="color: #888; margin: 3px 0; font-size: 13px;">✗ Lock Picking: +25% (not learned)</p><</if>> <<if _hasCombat>><p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Combat or Martial Arts: +5%</p><</if>> <<if _hasAth>><p style="color: #2ecc71; margin: 3px 0; font-size: 13px;">✓ Athletic: +5%</p><</if>> <p style="color: #c9a9ff; margin: 6px 0 0 0; font-size: 13px; font-weight: bold;">Total: <<= _stealthChance>>%</p> </div> <div style="text-align: center; margin: 24px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #c9a9ff 0%, #6e4ea8 100%); color: white; padding: 12px 28px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Pick the Lock</div>">> <<run advanceTime(15)>> <<if random(1, 100) <= _stealthChance>> <<goto "RoisinUnconsciousBodyScene">> <<else>> <<goto "RoisinBreakInFailure">> <</if>> <</link>> </div> <div style="text-align: center;"> <<set _walkAway = setup.sunfishCuff && setup.sunfishCuff.getRoisinCurrentLocation ? setup.sunfishCuff.getRoisinCurrentLocation() : (_bodyHome || "Plaza")>> <<link "<span style='color: #888; font-size: 13px; text-decoration: underline; cursor: pointer;'>Walk away. Try later.</span>">> <<goto _walkAway>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _bodyHome = $possessionBodyLocation || "StudioApartment">> <<set _preGen = ($possessionPreState && $possessionPreState.gender) ? $possessionPreState.gender : "female">> <<set _preGenitals = ($possessionPreState && $possessionPreState.bodyParts && $possessionPreState.bodyParts.genitals) ? $possessionPreState.bodyParts.genitals : "vagina">> <<set _preChest = ($possessionPreState && $possessionPreState.bodyParts) ? ($possessionPreState.bodyParts.chest || "medium") : "medium">> <<set _preButt = ($possessionPreState && $possessionPreState.bodyParts) ? ($possessionPreState.bodyParts.butt || "medium") : "medium">> <<set _preName = ($possessionPreState && $possessionPreState.firstName) ? $possessionPreState.firstName : "<<= _preName>>">> <<set _preTraits = ($possessionPreState && $possessionPreState.physicalTraits) ? $possessionPreState.physicalTraits : []>> <<set _preMental = ($possessionPreState && $possessionPreState.mentalTraits) ? $possessionPreState.mentalTraits : []>> <<set _preApp = ($possessionPreState && $possessionPreState.appearance) ? $possessionPreState.appearance : {}>> <<set _hasCock = (_preGenitals === "penis" || _preGenitals === "both")>> <<set _hasPussy = (_preGenitals === "vagina" || _preGenitals === "both")>> <<set _has = function(t) { return _preTraits.indexOf(t) !== -1 || _preMental.indexOf(t) !== -1; }>> <<set _hasAny = function(arr) { for (var i = 0; i < arr.length; i++) { if (_has(arr[i])) return true; } return false; }>> /* Pronoun lookup keyed off the player's pre-possession gender. The unconscious body is the player's old form, so its pronouns track that. */ <<set _isMaleBody = (_preGen === "male")>> <<set _bSub = _isMaleBody ? "he" : "she">> <<set _bSubCap = _isMaleBody ? "He" : "She">> <<set _bObj = _isMaleBody ? "him" : "her">> <<set _bPos = _isMaleBody ? "his" : "her">> <<set _bPosCap = _isMaleBody ? "His" : "Her">> <<set _tfKey = "">> <<set _tfLine = "">> <<set _tfActLabel = "">> <<if _hasAny(["Voluptuous Body", "Voluptuous", "Succubus Wings", "Demon Tail", "Succubus"])>> <<set _tfKey = "succubus">> <<set _tfLine = "Even unconscious, the succubus shape under <<= _preName>>'s skin radiates pull. Folded wings tucked under her shoulders. The pillow under her cheek smells of incense and want. The body is broadcasting on a frequency the bones cannot help.">> <<set _tfActLabel = "Drain a kiss from her">> <<elseif _hasAny(["Witch", "Coven Witch", "Witch Soul"])>> <<set _tfKey = "witch">> <<set _tfLine = "Faint violet sigils still crawl under <<= _preName>>'s skin, dim with you absent. The witch <<= _bSub>> became sleeps in the bones whether or not the soul is home. The room hums faint and electric around <<= _bObj>>.">> <<set _tfActLabel = "Trace her witch sigils">> <<elseif _hasAny(["Bimbo", "Bimbo Body"])>> <<set _tfKey = "bimbo">> <<set _tfLine = "<<= _preName>>'s body is plumped and polished into bimbo proportions, an absurd hourglass even in stillness. Lips puffed and softening into the pillow. Skin glossy. The body looks like an advertisement for itself.">> <<set _tfActLabel = "Get sloppy with her bimbo mouth">> <<elseif _hasAny(["Cheshire Cat", "Cheshire", "Cheshire Tail", "Phasing Touch"])>> <<set _tfKey = "cheshire">> <<set _tfLine = "<<= _preName>>'s body fades at the edges and back when you blink, like the artifact has not quite committed to which version of her is here. A faint curling smile lingers on her sleeping mouth.">> <<set _tfActLabel = "Phase your tongue through her">> <<elseif _hasAny(["Siren", "Siren Song"])>> <<set _tfKey = "siren">> <<set _tfLine = "<<= _preName>>'s skin shimmers wet even when dry, faint scales catching light along her ribs and thighs. The body smells of brine and something sweet beneath. A siren sleeping in human shape.">> <<set _tfActLabel = "Sing low against her ear">> <<elseif _hasAny(["Naiad", "Naiad Grace"])>> <<set _tfKey = "naiad">> <<set _tfLine = "<<= _preName>>'s body is laid out in elegant lines, even unconscious. Naiad grace. The shape of her hand resting on the sheet looks like a temple carving.">> <<set _tfActLabel = "Bless her with a slow touch">> <<elseif _hasAny(["Dark Angel", "Fallen Wings"])>> <<set _tfKey = "darkangel">> <<set _tfLine = "Black feather memory still ghosts at <<= _preName>>'s shoulder blades. The bed dips faint where the wings would rest. <<= _preName>>'s body looks like something fallen and not sorry about it.">> <<set _tfActLabel = "Wing-shroud her">> <<elseif _hasAny(["Angel", "Angel Wings", "Halo"])>> <<set _tfKey = "angel">> <<set _tfLine = "Soft white feather memory ghosts at <<= _preName>>'s shoulder blades. The bedside lamp catches a halo on <<= _preName>>'s crown that is not quite there. <<= _preName>>'s face is unfairly serene.">> <<set _tfActLabel = "Wing-shroud her">> <<elseif _hasAny(["Cerberus", "Cerberus Heat"])>> <<set _tfKey = "cerberus">> <<set _tfLine = "<<= _preName>>'s body radiates heat even unconscious. The sheet is slightly singed where her hand rests. A faint sulfur tang hangs in the air. The cerberus sleeps but the temperature is hers.">> <<set _tfActLabel = "Bite her with cerberus heat">> <<elseif _hasAny(["Anubis", "Anubis Mark"])>> <<set _tfKey = "anubis">> <<set _tfLine = "<<= _preName>>'s skin carries faint hieroglyphic ink along her arms, dark in the lamp light. The Anubis is sleeping but the marks are awake.">> <<set _tfActLabel = "Anoint her with oil">> <<elseif _hasAny(["Banshee", "Banshee Wail"])>> <<set _tfKey = "banshee">> <<set _tfLine = "<<= _preName>>'s hair lifts faintly off the pillow on its own, a ghost of the wail still in the body. The room is very quiet around <<= _bObj>>, the kind of quiet that listens back.">> <<set _tfActLabel = "Whisper into her ear">> <<elseif _hasAny(["Cupid", "Cupid Arrow", "Cupid Kiss"])>> <<set _tfKey = "cupid">> <<set _tfLine = "Faint pink lives under <<= _preName>>'s skin even at rest. <<= _preName>>'s mouth is already curled in something soft, like <<= _bSub>> is dreaming a kind dream. Cupid never stops working in there.">> <<set _tfActLabel = "Kiss her into a sweet dream">> <<elseif _hasAny(["Dominatrix", "Mistress"])>> <<set _tfKey = "domme">> <<set _tfLine = "Even slack she looks like she is in charge. The way <<= _preName>>'s wrist bends is a command. The body is built to be obeyed. It is strange seeing <<= _bObj>> this still.">> <<set _tfActLabel = "Dominate her quietly">> <<elseif _hasAny(["EGirl", "E-Girl", "Stream Goblin"])>> <<set _tfKey = "egirl">> <<set _tfLine = "<<= _preName>>'s body is laid out in egirl pinup, choker still around her neck, dyed strands fanning across the pillow. Even passed out <<= _bSub>> is camera ready.">> <<set _tfActLabel = "Stream-style tease her">> <<elseif _hasAny(["Gyaru"])>> <<set _tfKey = "gyaru">> <<set _tfLine = "Tan, gold-glossed, manicure on the hand resting on the sheet. Even unconscious she is dressed up. <<= _preName>>'s gyaru body wears self-presentation like skin.">> <<set _tfActLabel = "Gyaru kiss her gloss off">> <<elseif _hasAny(["GymBunny", "Gym Bunny"])>> <<set _tfKey = "gymbunny">> <<set _tfLine = "<<= _preName>>'s body is a gym bunny on display. Lean, sun-kissed, hair still in a high ponytail from the morning. Even slack the muscle reads.">> <<set _tfActLabel = "Pin her down properly">> <<elseif _hasAny(["Himbo", "Hunk"])>> <<set _tfKey = "himbo">> <<set _tfLine = "<<= _preName>>'s body is broad, bronzed, big and dumb and gorgeous in repose. The sweet golden retriever face is fully unguarded.">> <<set _tfActLabel = "Big dumb love her">> <<elseif _hasAny(["Automaton", "Clockwork"])>> <<set _tfKey = "automaton">> <<set _tfLine = "<<= _preName>>'s body is half artifice and half flesh, the seams faint along her wrists and ankles. A soft tick at the throat where a clockwork pulse keeps idling.">> <<set _tfActLabel = "Run her clockwork carefully">> <</if>> <div style="background: radial-gradient(ellipse at center, #1a0a28 0%, #000 75%); min-height: 100vh; padding: 30px 20px;"> <div style="max-width: 760px; margin: 0 auto; color: #ddd; line-height: 1.8;"> <h1 style="color: #c9a9ff; text-align: center;">Inside Your Own Door</h1> <<if !$breakInIntroDone>> <p>The lock surrenders with a soft click and Roisin's hand turns the knob. You step through. Familiar smell. Familiar light. Familiar body, slumped where the artifact left it.</p> <p>You stand over yourself for a long second. Your jaw is slack. Your chest rises and falls. Your eyelids twitch with whatever the artifact is letting you dream. The face you have known your whole life looks small from up here.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Hello, you. Did you miss me?"</p> <p>Roisin's grin pulls at your mouth. You crouch beside the body, slide a gloved hand under <<= _preName>>'s shoulders, and lift. Her muscle does the work for you. <<= _preName>>'s body lands soft on the mattress and one arm flops out across the sheet, palm up, exposed. You close the door and lock it from the inside, because old habits.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Now then. Let us be properly weird about this."</p> <<run State.variables.breakInIntroDone = true>> <</if>> <<if !$breakInCurrentAct>> <div style="background: #1a0a28; border: 2px solid #6e4ea8; border-radius: 10px; padding: 20px; margin: 20px 0; box-shadow: 0 0 22px rgba(201,169,255,0.18);"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">What you are looking at</h3> <p>You let your eyes take stock. You have lived in this body your whole life. You have never been able to look at it from outside.</p> <<if _preApp.hairLength || _preApp.hairColor>> <p><<= _preName>>'s <<= _preApp.hairLength || "">> <<= _preApp.hairColor ? _preApp.hairColor.toLowerCase() : "">> hair is fanned across the pillow, the way it falls when <<= _bSub>> lets it loose.</p> <</if>> <<if _preApp.skinTone === "pale">> <p><<= _preName>>'s pale skin reads every blue vein and every freckle in the lamp light. Porcelain. Easy to bruise. Easy to mark.</p> <<elseif _preApp.skinTone === "tan">> <p><<= _preName>>'s tan skin glows warm gold in the lamp light, that sun-kissed read that does not need makeup to look alive.</p> <<elseif _preApp.skinTone === "dark">> <p><<= _preName>>'s dark skin holds the lamp light like polished wood, every line of muscle and bone gathered into rich shadow.</p> <<else>> <p><<= _preName>>'s skin reads even and warm in the lamp light.</p> <</if>> <<if _has("Athletic")>><p>The cut of <<= _preName>>'s obliques. The lean stomach you remember training for. Even slack, the muscle reads through the skin like it is proud of itself.</p><</if>> <<if _has("Muscular")>><p>Ropes of <<= _preName>>'s muscle along the arms you used to flex in private mirrors. Even unconscious, the body looks like it could throw you across the room.</p><</if>> <<if _has("Curvy")>><p>The soft generous swell of <<= _preName>>'s hips. The way <<= _preName>>'s waist nips in under her ribs. Curves you used to photograph in the dim of your bathroom and never share.</p><</if>> <<if _has("Petite") || _has("Small Frame")>><p>Small in the way that hides nothing. Doll bones at <<= _preName>>'s wrists. The whole body fits in the middle third of the bed.</p><</if>> <<if _has("Tall")>><p>Long old legs sprawled the length of the bed, ankles crossing past the foot of the mattress.</p><</if>> <<if _has("Skinny")>><p>Thin and elegant. Ribs counted easy under shallow breath.</p><</if>> <<if _has("Plus Size") || _has("Plump") || _has("Chubby")>><p>The soft luxurious mass of her, every curve you ever apologized for in mirrors now resting unbothered. The mattress takes <<= _bObj>> weight like it was built for exactly this.</p><</if>> <<if _has("Thick")>><p>The heavy gorgeous weight of <<= _preName>>'s thighs. The press of <<= _preName>>'s hips against the sheet, dimpling fabric.</p><</if>> <<if _has("Tattooed")>><p>Ink crawls along <<= _preName>>'s shoulder and inner arm. Sleeves of stories you never told anyone. The lamp light makes the linework sharp.</p><</if>> <<if _has("Pierced")>><p>Studs and rings catching the lamp at <<= _preName>>'s ears, <<= _preName>>'s navel, lower if <<= _bSub>> went there.</p><</if>> <<if _has("Hairy")>><p>Soft fur on <<= _preName>>'s chest and arms, dark against the lamp.</p><</if>> <<if _has("Smooth") || _has("Hairless")>><p>Bare polish from chin to ankle. Every line of the body uninterrupted, soft as a poured candle.</p><</if>> <<if _has("Freckled")>><p>Constellations of freckles across <<= _preName>>'s shoulders and the bridge of <<= _preName>>'s nose.</p><</if>> <<if _has("Scarred")>><p>The white history of every old scar. Each one a date. Each one a story you only ever half told.</p><</if>> <<if _has("Flexible")>><p>Even unconscious <<= _preName>>'s hip falls open at an easy folded angle that most bodies cannot manage awake.</p><</if>> <<if _has("Strong")>><p>Strength still readable in the lay of <<= _preName>>'s shoulders even at rest.</p><</if>> <<if _has("Soft")>><p>Softness that resists nothing under your gloved fingertips.</p><</if>> <<if _preChest === "flat masculine">><p><<= _preName>>'s chest flat and cut, pectorals you used to squeeze in the mirror after a hot shower.</p> <<elseif _preChest === "flat">><p><<= _preName>>'s chest flat as paper, only the smallest budding of pink.</p> <<elseif _preChest === "small">><p>Small pert old breasts that sit high on her ribcage. Pink at the tips. Roisin's gloved palm could swallow either of them whole.</p> <<elseif _preChest === "medium">><p><<= _preName>>'s breasts handful sized and soft, settling on her ribs as <<= _bSub>> breathes.</p> <<elseif _preChest === "large">><p><<= _preName>>'s breasts large and heavy, falling either side of <<= _preName>>'s chest. The lamp light pools in the cleft between them.</p> <<elseif _preChest === "huge">><p><<= _preName>>'s breasts huge enough to spill over <<= _preName>>'s upper arms. The kind of chest that has its own gravity.</p> <<elseif _preChest === "giant">><p><<= _preName>>'s breasts giant and gravity-defying even unconscious.</p> <<elseif _preChest === "gigantic">><p><<= _preName>>'s breasts gigantic, each one bigger than your gloved hand can cup.</p> <</if>> <<if _preButt === "flat">><p>Flat behind. Just the line of <<= _preName>>'s back into <<= _preName>>'s thighs without ceremony.</p> <<elseif _preButt === "small">><p>Small tight rear.</p> <<elseif _preButt === "medium">><p>Soft round backside, fitting nicely against the sheet.</p> <<elseif _preButt === "large">><p><<= _preName>>'s large ass curves outward against the mattress, filling out the shape of any pants <<= _bSub>> ever owned.</p> <<elseif _preButt === "huge">><p><<= _preName>>'s huge ass jiggles faintly when you shift her hip. Impossible to hide.</p> <<elseif _preButt === "giant">><p><<= _preName>>'s giant ass dominates the lower half of the bed.</p> <<elseif _preButt === "gigantic">><p><<= _preName>>'s gigantic ass is a serious geographic feature.</p> <</if>> <<if _hasCock && _hasPussy>><p>Between <<= _preName>>'s thighs, both. Soft cock resting against <<= _preName>>'s folds, pussy beneath. The body has options.</p> <<elseif _hasCock>><p>Between <<= _preName>>'s thighs, the soft length of <<= _preName>>'s cock, resting heavy against <<= _preName>>'s hip.</p> <<elseif _hasPussy>><p>Between <<= _preName>>'s thighs, the bare soft folds of <<= _preName>>'s cunt. Closed for now. Familiar shape.</p> <</if>> <<if _has("Confident") || _has("Dominant")>><p>The face that runs the room when <<= _bSub>> is awake is gone right now. The set of the jaw is still hers, but soft.</p> <<elseif _has("Shy") || _has("Insecure")>><p>The shy line of the shoulder <<= _bSub>> always carries is gone in the slack. Even her body is letting itself be seen for once.</p> <<elseif _has("Sweet") || _has("Kind")>><p>Even unconscious the face is the kind face. The kind that listens to you when you stay too long in your own head.</p> <</if>> <<if _tfLine>> <p style="color: #c9a9ff; font-style: italic; border-left: 3px solid #6e4ea8; padding-left: 12px; margin: 14px 0;"><<= _tfLine>></p> <</if>> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. Look at the both of you in this state."</p> </div> <div style="background: #2a1a3e; padding: 20px; border-radius: 10px; border: 1px solid #6e4ea8; margin: 18px 0;"> <h3 style="color: #c9a9ff; margin: 0 0 12px 0;">What do you do to <<= _bObj>>?</h3> <<set _acts = $breakInActs || []>> <<if !_acts.includes("strip")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>👕 Strip her bare and look properly</div>">><<set $breakInCurrentAct = "strip">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Stripped her bare</div><</if>> <<if !_acts.includes("worship")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>💋 Worship every inch of her</div>">><<set $breakInCurrentAct = "worship">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Worshiped her</div><</if>> <<if !_acts.includes("look")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>👁️ Just look at her, no touch yet</div>">><<set $breakInCurrentAct = "look">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Looked her over</div><</if>> <<if _hasCock>> <<if !_acts.includes("suck")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>👄 Suck <<= _preName>>'s cock</div>">><<set $breakInCurrentAct = "suck">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Sucked her cock</div><</if>> <<if !_acts.includes("ride")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>🍑 Ride <<= _preName>>'s cock</div>">><<set $breakInCurrentAct = "ride">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Rode her</div><</if>> <</if>> <<if _hasPussy>> <<if !_acts.includes("eat")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>👅 Eat <<= _preName>>'s cunt</div>">><<set $breakInCurrentAct = "eat">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Ate her out</div><</if>> <<if !_acts.includes("trib")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>💦 Trib her, slick on slick</div>">><<set $breakInCurrentAct = "trib">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Tribbed her</div><</if>> <<if !_acts.includes("finger")>><<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #6e4ea8;'>✋ Finger her open slow</div>">><<set $breakInCurrentAct = "finger">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Fingered her</div><</if>> <</if>> <<if _tfKey && !_acts.includes("tf")>><<link "<div style='display: block; background: linear-gradient(135deg, #6e4ea8 0%, #1a0a28 100%); color: #ffd6ec; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; border: 1px solid #c9a9ff;'>✨ <<= _tfActLabel>></div>">><<set $breakInCurrentAct = "tf">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<elseif _tfKey>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Used her transformation</div><</if>> <<if !_acts.includes("mark")>><<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 10px 16px; border-radius: 6px; margin: 6px 0; cursor: pointer; font-weight: bold; border: 1px solid #c9a9ff;'>🌹 Mark her with Roisin's cum</div>">><<set $breakInCurrentAct = "mark">><<set $breakInSubActs = []>><<goto "RoisinUnconsciousBodyScene">><</link>><<else>><div style="display: block; background: #2a1a3e; color: #888; padding: 10px 16px; border-radius: 6px; margin: 6px 0; border: 1px solid #444;">✓ Marked her</div><</if>> </div> <div style="text-align: center; margin: 28px 0;"> <<set _spot = setup.sunfishCuff && setup.sunfishCuff.getRoisinCurrentLocation ? setup.sunfishCuff.getRoisinCurrentLocation() : "Plaza">> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 14px 32px; border-radius: 10px; cursor: pointer; font-weight: bold;'>🌙 Slip back into the night</div>">> <<set _actsCount = ($breakInActs || []).length>> <<run advanceTime(15 + _actsCount * 12)>> <<run State.variables.brokeIntoOwnHomeCount = (State.variables.brokeIntoOwnHomeCount || 0) + 1>> <<set $breakInActs = []>> <<set $breakInCurrentAct = null>> <<set $breakInSubActs = []>> <<set $breakInIntroDone = false>> <<goto _spot>> <</link>> </div> <<else>> <div style="background: #1a0a28; border: 2px solid #c9a9ff; border-radius: 10px; padding: 22px; margin: 18px 0; box-shadow: 0 0 22px rgba(255,143,200,0.18);"> <<if $breakInCurrentAct === "strip">> <p>You take your time with the buttons. The shirt comes apart in Roisin's gloved hands like <<= _bSub>> has done it a thousand times. The waistband peels down past <<= _preName>>'s hips. Underwear last, drawn slow over <<= _preName>>'s thighs and dropped to the floor like punctuation.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"There you are. All of you. About time someone got a proper look."</p> <p>You sit back on your heels and let your eyes do an unhurried tour. Collarbone. Sternum. The dip below <<= _preName>>'s ribs. The line of <<= _preName>>'s hip down to <<= _preName>>'s thigh. You knew every inch of this body the way you know a sentence you have repeated to yourself for years, but you have never been the one reading.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Bit unfair, you. You have been hiding all this from me forever. Not anymore."</p> <<elseif $breakInCurrentAct === "look">> <p>You sit on the edge of the bed and you do not touch. Not yet. Roisin's elbow on <<= _preName>>'s knee, Roisin's chin on Roisin's gloved hand. You let yourself look the way nobody has ever looked at this body. Slow. Generous. Unembarrassed.</p> <p>You watch <<= _preName>>'s chest rise and fall. The faint flutter at <<= _preName>>'s throat where the pulse lives. The twitch at the corner of <<= _preName>>'s mouth like the body is tasting something in a dream.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. You are lovely. I had no idea you were just lovely."</p> <p>You sit there longer than you meant to. The artifact stays warm at your wrist. It does not hurry you.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"All those years. All those mirrors. None of them showed you what you actually look like asleep."</p> <<elseif $breakInCurrentAct === "suck">> <<set _subs = $breakInSubActs || []>> <p>You settle Roisin's gloved fingers around the soft length of <<= _preName>>'s cock. <<= _bSubCap>> does not need to be hard yet. You take <<= _bObj>> in your mouth like that, soft, the body remembering before the mind would.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ, you. I have been wanting your cock since I figured out you had one. Bit awkward you are not awake to enjoy this."</p> <<if _subs.includes("lick")>> <p>Roisin's tongue drags from the base of <<= _preName>>'s cock to the tip in one slow flat stripe. The body shivers under the wet heat. <<= _preName>>'s cock answers, swelling against your tongue, twitching when you reach the head. You circle the crown with the point of your tongue and the body underneath you sighs out a small unconscious sound.</p> <p>You do it again. Slower. The artifact warms at her wrist. It is enjoying this with you.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"There you are. There you are. Hello, gorgeous."</p> <</if>> <<if _subs.includes("deepthroat")>> <p>You drop Roisin's mouth all the way down on <<= _preName>>'s cock in one smooth slide. Her trained throat opens like a key in a lock. <<= _preName>>'s length disappears past her lips and the soft heat of the back of her throat closes around the head and the body underneath you gives one full-body twitch that almost rolls <<= _preName>>'s hips off the bed.</p> <p>You hold there. Roisin's nose against the soft of <<= _preName>>'s belly. Her ginger ponytail spilled across <<= _preName>>'s thigh. You hum a low note around <<= _preName>>'s cock just to feel the body answer it.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. Right down. You are choking yourself on her cock and <<= _bSub>> will not even know."</p> <</if>> <<if _subs.includes("choke")>> <p>You pull back to the head and slam Roisin's mouth back down. Again. Again. Spit catches at the corner of her mouth and slides down her chin. Tears prick at the corners of Roisin's eyes from the throat work and the smell of <<= _preName>>'s cock fills your whole face. You make yourself gag once on purpose, the squeeze of Roisin's throat dragging an unconscious moan out of <<= _preName>>'s chest.</p> <p>You pull off wet and gasping. A long string of spit hangs between <<= _preName>>'s cock and Roisin's swollen lower lip. You laugh under your breath, mouth open, looking at it.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Filthy. Both of us. Not a single witness. Perfect."</p> <</if>> <<if _subs.includes("balls")>> <p>Roisin's hand keeps a slow lazy stroke on <<= _preName>>'s cock as you tilt <<= _bObj>> head and trace your tongue lower. You suck one of <<= _preName>>'s balls into Roisin's mouth, slow, heavy. The body twitches. You roll it across your tongue and feel the soft vein pulse against the flat of it, then switch to the other.</p> <p>You drag Roisin's tongue back up the underside in one long lick. Spit everywhere now. <<= _preName>>'s cock so hard it bounces against <<= _preName>>'s belly when you let go.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Pretty boy. Pretty pretty boy. I am going to ruin you and you will not remember a thing."</p> <</if>> <<if _subs.includes("edge")>> <p>You feel <<= _preName>>'s hips start that small unconscious lift, that pre-twitch the body does when it is about to cross. You pull off wet and let go. <<= _preName>>'s cock bounces hard against <<= _preName>>'s stomach, leaking, the slit weeping a fat clear bead. The body whines a little in its sleep, hips rolling toward nothing.</p> <p>You wait. Three breaths. Roisin's gloved hand strokes down the inside of <<= _preName>>'s thigh, idle, owning. Then you take <<= _preName>>'s cock back into Roisin's mouth slow, watching the slack face, holding the edge again.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Nope. Not yet. I am not done with you, you greedy thing."</p> <</if>> <<if _subs.includes("finish")>> <p>You let <<= _bObj>> have it this time. Roisin's mouth working <<= _preName>>'s cock in a steady relentless slide, throat opening on every drop. The body crests under you, and you hold yourself there as <<= _preName>>'s cock empties in long pulses down Roisin's throat. You swallow what you can and let the rest spill across your tape-wrapped chest like a drink <<= _bSub>> was never going to share.</p> <p>The body sighs out one long content breath and goes still again. You sit back on your heels with Roisin's lower lip swollen and shining. The artifact glows pleased at your wrist.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. That was cheating. I do not care. I will be back tomorrow."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("lick")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>👅 Lick slow up the underside</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["lick"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("deepthroat")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌹 Take her down to the root</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["deepthroat"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("choke")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💋 Choke yourself a little</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["choke"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("balls")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🥥 Suck <<= _preName>>'s balls into your mouth</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["balls"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("edge")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Edge her, hold <<= _bObj>> at the brink</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["edge"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("finish")>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; font-weight: bold; font-size: 14px;'>Take her over the edge</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "ride">> <<set _subs = $breakInSubActs || []>> <p>You climb up <<= _preName>>'s body with Roisin's deliberate weight. Her tape wrap pulls tight across her chest. You guide <<= _preName>>'s cock between <<= _preName>>'s thighs and against the slick heat of Roisin's pussy and you stop, head pressed against her entrance, watching <<= _preName>>'s slack face for a long second.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Look at us. Look at the both of us. The artifact has terrible judgement and excellent taste."</p> <<if _subs.includes("slow")>> <p>You sink down on <<= _preName>>'s cock one breath at a time. Roisin's pussy stretches around <<= _preName>>'s length and you feel the connection light up on both ends at once, the tight clutch of her cunt and the buried heat of <<= _preName>>'s cock at the same time. You bottom out and hold there, working your hips in slow tight circles, grinding her down into the hilt.</p> <p>Roisin's eyes flutter closed. Her tape wrap rises and falls. <<= _preName>>'s hips roll up to meet her without permission, the body tracking what it cannot help wanting.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. Aye. Right there. Stay right there."</p> <</if>> <<if _subs.includes("hard")>> <p>You let <<= _bObj>> hips go. Roisin's thighs flex and you start to bounce on <<= _preName>>'s cock with the easy practiced rhythm of a woman who knows exactly what <<= _bSub>> likes. Slap of skin on skin. Her tape wrap straining as her chest jumps with every drop. The bed creaks under the pace. <<= _preName>>'s hands flop limp on either side of her hips, useless except for the occasional twitch when the body remembers something.</p> <p>You ride <<= _bObj>> hard. <<= _preName>>'s cock works deep and Roisin's cunt squeezes around it tighter every drop.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. You are filling her right up. You will never know. That is the best part."</p> <</if>> <<if _subs.includes("reverse")>> <p>You spin on <<= _preName>>'s cock without letting <<= _bObj>> slip out. Roisin's ass faces <<= _preName>>'s slack face now, <<= _preName>>'s cock buried up into her cunt from this new angle. You drop forward onto Roisin's hands, her ass high and round and absolutely on display for a sleeping audience of one. You start to fuck back onto <<= _preName>>'s cock from the new angle.</p> <p>The press of <<= _preName>>'s shaft hits a different spot inside <<= _bObj>>. Roisin's mouth falls open. Her ginger ponytail swings against <<= _preName>>'s thighs.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Pretty view, you. Even with no one watching but a wall."</p> <</if>> <<if _subs.includes("hands")>> <p>You drop forward and gather both of <<= _preName>>'s wrists in one of Roisin's gloved hands and pin them above <<= _preName>>'s head against the pillow. The body lets you. Even unconscious it lets you. You start to grind down on <<= _preName>>'s cock with the slow controlled drag of someone who is not in a hurry.</p> <p>You bend low. Roisin's mouth at <<= _preName>>'s ear. Tape-wrapped chest dragging across <<= _preName>>'s chest. <<= _preName>>'s cock buried deep.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Mine for tonight. Whether you want to be or not. Lucky for you, you do."</p> <</if>> <<if _subs.includes("edge_ride")>> <p>You feel <<= _preName>>'s hips trying to lift toward the edge again, the body climbing under you. You stop completely. Roisin sits sunk on <<= _preName>>'s cock and refuses to move. The body twitches up into you, looking for friction. None on offer.</p> <p>You laugh once, soft and mean, and run a gloved fingertip down <<= _preName>>'s cheek.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Not yet. I want this to last. You can wait. Look at you, you can wait beautifully."</p> <</if>> <<if _subs.includes("finish")>> <p>You let <<= _bObj>> have it. Roisin's hips slam down at the rhythm her body wants, the bed creaking under you, her tape wrap soaked through with sweat. You feel both edges climbing at the same time. You hold for one impossible breath and let go.</p> <p><<= _preName>>'s cock empties up into her in long pulses. Roisin's cunt clenches around <<= _preName>>'s length and milks every drop. The body underneath shudders one long breath and goes still. You stay sat on <<= _preName>>'s cock until you stop pulsing around <<= _bObj>>, then ease off slow, watching the slow drip of <<= _preName>>'s come slide back out of Roisin's cunt and pool on <<= _preName>>'s hip.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Look at that. That is the prettiest mess I have ever made."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("slow")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌊 Slow grind, deep</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["slow"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("hard")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💥 Ride her hard and fast</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["hard"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("reverse")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🪞 Turn around, ass in her face</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["reverse"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("hands")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✋ Pin <<= _preName>>'s hands above her head</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["hands"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("edge_ride")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Hold her at the edge, do not let <<= _bObj>> come</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["edge_ride"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("finish")>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; font-weight: bold; font-size: 14px;'>Take her over the edge</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "eat">> <<set _subs = $breakInSubActs || []>> <p>You settle low between <<= _preName>>'s thighs and slide Roisin's gloved palms under <<= _preName>>'s hips, lifting them to your mouth like a gift you finally get to open. You take a long deep breath against <<= _preName>>'s cunt before you do anything. Just smell her. Just take that in.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. So that is what I have always smelled like. No wonder I never told myself."</p> <<if _subs.includes("circle")>> <p>You drag the tip of Roisin's tongue in lazy slow circles around <<= _preName>>'s clit, never quite landing on it. <<= _preName>>'s hips lift up to chase the contact and find nothing. The body underneath you arches faintly into the sheets, a soft frustrated sound rising out of <<= _preName>>'s throat without her in there to feel embarrassed about it.</p> <p>You smile against <<= _preName>>'s folds and do another slow circle. The artifact warms.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Begging in your sleep. Bold. I respect it."</p> <</if>> <<if _subs.includes("bury")>> <p>You stop teasing. Roisin's mouth seals over <<= _preName>>'s cunt and you eat her like the starving thing you are. Tongue deep in <<= _preName>>'s entrance, nose ground against <<= _preName>>'s clit, slick smearing all over Roisin's chin and jaw. The body underneath you shakes hard. <<= _preName>>'s hips push up into your face hungry, and you go with it, riding <<= _bObj>> motion, letting <<= _bObj>> grind herself on your mouth.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Oh. Oh, you taste like I never knew. I have been criminally underrated all these years."</p> <</if>> <<if _subs.includes("fingers_in")>> <p>You ease two of Roisin's gloved fingers into <<= _preName>>'s entrance, slow, slick, the leather catching faintly at <<= _preName>>'s folds. You curl them up against the front wall of <<= _preName>>'s cunt and at the same time wrap Roisin's lips around <<= _preName>>'s clit and suck. The body underneath you bows up off the bed at a violent unconscious angle.</p> <p>You hold <<= _bObj>> there. Sucking. Curling. The body shaking under your mouth and your hand at once.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. Found the spot. I am keeping that."</p> <</if>> <<if _subs.includes("tongue_fuck")>> <p>You stiffen Roisin's tongue and shove it inside <<= _preName>>'s cunt, fucking <<= _bObj>> on it slow and shallow. <<= _preName>>'s slick floods over your lower lip. Roisin's nose presses hard against <<= _preName>>'s clit on every push and the friction makes the body underneath shudder out a long unconscious moan you have never let yourself make awake.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"That sound. I am taking that one home."</p> <</if>> <<if _subs.includes("edge_eat")>> <p>You feel the body climb. <<= _preName>>'s thighs squeezing tighter around Roisin's head, <<= _preName>>'s hips lifting in that pre-twitch <<= _bSub>> always does right before. You pull off <<= _preName>>'s clit completely. The body freezes mid-arch, suspended, then drops back to the sheet with a small sleeping whine.</p> <p>You wait. Roisin's gloved fingertip traces a slow circle on the inside of <<= _preName>>'s thigh. Then you go back in.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"No. Not yet. You owe me longer than that."</p> <</if>> <<if _subs.includes("finish")>> <p>You stop holding <<= _bObj>> back. Roisin's mouth seals over <<= _preName>>'s clit and her gloved fingers curl up inside <<= _preName>>'s cunt and you do not stop until you feel the body crash against your mouth in a long shuddering wave. <<= _preName>>'s slick floods over Roisin's lips. <<= _preName>>'s hips spasm three slow beats and go still again.</p> <p>You stay there as the body relaxes, kissing <<= _preName>>'s folds soft and tender, easing your fingers out one knuckle at a time. You drag the back of Roisin's wrist across her glistening chin and grin up at the slack ceiling of a face.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Sleep well, you. I will come back hungrier next time."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("circle")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>👅 Circle her clit slow</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["circle"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("bury")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌹 Bury your face deep, sloppy</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["bury"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("fingers_in")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✋ Slide two fingers in while you suck</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["fingers_in"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("tongue_fuck")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🐍 Tongue-fuck <<= _bObj>> entrance</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["tongue_fuck"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("edge_eat")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Pull off when <<= _bSub>> gets close</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["edge_eat"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("finish")>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; font-weight: bold; font-size: 14px;'>Take her over the edge</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "trib">> <<set _subs = $breakInSubActs || []>> <p>You climb up the bed and settle Roisin's thighs over <<= _preName>>'s thigh, hooking your hips together at an angle that fits both <<= _preName>>'s cunt and Roisin's together in slick contact. You roll the very first slow grind. The wet contact is unbelievable on both sides at once.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ. Oh that is going to be a problem."</p> <<if _subs.includes("slow_grind")>> <p>You start a slow rocking rhythm. Roisin's pussy and <<= _preName>>'s pussy slide against each other in long deliberate drags, slick on slick, friction lighting up clits at the same time. Her tape wrap presses against <<= _preName>>'s breasts on every push. <<= _preName>>'s hips lift up under Roisin's without permission, the body climbing to meet her.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Right there. Right there. Together."</p> <</if>> <<if _subs.includes("slap")>> <p>You sit up tall on Roisin's hips and start to drop <<= _bObj>> cunt onto <<= _preName>>'s cunt, harder and faster, slap of slick on slick. The body underneath you shakes with every impact. Roisin's tape wrap soaks through. Both clits catch on each other on every meeting and the heat builds fast.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Loud. Filthy. Nobody to hear. I love it."</p> <</if>> <<if _subs.includes("leg_lift")>> <p>You lift <<= _preName>>'s leg up onto Roisin's shoulder and the angle changes everything. Both your cunts press tighter, deeper. You can feel <<= _preName>>'s clit drag against Roisin's with every roll. The body underneath you whines a sleeping whine that goes straight into Roisin's belly.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Ah. Better. Closer. I knew you had it in you."</p> <</if>> <<if _subs.includes("fingers_trib")>> <p>Roisin's hand slides between you both. Two of her gloved fingers in <<= _preName>>'s cunt while her own pussy keeps grinding her own ache into <<= _preName>>'s hip. You feel everything from three places at once. <<= _preName>>'s cunt squeezing your fingers. Roisin's clit dragging on <<= _preName>>'s skin. <<= _preName>>'s slick coating her gloved knuckles.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Three points of contact. Roisin Sullivan does not do anything halfway."</p> <</if>> <<if _subs.includes("edge_trib")>> <p>You feel both edges starting to climb. You stop the grind dead. The body underneath you twitches up looking for the friction that is no longer there. You laugh, low and pleased, and trail Roisin's fingertip down <<= _preName>>'s sternum.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Not yet, you. We are nowhere near done with each other."</p> <</if>> <<if _subs.includes("finish")>> <p>You let it go. Roisin's hips set a hard relentless rhythm and you grind down on <<= _preName>>'s cunt without mercy until the wave hits both of you at once. Two slow climaxes break in time, and Roisin laughs once low and pleased and rocks forward to catch herself on her gloved hands above <<= _preName>>'s chest. Slick everywhere. Sheets soaked.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Marked the bed. Marked you. Marked me. Good night's work."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("slow_grind")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌊 Slow grind, hip to hip</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["slow_grind"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("slap")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💥 Slap your pussy down hard on <<= _bObj>></div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["slap"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("leg_lift")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🦵 Hook <<= _preName>>'s leg over your shoulder</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["leg_lift"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("fingers_trib")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✋ Slide two fingers in while you grind</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["fingers_trib"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("edge_trib")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Hold yourself at the edge</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["edge_trib"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("finish")>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; font-weight: bold; font-size: 14px;'>Take her over the edge</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "finger">> <<set _subs = $breakInSubActs || []>> <p>You sit beside the bed and trace one of Roisin's gloved fingers along <<= _preName>>'s folds. Just feeling. The leather catches faint at her wet entrance. The body underneath you opens easy under the press, slick already, honest in a way her mind never quite was.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Right then. Let us see how loud you get when you do not have to perform for anyone."</p> <<if _subs.includes("two_curl")>> <p>You slide two fingers in to the second knuckle and curl them up. Right there. The body underneath you twitches hard. You curl them again, slow and rhythmic, and Roisin's free hand settles on <<= _preName>>'s belly to feel the contractions from outside while the inside answers her steady.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"There. Got you. You knew about that and never told me."</p> <</if>> <<if _subs.includes("deep_palm")>> <p>You slide all the way in to the knuckle and rock the heel of Roisin's palm against <<= _preName>>'s clit at the same time. Long slow strokes. <<= _preName>>'s cunt clutches around your fingers every time you rock back. The body underneath you arches faint into every press.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"That is the rhythm. Slow as I can stand it. Slower."</p> <</if>> <<if _subs.includes("thumb_clit")>> <p>You add Roisin's thumb to the pressure on <<= _preName>>'s clit while two fingers stay curled inside. Slow tight circles. <<= _preName>>'s hips start a small unconscious rolling motion, riding your hand while <<= _bSub>> sleeps. The slick pools into Roisin's palm.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Riding my hand in your sleep. That is the rudest most gorgeous thing I have ever seen."</p> <</if>> <<if _subs.includes("four")>> <p>You ease a third finger in. The body underneath you sucks them in eager. A fourth, slow, stretching <<= _preName>>'s cunt wider than usual. Roisin's other gloved hand smooths down <<= _preName>>'s belly to keep her relaxed for it. The body takes them.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"So much room when you are not awake to clench. Look at you take me."</p> <</if>> <<if _subs.includes("edge_finger")>> <p>You feel <<= _preName>>'s cunt clutching the way it does at the edge. You pull your fingers out completely. The body underneath you twitches at the sudden empty, hips lifting into nothing. You wait. Two breaths. Then you slide in again, slower than before.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"I will keep you here all night if I have to. The artifact does not check the clock."</p> <</if>> <<if _subs.includes("finish")>> <p>You take <<= _bObj>> over slow. Two fingers curled, thumb circling steady, the rhythm relentless. The body underneath you arches off the sheet and crests in a long shuddering wave that drenches Roisin's gloved knuckles. <<= _preName>>'s cunt clenches and clenches around your fingers, then slowly relaxes. <<= _preName>>'s breath evens out.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Sleep well, you greedy thing. I am marking that one in the calendar."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("two_curl")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✌️ Two fingers curled up against her g-spot</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["two_curl"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("deep_palm")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🤚 Knuckle deep, palm grinding her clit</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["deep_palm"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("thumb_clit")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>👍 Thumb circles on her clit</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["thumb_clit"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("four")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🤜 Stretch her with four fingers</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["four"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("edge_finger")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Stop right before <<= _bSub>> crests</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["edge_finger"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("finish")>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; font-weight: bold; font-size: 14px;'>Take her over the edge</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "worship">> <<set _subs = $breakInSubActs || []>> <p>You start at <<= _preName>>'s forehead and Roisin's lips press there once, soft, and the body sighs out a slow breath as if it heard the kindness. You take your time.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Hello, you. You have been a stranger to yourself. Not anymore."</p> <<if _subs.includes("face")>> <p>Roisin's mouth moves slow over <<= _preName>>'s face. Eyelid. The bridge of <<= _preName>>'s nose. The high of <<= _preName>>'s cheekbone. The corner of <<= _preName>>'s jaw. <<= _preName>>'s earlobe gets a soft suck. <<= _preName>>'s slack mouth gets a long open kiss with a slip of tongue, and the body responds the way bodies do, opening just enough for you, sleeping right through it.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"There is the mouth I have been chasing. Hello, mouth."</p> <</if>> <<if _subs.includes("throat")>> <p>Roisin's mouth fastens at <<= _preName>>'s pulse. You suck slow and patient. The skin reddens, then bruises, a dark plum bloom rising at the side of <<= _preName>>'s neck where any shirt will fail to hide it. The body underneath you shudders soft under the pressure. The pulse jumps once.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Tomorrow you will see that and have no idea how you got it. Lucky you."</p> <</if>> <<if _subs.includes("chest")>> <p>You spend a long greedy stretch on <<= _preName>>'s chest, kissing, sucking, biting soft. You leave faint pink marks in the soft of every spot a shirt would cover, the curve of one breast, the line under the other, the soft of <<= _preName>>'s sternum. You take Roisin's tape-wrapped weight against <<= _preName>>'s chest and grind down once, just to feel both at once.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Both of us. Pressed up. I want to live in this sentence."</p> <</if>> <<if (_has("Tattooed")) && _subs.includes("tattoo")>> <p>You trace each line of <<= _preName>>'s ink with the tip of your tongue, every story <<= _bSub>> never told yourself. The sleeve along <<= _preName>>'s shoulder. The piece on <<= _preName>>'s hip. The smaller hidden ones. You suck a slow soft mark right next to one of them, leaving a fresh pink bruise alongside the old black line.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"All of these. All of these are mine to know now. Hello, history."</p> <</if>> <<if (_has("Scarred")) && _subs.includes("scar")>> <p>You take <<= _preName>>'s scars one at a time. The one on <<= _preName>>'s knee. The one on <<= _preName>>'s hip. The one <<= _bSub>> never explained to anyone, not even you. Roisin's lips press soft to each one in turn, the way nobody has ever bothered. The body sighs out a content breath under each kiss as if it has been waiting decades for the gesture.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Every story you would not tell. Every one. I am keeping them all."</p> <</if>> <<if (_has("Pierced")) && _subs.includes("pierced")>> <p>You catch one of <<= _preName>>'s piercings between Roisin's teeth and tug, slow and easy. Metal warm from <<= _preName>>'s skin. The body shivers under the pull. You move on to the next one. Ear. Nipple if <<= _bSub>> went there. The little stud in the soft below <<= _preName>>'s navel. You leave each one with a wet kiss that pearls bright on the metal.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"All this jewellery and nobody home to enjoy how it is being used. Lucky for you, I am."</p> <</if>> <<if (_has("Freckled")) && _subs.includes("freckle")>> <p>Roisin's mouth maps the constellation across <<= _preName>>'s shoulders, the bridge of <<= _preName>>'s nose, the little spray <<= _bSub>> always forgot was on <<= _preName>>'s collarbone. Each freckle gets a soft press of lip. The body underneath you holds breath like it knows it is being counted.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Two hundred and forty something. I lost count. Worth losing count over."</p> <</if>> <<if _subs.includes("thighs")>> <p>Roisin's mouth goes lower. The crease at the top of <<= _preName>>'s thigh. The soft inside. The plush of <<= _preName>>'s ass under your gloved hand. You suck slow marks into the inside of both old thighs where only <<= _bSub>> will find them tomorrow. You bite once, soft, into the soft of <<= _preName>>'s ass and the body underneath you gives a sleepy little gasp.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Pretty hidden things. I want every one of these on me on me on me."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("face")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💋 Kiss every inch of her face</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["face"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("throat")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🩸 Suck a mark into her throat</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["throat"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("chest")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💗 Suck and bite <<= _preName>>'s chest</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["chest"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if (_has("Tattooed")) && !_subs.includes("tattoo")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🖋️ Tongue every old tattoo</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["tattoo"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if (_has("Scarred")) && !_subs.includes("scar")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🩹 Kiss every old scar tender</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["scar"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if (_has("Pierced")) && !_subs.includes("pierced")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🔗 Tug <<= _preName>>'s piercings gentle with your teeth</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["pierced"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if (_has("Freckled")) && !_subs.includes("freckle")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✨ Kiss every freckle one by one</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["freckle"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("thighs")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🍑 Worship <<= _preName>>'s thighs and ass</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["thighs"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "mark">> <<set _subs = $breakInSubActs || []>> <p>You stand back and look at <<= _preName>>'s body laid out across the sheet. Stripped. Used. Open. Roisin's hand drops between her own thighs and works herself slow at the edge of the bed, watching.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Going to leave a souvenir. You will not remember. The body will. The body always does."</p> <<if _subs.includes("stroke")>> <p>You straddle <<= _preName>>'s thigh and grind Roisin's slick along it. Slow heavy drags. Her tape wrap rises and falls. You watch <<= _preName>>'s slack face the whole time, chin tilted, smirk pulling. The pleasure builds slow and oceanic.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Look at me. Look at what you missed."</p> <</if>> <<if _subs.includes("chest_finish")>> <p>You climb up at the last second and tip yourself over <<= _preName>>'s breasts. Roisin's slick floods down across <<= _preName>>'s chest in a slow rope, pooling in the dip between <<= _preName>>'s breasts and sliding down <<= _preName>>'s sides. You drag two gloved fingers through it lazy, smearing it across <<= _preName>>'s skin.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Worn. Branded. Laundry tomorrow."</p> <</if>> <<if _subs.includes("face_finish")>> <p>You shuffle up and tip yourself over <<= _preName>>'s slack face. Roisin's slick paints across <<= _preName>>'s cheek and <<= _preName>>'s open mouth, dripping down <<= _preName>>'s jaw. You brush two gloved fingers through the mess on <<= _preName>>'s chin and slide them between <<= _preName>>'s slack lips, pressing the taste of you onto <<= _preName>>'s tongue.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Now you have me on your tongue too. Wonder if you will dream the taste."</p> <</if>> <<if _subs.includes("belly_finish")>> <p>You push yourself over <<= _preName>>'s stomach. Roisin's slick spills across <<= _preName>>'s belly in a slow wet rope, pooling in the soft just under <<= _preName>>'s navel. You drag your gloved fingertip through it and write a single letter on <<= _preName>>'s skin in her own slick. R. The body underneath you sleeps through the signature.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Signed and dated. The body knows whose it was tonight."</p> <</if>> <<if (_hasPussy) && _subs.includes("pussy_finish")>> <p>You straddle low and grind Roisin's pussy directly down on <<= _preName>>'s folds, slick on slick, until your wave breaks across <<= _preName>>'s cunt in a slow soaking finish. The body underneath you twitches as the heat lands. Your slick mixes with hers in the soft pool that gathers between you.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Mine and yours. You are not getting that one out for a while."</p> <</if>> <<if (_hasCock) && _subs.includes("cock_finish")>> <p>You straddle <<= _preName>>'s hips and grind Roisin's pussy along the soft length of <<= _preName>>'s cock, slow drags, slick and warm. <<= _preName>>'s cock answers without permission, swelling under you against your folds. You ride that growing length until your wave breaks, slick flooding across <<= _preName>>'s shaft and pooling at the base.</p> <p>You drag two gloved fingers through the mess and paint a slow shine up <<= _preName>>'s cock from base to tip, finishing with a wet kiss to the head.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"That is mine on you now. Pretty as a glaze."</p> <</if>> <<if !_subs.includes("finish")>> <div style="background: #2a1a3e; padding: 14px; border-radius: 8px; border: 1px solid #6e4ea8; margin: 14px 0;"> <p style="color: #c9a9ff; margin: 0 0 8px 0; font-weight: bold;">What next?</p> <<if !_subs.includes("stroke")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>👋 Get yourself off slow on <<= _preName>>'s thigh</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["stroke"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("chest_finish")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💦 Come on <<= _preName>>'s chest</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["chest_finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("face_finish")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💋 Come on <<= _preName>>'s face</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["face_finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if !_subs.includes("belly_finish")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌅 Come on <<= _preName>>'s belly</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["belly_finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if (_hasPussy) && !_subs.includes("pussy_finish")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌹 Come right on <<= _preName>>'s cunt</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["pussy_finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> <<if (_hasCock) && !_subs.includes("cock_finish")>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 8px 14px; border-radius: 6px; margin: 4px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🍆 Glaze <<= _preName>>'s cock</div>">> <<set $breakInSubActs = ($breakInSubActs || []).concat(["cock_finish"])>> <<goto "RoisinUnconsciousBodyScene">> <</link>> <</if>> </div> <</if>> <<elseif $breakInCurrentAct === "tf">> <<if _tfKey === "succubus">> <p>You lean down and seal Roisin's mouth over <<= _preName>>'s slack one. Not a kiss. The shape of one. You pull, the way the body taught you to pull, and a thin ribbon of warm bright something rises up out of <<= _preName>>'s chest and into yours.</p> <p>It is not soul. The artifact would not let you take soul. It is the loose fizzing surface energy the body gives off without missing it. Roisin's chest fills with it. <<= _preName>>'s chest relaxes deeper. The body sleeps better for the offering.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. There. I needed that. You did not."</p> <<elseif _tfKey === "witch">> <p>You lay Roisin's gloved palm over <<= _preName>>'s sternum and let the violet sigils that live in <<= _preName>>'s skin answer your touch. They bloom slow under her skin like ink in water, lighting old patterns. The witch in the bones recognizes you even with the soul gone.</p> <p>You trace one sigil along <<= _preName>>'s collarbone. The line warms under Roisin's fingertip. <<= _preName>>'s body sighs out the exact soft sound the witch makes during a casting.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Good girl. You have not forgotten anything."</p> <<elseif _tfKey === "bimbo">> <p>You drop down onto <<= _preName>>'s face like a queen settling. Roisin's gloved hands cup <<= _preName>>'s jaw and you press your tape-wrapped chest against her plump puffed mouth and you grind sloppy and slow against the kiss <<= _bObj>> body cannot help giving back.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Christ, you. Some woman built you for exactly this. Possibly her."</p> <<elseif _tfKey === "cheshire">> <p>You phase Roisin's tongue into <<= _preName>>'s skin where <<= _preName>>'s neck meets <<= _preName>>'s shoulder. The Cheshire body lets it. There is no wound. There is the strangest soft pressure of being inside her own skin from your tongue. <<= _bSubCap>> sleeps through it with a small dreaming smile.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. That is unfair. That is good."</p> <<elseif _tfKey === "siren">> <p>You lean down and put Roisin's mouth at <<= _preName>>'s ear. You sing. Not loud. A low note, the one the siren keeps under her tongue. <<= _preName>>'s body answers as if it has been waiting for the call.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Oh. There <<= _bSub>> is. The pretty thing under the pretty thing."</p> <<elseif _tfKey === "naiad">> <p>You bless her with a slow touch from <<= _preName>>'s crown to <<= _preName>>'s foot. The Naiad grace in the body answers Roisin's gloved fingertips in a long unfolding line.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. Even sleeping you are a hymn."</p> <<elseif _tfKey === "darkangel" || _tfKey === "angel">> <p>You spread the ghost of <<= _preName>>'s wings out across the bed. They are not really there. The body remembers the shape so hard the sheet dips where they settle. You lay Roisin's body down between them and <<= _preName>>'s wing memory shrouds you both.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Right. Now we are properly improper."</p> <<elseif _tfKey === "cerberus">> <p>You set Roisin's teeth at <<= _preName>>'s shoulder and breathe hot. The cerberus heat in the body answers up through your bite, real and alarming, and a faint pink mark blooms wide under your mouth in seconds.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. There you are. I have been wanting to bite you since I met you."</p> <<elseif _tfKey === "anubis">> <p>You retrieve the small bottle of oil the body keeps for its rites. You anoint <<= _preName>>'s forehead. <<= _preName>>'s chest. <<= _preName>>'s palms. The Anubis hieroglyphs wake slow and dark under each pressure of your gloved thumb.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Tonight <<= _bSub>> gets to be the saint."</p> <<elseif _tfKey === "banshee">> <p>You bring Roisin's mouth to <<= _preName>>'s ear and whisper the word the banshee remembers. Just the one. <<= _preName>>'s hair lifts soft off the pillow. The room goes very still.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye. I know. Sleep."</p> <<elseif _tfKey === "cupid">> <p>You kiss <<= _preName>>'s mouth so soft that the cupid kiss in <<= _preName>>'s skin lights up gentle pink under both of you.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Lucky you. Sweet dreams on the house."</p> <<elseif _tfKey === "domme">> <p>You straddle <<= _preName>>'s hips and pin <<= _preName>>'s wrists down with Roisin's gloved hands. The dominatrix in the body responds even under, a faint deep hum in the muscle, the body acknowledging that for one rare evening <<= _bSub>> is the one being held still.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"You needed this and you would never ask for it."</p> <<elseif _tfKey === "egirl">> <p>You set Roisin's gloved finger under <<= _preName>>'s chin and tilt <<= _bObj>> face the way a camera angle wants it. You pose <<= _preName>>'s body, slow, the way <<= _bSub>> poses for her own stream when <<= _bSub>> is trying to get a moment to land.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Stay there. Stay just there. I am keeping that one."</p> <<elseif _tfKey === "gyaru">> <p>You kiss <<= _preName>>'s gloss off slow. Roisin's mouth working <<= _preName>>'s mouth open just enough, taking the shimmer with you. The gyaru body keeps gloss on through anything and the lipstick stains Roisin's lips a faint sticky pink.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"You wear too much of this stuff. Tonight I take some."</p> <<elseif _tfKey === "gymbunny">> <p>You climb up and pin <<= _preName>>'s hips down properly with Roisin's full athletic weight. The gym bunny body in <<= _preName>>'s frame answers in a satisfied way only a body that knows how to be pinned does.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"You and me both like this. You just are not awake to admit it."</p> <<elseif _tfKey === "himbo">> <p>You wrap Roisin's whole body around <<= _preName>>'s big body in the messiest sweetest tangle of arms and legs.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"You are huge and lovely and I am going to keep this one for a while."</p> <<elseif _tfKey === "automaton">> <p>You find the soft seam at the inside of <<= _preName>>'s wrist where <<= _preName>>'s clockwork pulse runs. You wind it just the smallest fraction with Roisin's gloved fingertip.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"There. Topped you up. Sleep tight, you strange beautiful machine."</p> <</if>> <</if>> </div> <div style="text-align: center; margin: 18px 0;"> <<link "<div style='display: inline-block; background: #2a1a3e; color: #c9a9ff; padding: 10px 22px; border-radius: 8px; cursor: pointer; border: 1px solid #6e4ea8;'>Back to choices</div>">> <<set $breakInActs = ($breakInActs || []).concat([$breakInCurrentAct])>> <<set $breakInCurrentAct = null>> <<set $breakInSubActs = []>> <<goto "RoisinUnconsciousBodyScene">> <</link>> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <div style="background: radial-gradient(ellipse at center, #1a0a28 0%, #000 75%); min-height: 100vh; padding: 30px 20px;"> <div style="max-width: 720px; margin: 0 auto; color: #ddd; line-height: 1.7;"> <h1 style="color: #c9a9ff; text-align: center;">A Closer Look Tomorrow</h1> <p>Halfway through the lock the deadbolt seizes on you. Somewhere across the way a window slides open and a porch light blinks on. Roisin's instincts pull you off the steps and back into the dark before any face appears at the glass. The job will keep.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"Aye, alright. Tomorrow. I will bring better tools."</p> <div style="text-align: center; margin: 24px 0;"> <<set _spot = setup.sunfishCuff && setup.sunfishCuff.getRoisinCurrentLocation ? setup.sunfishCuff.getRoisinCurrentLocation() : "Plaza">> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #c9a9ff 0%, #6e4ea8 100%); color: white; padding: 12px 28px; border-radius: 8px; cursor: pointer; font-weight: bold;'>Slip away</div>">> <<goto _spot>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoisinBeachHouse">> <div style="background: linear-gradient(180deg, #2a1a3e 0%, #1a0a28 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a9ff; text-align: center;">🏝️ Roisin's Beach House</h1> <div style="padding: 20px; background: linear-gradient(135deg, #6e4ea8 0%, #c9a9ff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #c9a9ff;"> <<if !setup.oni.isPlayerInOwnBody()>> <p style="color: white; font-size: 17px; margin: 0; line-height: 1.6;"> A small white-washed bungalow tucked behind the dunes a mile up from the city. Salt-bleached cedar shingles. A wide porch facing the ocean. Wind chimes you made yourself from drift glass and copper wire. The kind of place you do not have to lock unless you really mean it. Your boards lean against the porch railing. Inside smells of salt, coffee, and a hint of orange peel. </p> <<else>> <p style="color: white; font-size: 17px; margin: 0; line-height: 1.6;"> A small pale bungalow tucked behind the dunes a mile up from the city. Weathered cedar shingles. A wide porch facing the ocean. Wind chimes Roisin made herself from drift glass and copper wire. The kind of place she does not bother locking unless she really means it. Her boards lean against the porch railing. Inside smells of salt, coffee, and a hint of orange peel. </p> <</if>> </div> <<set _npcsHere = setup.getNPCsAtLocation("RoisinBeachHouse")>> <<if _npcsHere && _npcsHere.length > 0>> <div style="background: #1a1a1a; padding: 15px; border-radius: 10px; margin-bottom: 20px; border: 3px solid #c9a9ff;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">Visitors</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 12px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 2px solid #6e4ea8; border-radius: 8px; padding: 12px; background: #2a1a3e;"> <h4 style="color: #c9a9ff; margin: 0 0 6px 0;">_npc.name</h4> <<link "<div style='background: #6e4ea8; color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer;'>Talk to _npc.name</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> <</capture>> <</for>> </div> </div> <</if>> <!-- Oni Riddle Tablet (three display states based on body + Foreign Language skill) --> <div style="border: 3px solid #b89c5c; border-radius: 10px; padding: 15px; background: #2a2418; box-shadow: 0 0 14px rgba(184,156,92,0.2); margin-bottom: 20px;"> <<if !setup.oni.isPlayerInOwnBody()>> /* State A: not own body */ <h3 style="color: #b89c5c; margin: 0 0 10px 0;">📜 Decorative Tablet</h3> <p style="font-size: 14px; color: #ddc4a0; margin: 0; line-height: 1.5; font-style: italic;">A pretty framed plaque hanging just inside the door. Foreign script in tea stained ink. The body you wear does not recognise it. To this body, it has always just looked nice.</p> <<elseif !($skills && ($skills.includes("Foreign Language") || $skills.includes("Languages")))>> /* State B: own body, no language skill */ <h3 style="color: #b89c5c; margin: 0 0 10px 0;">📜 Strange Foreign Tablet</h3> <p style="font-size: 14px; color: #ddc4a0; margin: 0; line-height: 1.5; font-style: italic;">A small framed parchment in tea stained ink hanging just inside the door. The script curls in a way you can't read. Roisin says her grandmother brought it from Sakaide. No one she ever met could read it either.</p> <<else>> /* State C: own body, has language skill */ <h3 style="color: #b89c5c; margin: 0 0 10px 0;">📜 The Verse of Three Cups</h3> <p style="font-size: 14px; color: #ddc4a0; margin: 0 0 10px 0; line-height: 1.5; font-style: italic;">A small framed parchment in tea stained ink. Your knowledge of foreign languages lets you read it.</p> <<link "<div style='background: #b89c5c; color: #1a1308; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Read the verse</div>">> <<goto "OniRiddleRead">> <</link>> <</if>> </div> <<if setup.oni && setup.oni.isPlayerInOwnBody()>> <div style="display: grid; grid-template-columns: 1fr; gap: 15px; margin-bottom: 20px;"> <div style="border: 3px solid #88c87c; border-radius: 10px; padding: 15px; background: #1a2418; box-shadow: 0 0 14px rgba(136,200,124,0.15);"> <h3 style="color: #88c87c; margin: 0 0 10px 0;">🌿 Walk past the bungalow into the dunes</h3> <p style="font-size: 14px; color: #c4ddb8; margin: 0 0 12px 0; line-height: 1.4;">A narrow path you have never quite noticed before now winds back through the salt grass.</p> <<link "<div style='background: linear-gradient(135deg, #88c87c 0%, #4d8a45 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Follow the path (10 min)</div>">> <<run advanceTime(10)>> <<goto "HiddenGrove">> <</link>> </div> </div> <</if>> <<if !setup.oni.isPlayerInOwnBody()>> <h2 style="color: #c9a9ff;">Rooms</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #ff8fc8; border-radius: 10px; padding: 15px; background: #2a1a3e; box-shadow: 0 0 14px rgba(255,143,200,0.18); display: flex; flex-direction: column;"> <h3 style="color: #ff8fc8; margin: 0 0 10px 0;">🛏️ Bedroom</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A messy unmade bed, a corkboard pinned with photos, a locked nightstand drawer.</p> <<link "<div style='background: #ff8fc8; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bedroom</div>">> <<goto "RoisinBedroom">> <</link>> </div> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #2a1a3e; box-shadow: 0 0 14px rgba(244,164,96,0.18); display: flex; flex-direction: column;"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">🍳 Kitchen</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Rustic, lived-in. A kettle on the hob, fish in the fridge, a row of spices.</p> <<link "<div style='background: #f4a460; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Kitchen</div>">> <<goto "RoisinKitchen">> <</link>> </div> <div style="border: 3px solid #4fc3f7; border-radius: 10px; padding: 15px; background: #2a1a3e; box-shadow: 0 0 14px rgba(79,195,247,0.18); display: flex; flex-direction: column;"> <h3 style="color: #4fc3f7; margin: 0 0 10px 0;">🚿 Bathroom</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Salt-bleached tiles, a rain-shower, a single mirror over the basin.</p> <<link "<div style='background: #4fc3f7; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Enter Bathroom</div>">> <<goto "RoisinBathroom">> <</link>> </div> </div> <<else>> <div style="border: 2px dashed #6e4ea8; border-radius: 10px; padding: 18px; background: #1a0a28; margin-bottom: 25px;"> <p style="color: #c9a9ff; font-size: 15px; line-height: 1.6; margin: 0; font-style: italic;">It would feel wrong to wander deeper into her home without her invitation. You stay in the entryway.</p> </div> <</if>> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #f4a460 0%, #87ceeb 100%); color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>🌿 Walk back down the path to the beach</div>">> <<run advanceTime(15)>> <<goto "Beach">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoisinBedroom">> <div style="background: linear-gradient(180deg, #2a1a3e 0%, #1a0a28 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #ff8fc8; text-align: center;">🛏️ Roisin's Bedroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ff8fc8;"> <p style="color: #1a0a28; font-size: 16px; margin: 0; line-height: 1.6;"> The bedroom is small and warm and entirely yours. A queen bed pushed under the window so you can watch the ocean change colour. Sheets shoved aside the way you left them. A corkboard above the headboard pinned with photos: Revna laughing, the docks at sunset, a polaroid of you in your tape wrap mid-lift, faces from the gym you have nicknames for. The locked nightstand drawer you never open and never throw out. Wind through the window from the porch, smelling of salt. </p> </div> <h2 style="color: #ff8fc8;">Things to do</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #ff8fc8; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #ff8fc8; margin: 0 0 10px 0;">😴 Sleep in her bed</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Curl up under her sheets. Advance to morning.</p> <<link "<div style='background: #ff8fc8; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Sleep until morning</div>">> <<run setup.advanceToMorning ? setup.advanceToMorning() : advanceTime(8 * 60)>> <<set $stats.energy = 100>> <<goto "RoisinBedroom">> <</link>> </div> <div style="border: 3px solid #c9a9ff; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #c9a9ff; margin: 0 0 10px 0;">🔒 Open the locked drawer</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">She has the key in her body's memory.</p> <<link "<div style='background: #c9a9ff; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Open the drawer</div>">> <<set $roisinDrawerOpened = true>> <<goto "RoisinBedroomDrawer">> <</link>> </div> <div style="border: 3px solid #ff8fc8; border-radius: 10px; padding: 15px; background: #1a0a28; box-shadow: 0 0 14px rgba(255,143,200,0.18); display: flex; flex-direction: column;"> <h3 style="color: #ff8fc8; margin: 0 0 10px 0;">💦 Touch yourself in her bed</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">The sheets she left rumpled. Her hands. Her bed.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Get yourself off (45 min)</div>">> <<goto "RoisinBedMasturbate">> <</link>> </div> </div> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: #6e4ea8; color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Back to the living room</div>">> <<goto "RoisinBeachHouse">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoisinKitchen">> <div style="background: linear-gradient(180deg, #2a1a3e 0%, #1a0a28 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #f4a460; text-align: center;">🍳 Roisin's Kitchen</h1> <div style="padding: 20px; background: linear-gradient(135deg, #f4a460 0%, #c9a9ff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #f4a460;"> <p style="color: #1a0a28; font-size: 16px; margin: 0; line-height: 1.6;"> Tile floor, an open shelf with a row of spices in jars labelled in your handwriting. A kettle on the hob, ready for the day. The fridge is a small thing under the counter, packed with caught fish, eggs, half a lemon, a wedge of cheese. A bottle of decent Irish whiskey in the cupboard above. Salt air comes in through the open kitchen window. The sink overlooks the dunes. </p> </div> <h2 style="color: #f4a460;">Things to do</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #f4a460; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #f4a460; margin: 0 0 10px 0;">☕ Brew her coffee</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">A little dark, a lot strong. Energy bump.</p> <<link "<div style='background: #f4a460; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Brew & drink (15 min)</div>">> <<run advanceTime(15)>> <<set $stats.energy = Math.min(100, ($stats.energy || 0) + 25)>> <<goto "RoisinKitchen">> <</link>> </div> <div style="border: 3px solid #4fc3f7; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #4fc3f7; margin: 0 0 10px 0;">🐟 Eat from the fridge</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Cold-smoked fish, a wedge of cheese, half a lemon. Quick meal.</p> <<link "<div style='background: #4fc3f7; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Eat (20 min)</div>">> <<run advanceTime(20)>> <<set $stats.energy = Math.min(100, ($stats.energy || 0) + 15)>> <<set $stats.hunger = Math.max(0, ($stats.hunger || 50) - 30)>> <<goto "RoisinKitchen">> <</link>> </div> <div style="border: 3px solid #b8860b; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #d4af37; margin: 0 0 10px 0;">🥃 Pour a whiskey</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Two fingers of the good stuff, neat.</p> <<link "<div style='background: #d4af37; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Pour & sip (15 min)</div>">> <<run advanceTime(15)>> <<set $stats.energy = Math.max(0, ($stats.energy || 0) - 5)>> <<set $stats.mood = Math.min(100, ($stats.mood || 50) + 10)>> <<goto "RoisinKitchen">> <</link>> </div> </div> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: #6e4ea8; color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Back to the living room</div>">> <<goto "RoisinBeachHouse">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RoisinBathroom">> <<set $mirrorReturnLocation = "RoisinBathroom">> <div style="background: linear-gradient(180deg, #2a1a3e 0%, #1a0a28 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #4fc3f7; text-align: center;">🚿 Roisin's Bathroom</h1> <div style="padding: 20px; background: linear-gradient(135deg, #4fc3f7 0%, #c9a9ff 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #4fc3f7;"> <p style="color: #1a0a28; font-size: 16px; margin: 0; line-height: 1.6;"> Small. Practical. Salt-bleached white tile. A round mirror over a chipped basin. A rain-shower stall behind a half-frosted glass door. Towels she clearly steals from the gym, embroidered with someone else's initials. A jar of sea salt scrub on the shelf. The window above the toilet looks out at scrub grass and dunes. </p> </div> <h2 style="color: #4fc3f7;">Things to do</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #4fc3f7; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #4fc3f7; margin: 0 0 10px 0;">🚿 Take a shower</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Rinse off the salt and the morning. Cleans appearance.</p> <<link "<div style='background: #4fc3f7; color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Shower (20 min)</div>">> <<run advanceTime(20)>> <<if setup.applyBuff>><<run setup.applyBuff("shower_fresh", 240)>><</if>> <<set $appearance.hairStyle = "clean">> <<goto "RoisinBathroom">> <</link>> </div> <div style="border: 3px solid #f39c12; border-radius: 10px; padding: 15px; background: #1a0a28; display: flex; flex-direction: column;"> <h3 style="color: #f39c12; margin: 0 0 10px 0;">🪞 Look in the mirror</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Take a proper look at yourself in her glass.</p> <<link "<div style='background: #f39c12; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Look in the mirror</div>">> <<set $mirrorReturnLocation = "RoisinBathroom">> <<goto "MirrorView">> <</link>> </div> <div style="border: 3px solid #ff8fc8; border-radius: 10px; padding: 15px; background: #1a0a28; box-shadow: 0 0 14px rgba(255,143,200,0.18); display: flex; flex-direction: column;"> <h3 style="color: #ff8fc8; margin: 0 0 10px 0;">💦 Touch yourself in the shower</h3> <p style="font-size: 14px; color: #ddc4ff; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Hot water, soap, her hands. Take your time.</p> <<link "<div style='background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Get yourself off (40 min)</div>">> <<goto "RoisinShowerMasturbate">> <</link>> </div> </div> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: #6e4ea8; color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Back to the living room</div>">> <<goto "RoisinBeachHouse">> <</link>> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #2a1a3e 0%, #1a0a28 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 720px; margin: 0 auto; color: #ddd; line-height: 1.7;"> <h1 style="color: #c9a9ff; text-align: center;">🔒 Inside the Locked Drawer</h1> <p>The drawer slides open under your gloved hand without protest. The little brass key was always inside her body's muscle memory. You did not have to find it. Roisin did.</p> <p>Inside: a stack of polaroids face down, a folded letter Revna wrote her years ago, a single small wooden box, a worn paperback with too many dog-ears, two bullets she would not say where she got, and a photograph of a woman who is not Revna and is not anyone you have seen in Sunfish City.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center;">"So that is who you keep in there. Hello, mystery woman."</p> <p>You close the drawer. You leave everything where she left it. The body settles a little, like it appreciates someone honoring the secret without taking it.</p> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: #6e4ea8; color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Close the drawer</div>">> <<goto "RoisinBedroom">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<if typeof $rsmPleasure !== 'number'>><<set $rsmPleasure = 0>><</if>> <<if typeof $rsmEdges !== 'number'>><<set $rsmEdges = 0>><</if>> <<if !$rsmLog>><<set $rsmLog = []>><</if>> <<set _p = $rsmPleasure>> <<set _e = $rsmEdges>> <<set _log = $rsmLog>> <div style="background: linear-gradient(180deg, #1a0a28 0%, #2a1a3e 50%, #1a0a28 100%); min-height: 100vh; padding: 30px 20px;"> <div style="max-width: 760px; margin: 0 auto; color: #ddd; line-height: 1.85;"> <h1 style="color: #ff8fc8; text-align: center;">💦 Steam and Salt</h1> <!-- ROISIN_SHOWER_IMAGES_START --> <<if $imageSettings && $imageSettings.imagesEnabled>> <<set _rsmLast = _log[_log.length - 1]>> <<set _rsmImg = null>> <<if _rsmLast === "climax">> <<set _rsmImg = "Images/Scenes/Roisin_Shower_2.webp">> <<elseif _log.length >= 1>> <<set _rsmImg = "Images/Scenes/Roisin_Shower_1.webp">> <</if>> <<if _rsmImg>> <div style="text-align: center; margin: 14px 0 18px 0;"> <img @src="_rsmImg" style="display: block; margin: 0 auto; max-width: min(100%, 720px); max-height: 640px; width: auto; height: auto; border-radius: 12px; border: 4px solid #ff8fc8; box-shadow: 0 0 36px rgba(255, 143, 200, 0.55), 0 6px 20px rgba(0, 0, 0, 0.55);" onerror="this.style.display='none';"> </div> <</if>> <</if>> <!-- ROISIN_SHOWER_IMAGES_END --> <<if _log.length === 0>> <p>You crank the hot tap and the shower opens up. Steam rises fast off the tile. The salt of her morning run washes off your shoulders in slow rivulets that pink under the lamp light. You step into the rain spray. The whole house knows it is alone. So do you.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Right so, Sullivan. Let's see what ye sound like when no one's listenin'."</p> <</if>> <div style="background: #1a0a28; border: 2px solid #ff8fc8; border-radius: 10px; padding: 14px; margin: 16px 0;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px;"> <span style="color: #ff8fc8; font-weight: bold; font-size: 14px;">💗 Pleasure</span> <span style="color: #ddc4ff; font-size: 13px;"><<= _p>>/100 · Edges: <<= _e>></span> </div> <div style="background: #2a1a3e; height: 18px; border-radius: 9px; overflow: hidden; border: 1px solid #ff8fc8;"> <div @style="'background: linear-gradient(90deg, #ff8fc8, #c9a9ff); height: 100%; width: ' + _p + '%; transition: width .3s;'"></div> </div> </div> <<for _i = 0; _i < _log.length; _i++>> <<set _ak = _log[_i]>> <<if _ak === "tape_off">> <p>Your bare fingers shake out the tape wrap around your chest. The whole heavy weight drops free into the steam, nipples standing up at the air, the wrap landing wet on the tile with a slap. You take a long look down at the body you're driving and your breath catches.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Right so. Hello, gorgeous. Tis a feckin' shame ye keep these strapped down all day."</p> <</if>> <<if _ak === "soap_tits">> <p>You lather slow. The suds slide down across the curve of each breast, between them, into the soft underneath where the tape leaves a faint pink line. You palm both at once and lift, just to feel the weight in your hands the way she likes.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Christ above. Ye are heavy, mo grá. Heavy and lovely and mine for the hour."</p> <</if>> <<if _ak === "nipple">> <p>You take one nipple between your thumb and forefinger and you roll. Soft at first. Then sharp. Soft again. The body answers. A little gasp under the spray. Heat creeping down inside your belly.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Aye, there ye are. Wisha, yer a sensitive one when no one's lookin'."</p> <</if>> <<if _ak === "wall">> <p>You brace one of your bare palms against the steamed shower wall and press your chest flat against the glass. Your chest squishes wide, nipples dragging across the cold pane, the temperature shock making you hiss. Your ass pushes back against nothing in particular and the body keeps offering it anyway.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Feckin' hell. Cold glass on hot skin. Tis a religious experience."</p> <</if>> <<if _ak === "thigh_hand">> <p>Your fingers drag down over the carved plates of your stomach and lower, until they brush the bare folds of your cunt. You're already so wet the hot water cannot rinse it off. You drag one finger up the seam and the body lets out a small sound that bounces off the tile.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Jaysus, cailín. Ye've been ready for hours. Ye filthy, gorgeous thing."</p> <</if>> <<if _ak === "two_fingers">> <p>You push two of your fingers up inside your cunt to the second knuckle and curl. The body folds forward against the steamed glass and a long broken vowel comes out of your mouth that you didn't mean to make. You curl them again. Slow. Mean. Deliberate.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Aye. Aye, mo croí. There. Feckin' there."</p> <</if>> <<if _ak === "rain_head">> <p>The detachable rain head clicks off the wall in your hand. You drag the hot pulse of water in slow circles across your clit and your thighs slam together once around your own wrist. You push them open again. The spray hammers and your breath goes ragged.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Stop the lights. That is unfair. That is feckin' unfair."</p> <</if>> <<if _ak === "edge_pull">> <p>The body is climbing fast. You yank the rain head away. Your fingers slide out of your cunt slick and shaking. The body whines into the spray, hips pushing into nothing, every muscle locked at the edge with nowhere to go.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Not yet, ye greedy thing. Not yet so. We'll wait. We'll wait, and tis goin' to be worth it."</p> <</if>> <<if _ak === "bite_hand">> <p>You sink your teeth into the back of your own hand to keep the sound from leaving the bathroom. Your skin muffles half of it. The rest still climbs the wall and bounces back at you, hot and unmistakable.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Mind yerself, Sullivan. Or don't. Sure no one's about to hear ye anyway."</p> <</if>> <<if _ak === "fuck_palm">> <p>You plant your palm flat between your thighs and you fuck yourself down on your own hand against the tile, the heel grinding your clit, two fingers hooked and curling deep. The body's hips start a rhythm you didn't ask for and you let it carry you.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Christ on a feckin' bicycle. There ye are. There ye are, mo grá."</p> <</if>> <</for>> <<if _log[_log.length - 1] === "climax">> <<if _e >= 3>> <p>You let it loose at last. The body crashes through the climax like a wave breaking through tile. After three edges held tight, the dam breaks all the way through. Your cunt clenches and clenches around your own two fingers. The rain head pours hard against your clit. You come hard standing up, head tipped back into the spray, a long broken cry spilling out of your open mouth and down the drain. Your thighs shake. Your knees nearly fold. Aftershocks roll through you like surf, one after another, every one of the three you held back finally landing.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Bejaysus. Bejaysus. I'm goin' to die in this shower and that is grand."</p> <p>You stand under the hot water until the body remembers how to hold itself up. Your breath is wrecked. Your chest is pink and shining. Slick is still creeping down the inside of your thigh and the spray cannot keep up.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Sláinte to me. I owed her that one."</p> <</if>> <<if _e >= 1>> <p>You let it happen. You come hard standing up against the steamed glass, your cunt squeezing tight on your own fingers, the rain head pressing close on your clit. A long broken sound spills out of your mouth and down the drain along with everything else. The wave rolls slow. The body shudders three times and finally drops down off the edge.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Christ. There. Aye. Better for the holdin' off."</p> <p>You lean on the shower wall. Your thighs are tight. The water is starting to cool and you let it.</p> <</if>> <<if true>> <p>The body crests fast under the spray. You come with a sharp gasp into your own bare hand, your cunt clenching tight, hot water cascading over your chest. The wave is quick but solid. The body relaxes against the tile.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Aye. Aye, that'll do for now. Tis only one for the morning so."</p> <</if>> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 14px 32px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Step out of the shower</div>">> <<set $rsmPleasure = 0>> <<set $rsmEdges = 0>> <<set $rsmLog = []>> <<run advanceTime(15)>> <<if setup.applyBuff>><<run setup.applyBuff("shower_fresh", 240)>><</if>> <<set $appearance.hairStyle = "clean">> <<run State.variables.roisinShowerMasturbateCount = (State.variables.roisinShowerMasturbateCount || 0) + 1>> <<goto "RoisinBathroom">> <</link>> </div> <<else>> <div style="background: #2a1a3e; padding: 18px; border-radius: 10px; border: 1px solid #6e4ea8; margin: 18px 0;"> <p style="color: #ff8fc8; margin: 0 0 10px 0; font-weight: bold;">What do you do next?</p> <<if !_log.includes("tape_off") && _p >= 0>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🩷 Peel the tape wrap off <span style=\'color:#888; font-size:12px;\'>(+12)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["tape_off"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 12))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("soap_tits") && _p >= 5>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🫧 Soap up your chest slow <span style=\'color:#888; font-size:12px;\'>(+11)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["soap_tits"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 11))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("nipple") && _p >= 0>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🍒 Roll a nipple between your fingers <span style=\'color:#888; font-size:12px;\'>(+10)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["nipple"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 10))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("wall") && _p >= 15>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🧱 Press up against the steamed glass <span style=\'color:#888; font-size:12px;\'>(+13)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["wall"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 13))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("thigh_hand") && _p >= 20>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>💦 Slide a hand between your thighs <span style=\'color:#888; font-size:12px;\'>(+16)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["thigh_hand"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 16))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("two_fingers") && _p >= 35>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✌️ Push two fingers up inside her <span style=\'color:#888; font-size:12px;\'>(+19)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["two_fingers"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 19))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("rain_head") && _p >= 50>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🚿 Pull the rain head down on your clit <span style=\'color:#888; font-size:12px;\'>(+24)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["rain_head"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 24))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("edge_pull") && _p >= 60>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Pull off — hold yourself at the edge <span style=\'color:#888; font-size:12px;\'>(-22)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["edge_pull"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + -22))>> <<set $rsmEdges = ($rsmEdges || 0) + 1>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("bite_hand") && _p >= 25>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🤫 Bite the back of your hand to muffle a moan <span style=\'color:#888; font-size:12px;\'>(+9)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["bite_hand"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 9))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if !_log.includes("fuck_palm") && _p >= 65>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✊ Ride your own hand against the wall <span style=\'color:#888; font-size:12px;\'>(+22)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["fuck_palm"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 22))>> <<goto "RoisinShowerMasturbate">> <</link>> <</if>> <<if _p >= 90>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 11px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #c9a9ff; font-weight: bold; font-size: 15px;'>🌹 Let it break — finish for yourself</div>">> <<set $rsmLog = ($rsmLog || []).concat(["climax"])>> <<goto "RoisinShowerMasturbate">> <</link>> <<elseif _p >= 70>> <p style="color: #888; font-size: 13px; text-align: center; margin: 10px 0 0 0; font-style: italic;">Almost there. Push past 90 and you can let go.</p> <</if>> <div style="margin-top: 14px; text-align: center;"> <<link "<span style='color: #888; font-size: 13px; text-decoration: underline; cursor: pointer;'>Cool off and stop here</span>">> <<set $rsmPleasure = 0>> <<set $rsmEdges = 0>> <<set $rsmLog = []>> <<run advanceTime(10)>> <<goto "RoisinBathroom">> <</link>> </div> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<if typeof $rsmPleasure !== 'number'>><<set $rsmPleasure = 0>><</if>> <<if typeof $rsmEdges !== 'number'>><<set $rsmEdges = 0>><</if>> <<if !$rsmLog>><<set $rsmLog = []>><</if>> <<set _p = $rsmPleasure>> <<set _e = $rsmEdges>> <<set _log = $rsmLog>> <div style="background: linear-gradient(180deg, #1a0a28 0%, #2a1a3e 50%, #1a0a28 100%); min-height: 100vh; padding: 30px 20px;"> <div style="max-width: 760px; margin: 0 auto; color: #ddd; line-height: 1.85;"> <h1 style="color: #ff8fc8; text-align: center;">💦 In Her Own Bed</h1> <!-- ROISIN_BED_CLIMAX_IMAGE_START --> <<if $imageSettings && $imageSettings.imagesEnabled && _log[_log.length - 1] === "climax">> <div style="text-align: center; margin: 14px 0 18px 0;"> <img src="Images/Scenes/Roisin_Bed.webp" style="display: block; margin: 0 auto; max-width: min(100%, 720px); max-height: 640px; width: auto; height: auto; border-radius: 12px; border: 4px solid #ff8fc8; box-shadow: 0 0 36px rgba(255, 143, 200, 0.55), 0 6px 20px rgba(0, 0, 0, 0.55);" onerror="this.style.display='none';"> </div> <</if>> <!-- ROISIN_BED_CLIMAX_IMAGE_END --> <<if _log.length === 0>> <p>You shut the bedroom door, even though the house is empty. Old habit. The sheet she left rumpled gets thrown back. You sit on the edge of her bed and the springs creak your name. The salt breeze comes in across the dunes through her open window. The whole house is yours for the afternoon.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Right so. Hello, ye gorgeous thing. Let us spend an hour gettin' reacquainted."</p> <</if>> <div style="background: #1a0a28; border: 2px solid #ff8fc8; border-radius: 10px; padding: 14px; margin: 16px 0;"> <div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px;"> <span style="color: #ff8fc8; font-weight: bold; font-size: 14px;">💗 Pleasure</span> <span style="color: #ddc4ff; font-size: 13px;"><<= _p>>/100 · Edges: <<= _e>></span> </div> <div style="background: #2a1a3e; height: 18px; border-radius: 9px; overflow: hidden; border: 1px solid #ff8fc8;"> <div @style="'background: linear-gradient(90deg, #ff8fc8, #c9a9ff); height: 100%; width: ' + _p + '%; transition: width .3s;'"></div> </div> </div> <<for _i = 0; _i < _log.length; _i++>> <<set _ak = _log[_i]>> <<if _ak === "strip">> <p>You shut the bedroom door even though the house is empty. Old habit. The tape wrap comes off slow. Booty shorts and her thong with them. You lie back on her unmade bed, ginger ponytail spread across the pillow, the salt breeze coming in across the dunes through her window.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Right so. Bed in the middle of the day. Tis filthy of me. Sure, her schedule has it free."</p> <</if>> <<if _ak === "trail">> <p>Roisin's gloved fingertip drags slow down her throat, between her chest, across the carved plates of her abs, into the soft crease at the top of her thigh. Every inch of skin lights up under the leather. Her hips do that small unconscious roll the body does when she likes something.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Hello, ye gorgeous thing. We've not had a proper hello in ages."</p> <</if>> <<if _ak === "nipple_bed">> <p>You roll one of Roisin's nipples between her thumb and forefinger. The body lifts off the sheet. You roll the other one with her left hand. Both are heavy in her own palms and gorgeous and you take a long greedy minute on them.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Christ above. I could stay on yer chest for an hour and ye'd not complain."</p> <</if>> <<if _ak === "thigh_open">> <p>You let her thighs fall open across the sheet. The salt breeze comes in cool through the open window and licks across the bare wet of her cunt. The body tilts its hips up at nothing in particular, looking for friction, getting only air.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Aye. Look at the state of ye. Pure invitation, that is."</p> <</if>> <<if _ak === "circle_clit">> <p>Roisin's middle finger drags slow circles around her own clit, never quite landing on it. The body gets greedy fast. Her hips lift up to chase the contact and find the air. You laugh, low and pleased, and slow your pace on purpose.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Beg me, cailín. Sure ye're nearly beggin' already."</p> <</if>> <<if _ak === "two_in_bed">> <p>You push two of Roisin's fingers up inside her cunt to the second knuckle and curl them up against the front wall of her. The body bows up off the sheet. The pillow muffles half a moan. You curl them again. Slow. Steady. Mean.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"There. Right feckin' there. I knew ye had a spot like that, ye sly thing."</p> <</if>> <<if _ak === "pillow_ride">> <p>You drag her body's pillow down between her thighs and clamp her legs around it. Her hips start a slow grind, the cotton soaking up her slick fast, her clit dragging the seam on every roll. Roisin's gloved hands fist the sheets above her head.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Wisha. The state of us. The pillow is takin' the brunt of it, mo grá."</p> <</if>> <<if _ak === "thumb_clit">> <p>You add Roisin's thumb to the pressure on her clit while two fingers stay buried in her cunt. Slow tight circles. Her hips start a small unconscious rolling motion, riding her own hand while the body shakes through it.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Aye. Ridin' me own hand in me own bed. Pure decadence."</p> <</if>> <<if _ak === "edge_bed">> <p>You yank Roisin's hand out of her cunt right as the body starts climbing. The slick threads off her gloved fingers in long shining lines. The body twitches up looking for the friction that vanished. You smile up at her own ceiling and let the wave die down before you start over.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Not yet, ye greedy thing. We'll go again. Tis sweeter for the waitin'."</p> <</if>> <<if _ak === "roll_belly">> <p>You roll over onto her belly. The mattress takes her weight. Your gloved hand slides under her hips, two fingers buried, heel of her palm working her clit, and you start to fuck her own hand into the bed proper. The mattress springs creak. Her ginger ponytail sticks to her wet cheek.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Christ. The bed is takin' some abuse. Sorry, bed. Not really sorry."</p> <</if>> <</for>> <<if _log[_log.length - 1] === "climax">> <<if _e >= 3>> <p>You let it all the way loose. The wave crashes through her after three edges held back, every held-back climax landing at once. Roisin's cunt clenches tight on her own two fingers, her hips press down hard, a long broken cry spills muffled into the pillow. The body jerks and jerks. Slick floods over her gloved knuckles and into the sheet underneath you. Her thighs squeeze tight together and tremble through the whole long aftermath.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Feckin'. Hell. I am gonna haunt this bed."</p> <p>Aftershocks roll one after another. You stay sunk in her own cunt with two fingers buried until the very last little spasm, and then you ease them out wet and shining and lift them to her mouth and suck them clean.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Sláinte. Sláinte to all the holdin' off in the world. Worth every second."</p> <</if>> <<if _e >= 1>> <p>The wave breaks over both of you at once. Roisin comes hard into her own bed, her cunt clenching tight on her own fingers, her hips pressing down, a long broken sound spilling muffled into the pillow. The body jerks twice. Slick floods over her gloved knuckles and into the sheet.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Bejaysus. Better for the waitin'. Always better for the waitin'."</p> <p>You lie there a while after, the salt breeze cooling the wreckage of her wet thighs, every muscle in her body finally loose.</p> <</if>> <<if true>> <p>The body crests under her own hand. Roisin comes with a soft cry into her pillow, her cunt clenching tight, her hips pressing down once and going still. The wave is quick but real.</p> <p style="color: #ffd6ec; font-style: italic; text-align: center; margin: 8px 0;">"Aye. That'll do, mo grá. That'll do for an afternoon."</p> <</if>> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff8fc8 0%, #c9a9ff 100%); color: #1a0a28; padding: 14px 32px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Get up off the bed</div>">> <<set $rsmPleasure = 0>> <<set $rsmEdges = 0>> <<set $rsmLog = []>> <<run advanceTime(15)>> <<run State.variables.roisinBedMasturbateCount = (State.variables.roisinBedMasturbateCount || 0) + 1>> <<goto "RoisinBedroom">> <</link>> </div> <<else>> <div style="background: #2a1a3e; padding: 18px; border-radius: 10px; border: 1px solid #6e4ea8; margin: 18px 0;"> <p style="color: #ff8fc8; margin: 0 0 10px 0; font-weight: bold;">What do you do next?</p> <<if !_log.includes("strip") && _p >= 0>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🩷 Strip out of her gear onto the bed <span style=\'color:#888; font-size:12px;\'>(+11)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["strip"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 11))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("trail") && _p >= 5>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🪶 Drag a fingertip down her throat to her belly <span style=\'color:#888; font-size:12px;\'>(+9)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["trail"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 9))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("nipple_bed") && _p >= 0>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🍒 Roll a nipple slow <span style=\'color:#888; font-size:12px;\'>(+10)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["nipple_bed"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 10))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("thigh_open") && _p >= 10>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🦵 Let her thighs fall open <span style=\'color:#888; font-size:12px;\'>(+12)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["thigh_open"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 12))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("circle_clit") && _p >= 20>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌀 Circle her clit in slow lazy rolls <span style=\'color:#888; font-size:12px;\'>(+14)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["circle_clit"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 14))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("two_in_bed") && _p >= 30>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>✌️ Slide two fingers in deep, curl up <span style=\'color:#888; font-size:12px;\'>(+20)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["two_in_bed"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 20))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("pillow_ride") && _p >= 35>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛏️ Hump the pillow between her thighs <span style=\'color:#888; font-size:12px;\'>(+18)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["pillow_ride"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 18))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("thumb_clit") && _p >= 45>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>👍 Thumb circles on her clit while two fingers stay deep <span style=\'color:#888; font-size:12px;\'>(+22)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["thumb_clit"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 22))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("edge_bed") && _p >= 55>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🛑 Pull her hand back — edge yourself <span style=\'color:#888; font-size:12px;\'>(-20)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["edge_bed"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + -20))>> <<set $rsmEdges = ($rsmEdges || 0) + 1>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if !_log.includes("roll_belly") && _p >= 65>> <<link "<div style='display: block; background: #1a0a28; color: #ffd6ec; padding: 9px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #6e4ea8; font-size: 14px;'>🌊 Roll over and grind into her own gloved hand <span style=\'color:#888; font-size:12px;\'>(+23)</span></div>">> <<set $rsmLog = ($rsmLog || []).concat(["roll_belly"])>> <<set $rsmPleasure = Math.max(0, Math.min(100, $rsmPleasure + 23))>> <<goto "RoisinBedMasturbate">> <</link>> <</if>> <<if _p >= 90>> <<link "<div style='display: block; background: linear-gradient(135deg, #ff8fc8 0%, #6e4ea8 100%); color: #1a0a28; padding: 11px 14px; border-radius: 6px; margin: 5px 0; cursor: pointer; border: 1px solid #c9a9ff; font-weight: bold; font-size: 15px;'>🌹 Let it break — finish for yourself</div>">> <<set $rsmLog = ($rsmLog || []).concat(["climax"])>> <<goto "RoisinBedMasturbate">> <</link>> <<elseif _p >= 70>> <p style="color: #888; font-size: 13px; text-align: center; margin: 10px 0 0 0; font-style: italic;">Almost there. Push past 90 and you can let go.</p> <</if>> <div style="margin-top: 14px; text-align: center;"> <<link "<span style='color: #888; font-size: 13px; text-decoration: underline; cursor: pointer;'>Cool off and stop here</span>">> <<set $rsmPleasure = 0>> <<set $rsmEdges = 0>> <<set $rsmLog = []>> <<run advanceTime(10)>> <<goto "RoisinBedroom">> <</link>> </div> </div> <</if>> </div> </div> <</nobr>>
<<script>> /* ---------------------------------- */ /* OJOU TRAIT SYSTEM */ /* ---------------------------------- */ /* Tick the refinement counter when the player does an upscale activity. Hidden permanent stat. Once-per-day dedup per source. Grants a permanent Charisma point every third tick of lifetime refinement. No-op once the Ojou trait has been acquired. */ setup.tickOjouRefinement = function(source, amount) { var v = State.variables; /* No-op after Ojou: the path\u0027s purpose has been fulfilled. */ if (v.physicalTraits && v.physicalTraits.indexOf("Ojou") !== -1) return; /* Main-body only. Refinement is a poise-of-self thing; it does not transfer through a borrowed body or a swapped life. */ if (v.possessionActive === true) return; if (v.lifeSwapPortraitSource && v.lifeSwapPortraitSource !== "player") return; /* Hair must be styled to gain refinement. A heiress in the making does not pick up poise while her hair is a mess. */ if (v.appearance && v.appearance.hairStyle === "messy") return; if (typeof v.ojou_refinement !== "number") v.ojou_refinement = 0; if (typeof v.ojou_refinementLifetime !== "number") v.ojou_refinementLifetime = 0; if (!v.ojou_lastRefinementTick) v.ojou_lastRefinementTick = {}; var day = v.dayNumber || 0; if (v.ojou_lastRefinementTick[source] === day) return; v.ojou_lastRefinementTick[source] = day; v.ojou_refinement = Math.min(100, v.ojou_refinement + (amount || 5)); v.ojou_refinementLifetime += 1; /* Hidden permanent stat bonus: every third lifetime tick grants +1 Charisma. Writes to $stats.charisma (the canonical stat the rest of the game reads), respecting $statMaxCaps if present. */ if (v.ojou_refinementLifetime % 3 === 0) { if (!v.stats) v.stats = { charisma: 0, intelligence: 0, strength: 0, dexterity: 0 }; var cap = v.statMaxCaps && typeof v.statMaxCaps.charisma === "number" ? v.statMaxCaps.charisma : Infinity; v.stats.charisma = Math.max((v.stats.charisma || 0), Math.min(cap, (v.stats.charisma || 0) + 1)); } }; /* Reset the current refinement gate counter. Called from prostitution and theft hooks. Lifetime ticks and any Charisma already earned stay intact; only the gate value goes back to 0. No-op after Ojou. */ setup.resetOjouRefinement = function() { var v = State.variables; if (v.physicalTraits && v.physicalTraits.indexOf("Ojou") !== -1) return; v.ojou_refinement = 0; }; /* Hair messy override. Replaces direct $appearance.hairStyle = "messy" assignments. When Ojou is active, hair stays long blonde styled instead of going messy. */ setup.setHairMessy = function() { var v = State.variables; if (!v.appearance) v.appearance = {}; if (v.physicalTraits && v.physicalTraits.indexOf("Ojou") !== -1) { v.appearance.hairStyle = "long"; v.appearance.hairColor = "Blonde"; return; } v.appearance.hairStyle = "messy"; }; /* Apply the Ojou body transformation. Called once during the cutscene. - Gender to female if not already (syncs both \$gender and \$bodyParts.gender) - Chest to large if smaller (setsChestFloorOnly behavior, syncs \$bodyParts.chest too) - Hair color to Blonde (Title Case to match game convention), style/length to long - Skin tone to pale (syncs both \$appearance.skinTone and \$bodyParts.skinTone) - If body had a penis, replace it with a vagina */ setup.applyOjouTransformation = function() { var v = State.variables; /* Mutual exclusivity: an Ojou is an Ojou alone. Strip every other registered full transformation before applying ours. We delegate to setup.revertFullTransformation per trait so granted-trait tracking, Voluptuous Succubus body restore, etc. all run cleanly. */ if (setup.fullTransformations) { var ojouMutexNames = Object.keys(setup.fullTransformations).filter(function(n){ return n !== "Ojou"; }); for (var oi = 0; oi < ojouMutexNames.length; oi++) { var otherName = ojouMutexNames[oi]; var hadIt = (v.physicalTraits && v.physicalTraits.indexOf(otherName) !== -1) || (v.mentalTraits && v.mentalTraits.indexOf(otherName) !== -1); if (hadIt && typeof setup.revertFullTransformation === "function") { try { setup.revertFullTransformation(otherName); } catch (e) {} } } /* activeTransformation may have pointed at the prior form. */ if (v.activeTransformation && v.activeTransformation !== "Ojou") { v.activeTransformation = null; } } /* Stash the pre-transform body state so we can revert later if trait is stored */ if (!v.ojou_preBody) { v.ojou_preBody = { gender: v.gender, chest: v.appearance ? v.appearance.chestSize : null, hairColor: v.appearance ? v.appearance.hairColor : null, hairStyle: v.appearance ? v.appearance.hairStyle : null, hairLength: v.appearance ? v.appearance.hairLength : null, skinTone: v.appearance ? v.appearance.skinTone : null, bodyChest: v.bodyParts ? v.bodyParts.chest : null, bodyGender: v.bodyParts ? v.bodyParts.gender : null, bodyGenitals: v.bodyParts ? v.bodyParts.genitals : null, bodySkinTone: v.bodyParts ? v.bodyParts.skinTone : null }; } if (!v.appearance) v.appearance = {}; if (!v.bodyParts) v.bodyParts = {}; /* Gender lock */ v.gender = "female"; v.bodyParts.gender = "female"; /* If the body had a penis, replace with a vagina */ var oldGenitals = (v.bodyParts.genitals || "").toLowerCase(); if (oldGenitals.indexOf("penis") !== -1 || oldGenitals.indexOf("cock") !== -1) { v.bodyParts.genitals = "vagina"; } /* Chest floor at "large" */ var chestOrder = ["flat masculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]; var apparentChest = v.appearance.chestSize || "medium"; var partsChest = v.bodyParts.chest || apparentChest; var largeIdx = chestOrder.indexOf("large"); if (chestOrder.indexOf(apparentChest) < largeIdx) v.appearance.chestSize = "large"; if (chestOrder.indexOf(partsChest) < largeIdx) v.bodyParts.chest = "large"; /* Hair: long blonde styled */ v.appearance.hairColor = "Blonde"; v.appearance.hairStyle = "long"; v.appearance.hairLength = "long"; /* Skin: pale */ v.appearance.skinTone = "pale"; v.bodyParts.skinTone = "pale"; }; /* Revert body when the Ojou trait is stored away via Roisin storage. */ setup.revertOjouBody = function() { var v = State.variables; if (!v.ojou_preBody) return; var pre = v.ojou_preBody; if (pre.gender) v.gender = pre.gender; if (v.appearance) { if (pre.chest != null) v.appearance.chestSize = pre.chest; if (pre.hairColor != null) v.appearance.hairColor = pre.hairColor; if (pre.hairStyle != null) v.appearance.hairStyle = pre.hairStyle; if (pre.hairLength != null) v.appearance.hairLength = pre.hairLength; if (pre.skinTone != null) v.appearance.skinTone = pre.skinTone; } if (v.bodyParts) { if (pre.bodyChest != null) v.bodyParts.chest = pre.bodyChest; if (pre.bodyGender != null) v.bodyParts.gender = pre.bodyGender; if (pre.bodyGenitals != null) v.bodyParts.genitals = pre.bodyGenitals; if (pre.bodySkinTone != null) v.bodyParts.skinTone = pre.bodySkinTone; } }; /* Money buff multipliers. Consulted by earning systems via setup.ojouBuffs.payMultiplier(jobKey). */ setup.ojouBuffs = { hourlyJobMultipliers: { "Negotiator": 1.5, "Cocktail Waitress": 1.3, "Model": 1.4, "Secretary": 1.25, "Mayor": 1.2, "Construction": 0.75, "Mining": 0.75, "Docks": 0.75, "Janitor": 0.75 }, streamMultipliers: { "styling": 1.3, "music": 1.3, "asmr": 1.25, "cooking": 1.15 }, payMultiplier: function(jobKey) { var v = State.variables; if (!v.physicalTraits || v.physicalTraits.indexOf("Ojou") === -1) return 1.0; return this.hourlyJobMultipliers[jobKey] || 1.0; }, streamMultiplier: function(category) { var v = State.variables; if (!v.physicalTraits || v.physicalTraits.indexOf("Ojou") === -1) return 1.0; var key = (category || "").toLowerCase(); return this.streamMultipliers[key] || 1.0; } }; /* Renovate a buried mansion room. Deducts cost from player money, sets the corresponding restored flag, and returns true on success. Returns false if the player cannot afford it or already renovated. */ setup.renovateOjouRoom = function(roomKey, cost) { var v = State.variables; /* Reject unknown room keys so the helper cannot be tricked into deducting an arbitrary cost and setting a phantom flag. */ if (!setup.ojouRenovationCosts || !setup.ojouRenovationCosts.hasOwnProperty(roomKey)) return false; if ((v.money || 0) < cost) return false; var flagName = "ojou_" + roomKey + "Restored"; if (v[flagName]) return false; v.money -= cost; v[flagName] = true; return true; }; /* Per-room renovation costs. Keyed by the suffix used in the flag name. */ setup.ojouRenovationCosts = { wineVault: 400000, drawingRoom: 200000, library: 75000, teaRoom: 25000, bedchamber: 500000 }; /* Book catalog for the restored Library. */ setup.ojouBooks = { etiquette: { title: "Etiquette Manual", cost: 5000, desc: "Permanent +2 Charisma" }, poetry: { title: "Imported Poetry", cost: 5000, desc: "Permanent +2 Intelligence" }, investment: { title: "Treatises on Investment", cost: 10000, desc: "Permanent +10% to hourly job pay" }, wineGuide: { title: "Connoisseur\u0027s Guide to Wine", cost: 8000, desc: "Doubles Wine Vault aging speed" }, musicTheory: { title: "Music Theory", cost: 7000, desc: "Adds +50% to Drawing Room recital pay" } }; /* Buy and read a book from the restored Library in one step. */ setup.ojouBuyAndReadBook = function(bookKey) { var v = State.variables; var book = setup.ojouBooks[bookKey]; if (!book) return "not_a_book"; if (!v.ojou_libraryBooksRead) v.ojou_libraryBooksRead = []; if (v.ojou_libraryBooksRead.indexOf(bookKey) !== -1) return "already_read"; if ((v.money || 0) < book.cost) return "no_money"; v.money -= book.cost; v.ojou_libraryBooksRead.push(bookKey); /* Book stat bonuses write to $stats.* so they count toward checks, displays, and earnings, with $statMaxCaps respected. */ if (!v.stats) v.stats = { charisma: 0, intelligence: 0, strength: 0, dexterity: 0 }; var caps = v.statMaxCaps || {}; if (bookKey === "etiquette") { var capC = typeof caps.charisma === "number" ? caps.charisma : Infinity; v.stats.charisma = Math.max((v.stats.charisma || 0), Math.min(capC, (v.stats.charisma || 0) + 2)); } if (bookKey === "poetry") { var capI = typeof caps.intelligence === "number" ? caps.intelligence : Infinity; v.stats.intelligence = Math.max((v.stats.intelligence || 0), Math.min(capI, (v.stats.intelligence || 0) + 2)); } return "ok"; }; /* Is the player currently under the Heiress\u0027s Repose buff for this day? */ setup.ojouHasRepose = function() { var v = State.variables; return (v.ojou_teaActiveDay || 0) === (v.dayNumber || 0); }; /* Take Tea: once per day. Grants Repose for today. */ setup.ojouTakeTea = function() { var v = State.variables; var today = v.dayNumber || 0; if ((v.ojou_lastTeaDay || 0) === today) return false; v.ojou_lastTeaDay = today; v.ojou_teaActiveDay = today; /* Mirror the flag as a real buff so it shows in the active buffs UI and the cheat menu's buff list. Duration = exactly the minutes remaining until midnight, so the visible buff expires in sync with the underlying flag (ojou_teaActiveDay === dayNumber). */ if (typeof setup.addBuff === "function") { try { var minsLeft = Math.max(1, 1440 - (v.timeInMinutes || 0)); setup.addBuff("ojou_heiress_repose", minsLeft); } catch (e) {} } return true; }; /* Sleep in the buried Bedchamber. Advances to 6am the NEXT day, rolls a real full-night rest, and sets Repose for tomorrow. */ setup.ojouSleepBedchamber = function() { var v = State.variables; /* Target = 30:00 (i.e. 6am tomorrow) measured from today midnight, so the delta to advance is always (30*60) - currentMinutes. The advanceTime helper handles the midnight rollover and day++ for us. */ var current = v.timeInMinutes || 0; var minutesToAdvance = (30 * 60) - current; if (typeof window.advanceTime === "function") { window.advanceTime(minutesToAdvance); } else { v.timeInMinutes = (current + minutesToAdvance); while (v.timeInMinutes >= 1440) { v.timeInMinutes -= 1440; v.dayNumber = (v.dayNumber || 0) + 1; } } /* Full-night rest bookkeeping, matching the studio/home bed flow. */ if (typeof setup.getTotalGameMinutes === "function") { v.lastSleepTime = setup.getTotalGameMinutes(); } if (setup.removeDebuff) { try { setup.removeDebuff("exhaustion"); } catch (e) {} } if (setup.removeDebuff) { try { setup.removeDebuff("dive_injury"); } catch (e) {} } if (setup.addBuff && (!setup.hasSleepImmunity || !setup.hasSleepImmunity())) { try { setup.addBuff("well_rested", 480); } catch (e) {} } if (setup.mining && setup.mining.refillEnergy) { try { setup.mining.refillEnergy(); } catch (e) {} } /* Repose carries the +20% charm-earnings buff into the morning we wake to. */ v.ojou_teaActiveDay = v.dayNumber || 0; /* Mirror the flag as a real buff so it shows in the active buffs UI and the cheat menu's buff list. Duration = rest of the new day. */ if (typeof setup.addBuff === "function") { try { var minsLeft = Math.max(60, 1440 - (v.timeInMinutes || 0)); setup.addBuff("ojou_heiress_repose", minsLeft); } catch (e) {} } return true; }; /* Vanity: daily small charisma kicker. */ setup.ojouVanityRitual = function() { var v = State.variables; var today = v.dayNumber || 0; if ((v.ojou_lastVanityDay || 0) === today) return false; v.ojou_lastVanityDay = today; if (typeof setup.addBuff === "function") { try { setup.addBuff("ojou_polished", 480); } catch (e) {} } return true; }; /* Buy a wine bottle. Cost $2,000 per bottle. Cap inventory at 20. */ setup.ojouBuyWine = function() { var v = State.variables; if (!v.ojou_wineInventory) v.ojou_wineInventory = []; if (v.ojou_wineInventory.length >= 20) return "full"; if ((v.money || 0) < 2000) return "no_money"; v.money -= 2000; v.ojou_wineInventory.push({ purchaseDay: v.dayNumber || 0, cost: 2000 }); return "ok"; }; /* Compute current sale value of one wine bottle by index. */ setup.ojouWineValue = function(idx) { var v = State.variables; var bottle = (v.ojou_wineInventory || [])[idx]; if (!bottle) return 0; var days = (v.dayNumber || 0) - bottle.purchaseDay; if (days < 0) days = 0; var divisor = (v.ojou_libraryBooksRead && v.ojou_libraryBooksRead.indexOf("wineGuide") !== -1) ? 15 : 30; var multiplier = 1 + Math.min(days / divisor, 9); return Math.floor(bottle.cost * multiplier); }; /* Sell one wine bottle by index. Returns the sale value or 0 if missing. */ setup.ojouSellWine = function(idx) { var v = State.variables; if (!v.ojou_wineInventory) return 0; var bottle = v.ojou_wineInventory[idx]; if (!bottle) return 0; var value = setup.ojouWineValue(idx); v.money = (v.money || 0) + value; v.ojou_wineInventory.splice(idx, 1); return value; }; /* Host a recital. Returns payout in dollars, or 0 if on cooldown. */ setup.ojouHostRecital = function() { var v = State.variables; var today = v.dayNumber || 0; if (today - (v.ojou_lastRecitalDay || -7) < 7) return 0; v.ojou_lastRecitalDay = today; var payout = 5000 + Math.floor(Math.random() * 3001); if (v.ojou_libraryBooksRead && v.ojou_libraryBooksRead.indexOf("musicTheory") !== -1) { payout = Math.floor(payout * 1.5); } v.money = (v.money || 0) + payout; v.ojou_lastRecitalPayout = payout; return payout; }; /* Layer Repose buff and Investment book bonus onto the Phase 1 pay multipliers. */ (function patchPayMultiplier() { if (!setup.ojouBuffs || setup.ojouBuffs._phase3Patched) return; var originalPay = setup.ojouBuffs.payMultiplier.bind(setup.ojouBuffs); var originalStream = setup.ojouBuffs.streamMultiplier.bind(setup.ojouBuffs); setup.ojouBuffs.payMultiplier = function(jobKey) { var v = State.variables; var mult = originalPay(jobKey); if (mult === 1.0) return mult; if (setup.ojouHasRepose && setup.ojouHasRepose()) mult *= 1.2; if (v.ojou_libraryBooksRead && v.ojou_libraryBooksRead.indexOf("investment") !== -1) mult *= 1.1; return mult; }; setup.ojouBuffs.streamMultiplier = function(category) { var mult = originalStream(category); if (mult === 1.0) return mult; if (setup.ojouHasRepose && setup.ojouHasRepose()) mult *= 1.2; return mult; }; setup.ojouBuffs._phase3Patched = true; })(); <</script>>
<<nobr>> <<set $lastLocation = "BuriedWineVault">> <div style="background: #0a0508; min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a0dc; text-align: center;">🍷 The Buried Wine Vault</h1> <<if $ojou_wineVaultRestored>> <div style="background: linear-gradient(135deg, #2a1424 0%, #1a0a1a 100%); padding: 22px; border-radius: 12px; border: 2px solid #c9a0dc; margin-bottom: 20px;"> <p style="color: #e8c9e8; font-size: 16px; line-height: 1.7; margin: 0;">The stone chamber is swept clean. Fresh wine racks line the walls, varnished and ready to be filled. A wrought iron chandelier hangs lit overhead. Even the iron door at the back has been oiled and rehung true. The vault smells of beeswax and cedar. It is ready for a proper cellar again.</p> </div> <<else>> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0008 100%); padding: 22px; border-radius: 12px; border: 2px solid #6a0dad; margin-bottom: 20px;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.7; margin: 0;">The stairs end in a stone chamber thick with dust. Tipped over wine racks lie in heaps. Glass crunches underfoot, ancient bottles long since shattered. The ceiling is the underside of your mansion's foundation. The walls are older, fitted stone. An iron door stands at the back of the room, ajar.</p> </div> <</if>> <<if $physicalTraits.includes("Ojou") && !$ojou_wineVaultRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px; text-align: center;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛠️ Restore This Room</h3> <p style="color: #d4a5d4; line-height: 1.6; margin: 0 0 15px 0;">Bring in workers, materials, and furnishings to return this room to her standard. Cost: <strong style="color: #ffd700;">$400,000</strong>.</p> <<if $money >= setup.ojouRenovationCosts.wineVault>> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Begin restoration</div>">> <<run setup.renovateOjouRoom("wineVault", setup.ojouRenovationCosts.wineVault)>> <<run window.advanceTime(120)>> <<goto `passage()`>> <</link>> <<else>> <p style="color: #ff6b6b; font-style: italic; margin: 0;">You cannot afford this restoration yet.</p> <</if>> </div> <</if>> <<if $physicalTraits.includes("Ojou") && $ojou_wineVaultRestored>> <div style="border: 3px solid #722f37; border-radius: 10px; padding: 18px; background: #2a1414; margin-bottom: 20px;"> <h3 style="color: #d4a5a5; margin: 0 0 10px 0;">🍷 Aging Cellar</h3> <p style="color: #e8c9c9; line-height: 1.5; margin: 0 0 12px 0;">Bottles in cellar: <strong><<= $ojou_wineInventory.length>> / 20</strong>. Each bottle gains value with age.</p> <<if $ojou_wineInventory.length < 20>> <<if $money >= 2000>> <<link "<div style='background: #722f37; color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; margin: 6px 0; cursor: pointer;'>Buy a bottle ($2,000)</div>">><<run setup.ojouBuyWine()>><<run window.advanceTime(10)>><<goto `passage()`>><</link>> <<else>><p style="color: #ff6b6b; font-style: italic;">Not enough money for another bottle.</p><</if>> <<else>><p style="color: #d4a5a5; font-style: italic;">The cellar is at capacity.</p><</if>> <<if $ojou_wineInventory.length > 0>> <div style="margin-top: 12px; padding-top: 12px; border-top: 1px solid #722f37;"> <p style="color: #d4a5a5; margin: 0 0 8px 0;">Bottles in your cellar:</p> <<for _wi = 0; _wi < $ojou_wineInventory.length; _wi++>> <<set _wval = setup.ojouWineValue(_wi)>> <<set _wage = ($dayNumber || 0) - $ojou_wineInventory[_wi].purchaseDay>> <div style="display: flex; align-items: center; gap: 12px; margin: 6px 0; padding: 6px 10px; background: #1a0a0a; border-radius: 6px;"> <span style="flex: 1; color: #e8c9c9;">Bottle aged <<= _wage>> day<<if _wage !== 1>>s<</if>>. Worth $<<= _wval>></span> <<capture _wi>><<link "<div style='background: #722f37; color: white; padding: 6px 14px; border-radius: 4px; font-size: 13px; cursor: pointer; display: inline-block;'>Sell</div>">><<run setup.ojouSellWine(_wi)>><<goto `passage()`>><</link>><</capture>> </div> <</for>> </div> <</if>> </div> <</if>> <h2 style="color: #c9a0dc;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;"> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 15px; background: #1a0a1a;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🚪 The Drawing Room</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 12px 0;">Through the iron door, into a sheet covered parlor.</p> <<link "<div style='background: #6a0dad; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Enter</div>">><<run window.advanceTime(5)>><<goto "BuriedDrawingRoom">><</link>> </div> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 15px; background: #1a0a1a;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">⬆️ Climb back up</h3> <p style="color: #aaa; font-size: 14px; margin: 0 0 12px 0;">Return to your wine cellar.</p> <<link "<div style='background: #667eea; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Ascend</div>">><<run window.advanceTime(5)>><<goto "MansionWineCellar">><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BuriedDrawingRoom">> <div style="background: #0a0508; min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a0dc; text-align: center;">🎼 The Drawing Room</h1> <<if $ojou_drawingRoomRestored>> <div style="background: linear-gradient(135deg, #2a1424 0%, #1a0a1a 100%); padding: 22px; border-radius: 12px; border: 2px solid #c9a0dc; margin-bottom: 20px;"> <p style="color: #e8c9e8; font-size: 16px; line-height: 1.7; margin: 0;">The sheets are gone. The sofa is reupholstered in deep plum velvet, the armchairs polished to mirror sheen. The grand piano stands uncovered against the far wall, its lacquer restored, its keys touched up by a tuner. The family portraits have been cleaned and rehung in matching gilt frames. The heiress's portrait, at last, looks at home again.</p> </div> <<else>> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0008 100%); padding: 22px; border-radius: 12px; border: 2px solid #6a0dad; margin-bottom: 20px;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.7; margin: 0;">A parlor caught mid breath. White sheets cover everything: a sofa, a pair of armchairs, a draped shape near the windowless wall that must be a grand piano. Portraits line the far wall. One of them, a young woman with golden drill curls and a refined smile, catches your eye and holds it.</p> </div> <</if>> <<if $physicalTraits.includes("Ojou") && $ojou_drawingRoomRestored>> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🎼 Host a Recital</h3> <p style="color: #d4a5d4; line-height: 1.5; margin: 0 0 12px 0;">Invite guests for an evening of piano and conversation. Burns four hours. Cooldown: once per week.</p> <<set _daysSinceRecital = ($dayNumber || 0) - $ojou_lastRecitalDay>> <<if _daysSinceRecital >= 7>> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; cursor: pointer;'>Host the recital</div>">> <<run setup.ojouHostRecital()>> <<run window.advanceTime(240)>> <<goto `passage()`>> <</link>> <<else>> <p style="color: #d4a5d4; font-style: italic; margin: 0;">Next recital available in <<= 7 - _daysSinceRecital>> day<<if 7 - _daysSinceRecital !== 1>>s<</if>>.</p> <</if>> <<if $ojou_lastRecitalPayout && $ojou_lastRecitalDay === ($dayNumber || 0)>> <p style="color: #ffd700; margin-top: 10px;">Tonight's purse: <strong>$<<= $ojou_lastRecitalPayout>></strong></p> <</if>> </div> <</if>> <<if $physicalTraits.includes("Ojou") && !$ojou_drawingRoomRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px; text-align: center;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛠️ Restore This Room</h3> <p style="color: #d4a5d4; line-height: 1.6; margin: 0 0 15px 0;">Bring in workers, materials, and furnishings to return this room to her standard. Cost: <strong style="color: #ffd700;">$200,000</strong>.</p> <<if $money >= setup.ojouRenovationCosts.drawingRoom>> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Begin restoration</div>">> <<run setup.renovateOjouRoom("drawingRoom", setup.ojouRenovationCosts.drawingRoom)>> <<run window.advanceTime(120)>> <<goto `passage()`>> <</link>> <<else>> <p style="color: #ff6b6b; font-style: italic; margin: 0;">You cannot afford this restoration yet.</p> <</if>> </div> <</if>> <h2 style="color: #c9a0dc;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 15px;"> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 15px; background: #1a0a1a;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">📚 The Library</h3> <<link "<div style='background: #6a0dad; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Enter</div>">><<run window.advanceTime(3)>><<goto "BuriedLibrary">><</link>> </div> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 15px; background: #1a0a1a;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🫖 The Tea Room</h3> <<link "<div style='background: #6a0dad; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Enter</div>">><<run window.advanceTime(3)>><<goto "BuriedTeaRoom">><</link>> </div> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 15px; background: #1a0a1a;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛏️ The Bedchamber</h3> <<link "<div style='background: #6a0dad; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Enter</div>">><<run window.advanceTime(3)>><<goto "BuriedBedchamber">><</link>> </div> <div style="border: 3px solid #6a0dad; border-radius: 10px; padding: 15px; background: #1a0a1a;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🍷 The Wine Vault</h3> <<link "<div style='background: #6a0dad; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Return</div>">><<run window.advanceTime(3)>><<goto "BuriedWineVault">><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BuriedLibrary">> <div style="background: #0a0508; min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a0dc; text-align: center;">📚 The Library</h1> <<if $ojou_libraryRestored>> <div style="background: linear-gradient(135deg, #2a1424 0%, #1a0a1a 100%); padding: 22px; border-radius: 12px; border: 2px solid #c9a0dc; margin-bottom: 20px;"> <p style="color: #e8c9e8; font-size: 16px; line-height: 1.7; margin: 0;">The shelves are oiled and full again, the worst of the mildewed volumes replaced with handsome new bindings. The writing desk shines under fresh lamplight, ink and paper laid out. The room smells faintly of cedar, paper, and bergamot. It is a library again.</p> </div> <<else>> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0008 100%); padding: 22px; border-radius: 12px; border: 2px solid #6a0dad; margin-bottom: 20px;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.7; margin: 0;">Floor to ceiling shelves of leather bound books, more than half of them ruined by mildew. An inlaid writing desk sits at the center of the room. A slim leather journal lies open on it, the final entry interrupted mid sentence.</p> </div> <</if>> <<if $physicalTraits.includes("Ojou") && !$ojou_libraryRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px; text-align: center;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛠️ Restore This Room</h3> <p style="color: #d4a5d4; line-height: 1.6; margin: 0 0 15px 0;">Bring in workers, materials, and furnishings to return this room to her standard. Cost: <strong style="color: #ffd700;">$75,000</strong>.</p> <<if $money >= setup.ojouRenovationCosts.library>> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Begin restoration</div>">> <<run setup.renovateOjouRoom("library", setup.ojouRenovationCosts.library)>> <<run window.advanceTime(120)>> <<goto `passage()`>> <</link>> <<else>> <p style="color: #ff6b6b; font-style: italic; margin: 0;">You cannot afford this restoration yet.</p> <</if>> </div> <</if>> <<if $physicalTraits.includes("Ojou") && $ojou_libraryRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">📚 The Restored Bookshelf</h3> <p style="color: #d4a5d4; line-height: 1.5; margin: 0 0 12px 0;">Curated volumes that befit her standard. Each is consumed on reading.</p> <<for _bk, _b range setup.ojouBooks>> <<set _alreadyRead = ($ojou_libraryBooksRead && $ojou_libraryBooksRead.indexOf(_bk) !== -1)>> <div style="margin: 8px 0; padding: 10px; background: #0d0518; border: 1px solid #6a0dad; border-radius: 6px;"> <p style="margin: 0 0 6px 0;"><strong style="color: #c9a0dc;"><<= _b.title>></strong> <span style="color: #888; font-size: 12px;">($<<= _b.cost>>)</span></p> <p style="color: #d4a5d4; margin: 0 0 8px 0; font-size: 14px;"><<= _b.desc>></p> <<if _alreadyRead>> <span style="color: #51cf66; font-size: 13px;">✓ Read</span> <<elseif $money >= _b.cost>> <<capture _bk>><<link "<div style='background: #6a0dad; color: white; padding: 6px 14px; border-radius: 4px; font-size: 13px; display: inline-block; cursor: pointer;'>Buy and read</div>">><<run setup.ojouBuyAndReadBook(_bk)>><<run window.advanceTime(60)>><<goto `passage()`>><</link>><</capture>> <<else>> <span style="color: #ff6b6b; font-style: italic; font-size: 13px;">Cannot afford yet.</span> <</if>> </div> <</for>> </div> <</if>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">📖 Her Journal</h3> <p style="color: #d4a5d4; font-size: 14px; margin: 0 0 12px 0;">Five entries survive the damage. The rest is ash and watermark.</p> <<link "<div style='background: #6a0dad; color: white; padding: 10px 25px; border-radius: 6px; font-weight: bold; display: inline-block;'>Read the journal</div>">><<goto "OjouJournalRead">><</link>> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Back to the Drawing Room</div>">><<run window.advanceTime(3)>><<goto "BuriedDrawingRoom">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BuriedTeaRoom">> <div style="background: #0a0508; min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a0dc; text-align: center;">🫖 The Tea Room</h1> <<if $ojou_teaRoomRestored>> <div style="background: linear-gradient(135deg, #2a1424 0%, #1a0a1a 100%); padding: 22px; border-radius: 12px; border: 2px solid #c9a0dc; margin-bottom: 20px;"> <p style="color: #e8c9e8; font-size: 16px; line-height: 1.7; margin: 0;">The lacquered table is polished to a deep black sheen. The two delicate chairs have been recaned. A fresh tea service waits, the porcelain washed, the linens crisp. Bergamot is no longer just a memory in the cloth. It is the room's active fragrance.</p> </div> <<else>> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0008 100%); padding: 22px; border-radius: 12px; border: 2px solid #6a0dad; margin-bottom: 20px;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.7; margin: 0;">A small chamber, perfectly preserved. A low lacquered table, two delicate chairs, a tea service laid out for two. The water has long since gone, the leaves dust. A faint scent of bergamot still clings to the linens.</p> </div> <</if>> <<if $physicalTraits.includes("Ojou") && !$ojou_teaRoomRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px; text-align: center;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛠️ Restore This Room</h3> <p style="color: #d4a5d4; line-height: 1.6; margin: 0 0 15px 0;">Bring in workers, materials, and furnishings to return this room to her standard. Cost: <strong style="color: #ffd700;">$25,000</strong>.</p> <<if $money >= setup.ojouRenovationCosts.teaRoom>> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Begin restoration</div>">> <<run setup.renovateOjouRoom("teaRoom", setup.ojouRenovationCosts.teaRoom)>> <<run window.advanceTime(120)>> <<goto `passage()`>> <</link>> <<else>> <p style="color: #ff6b6b; font-style: italic; margin: 0;">You cannot afford this restoration yet.</p> <</if>> </div> <</if>> <<if $physicalTraits.includes("Ojou") && $ojou_teaRoomRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🫖 Take Tea</h3> <p style="color: #d4a5d4; line-height: 1.5; margin: 0 0 12px 0;">A refined afternoon ritual. Grants Heiress's Repose for the rest of today, adding +20% to the following jobs: Negotiator, Cocktail Waitress, Model, Secretary, Mayor. Streams: Styling, Music, ASMR, Cooking.</p> <<if $ojou_lastTeaDay === ($dayNumber || 0)>> <p style="color: #51cf66; font-style: italic; margin: 0;">You have already taken tea today.</p> <<else>> <<link "<div style='background: #6a0dad; color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; cursor: pointer;'>Take tea</div>">><<run setup.ojouTakeTea()>><<run window.advanceTime(30)>><<goto `passage()`>><</link>> <</if>> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Back to the Drawing Room</div>">><<run window.advanceTime(3)>><<goto "BuriedDrawingRoom">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BuriedBedchamber">> <div style="background: #0a0508; min-height: 100vh; padding: 20px;"> <h1 style="color: #c9a0dc; text-align: center;">🛏️ The Bedchamber</h1> <<if $ojou_bedchamberRestored>> <div style="background: linear-gradient(135deg, #2a1424 0%, #1a0a1a 100%); padding: 22px; border-radius: 12px; border: 2px solid #c9a0dc; margin-bottom: 20px;"> <p style="color: #e8c9e8; font-size: 16px; line-height: 1.7; margin: 0;">The canopied bed has new hangings in cream silk and the mattress has been replaced. The vanity gleams, its mirror cleaned, its drawers full of fresh combs and powders. The rosewood wardrobe stands true again. The family crest on the jewelry case looks freshly polished, as though it never spent a day in the dark.</p> </div> <<else>> <div style="background: linear-gradient(135deg, #1a0a1a 0%, #0a0008 100%); padding: 22px; border-radius: 12px; border: 2px solid #6a0dad; margin-bottom: 20px;"> <p style="color: #c9a0dc; font-size: 16px; line-height: 1.7; margin: 0;">A grand canopied bed dominates the room, the hangings rotting but the heavy wood frame intact. A tall vanity stands against the far wall, its mirror somehow uncracked. A rosewood wardrobe leans beside it. On the vanity sits a jewelry case bearing the same family crest you saw in the Drawing Room portraits.</p> </div> <</if>> <<if $physicalTraits.includes("Ojou") && !$ojou_bedchamberRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px; text-align: center;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛠️ Restore This Room</h3> <p style="color: #d4a5d4; line-height: 1.6; margin: 0 0 15px 0;">Bring in workers, materials, and furnishings to return this room to her standard. Cost: <strong style="color: #ffd700;">$500,000</strong>.</p> <<if $money >= setup.ojouRenovationCosts.bedchamber>> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Begin restoration</div>">> <<run setup.renovateOjouRoom("bedchamber", setup.ojouRenovationCosts.bedchamber)>> <<run window.advanceTime(120)>> <<goto `passage()`>> <</link>> <<else>> <p style="color: #ff6b6b; font-style: italic; margin: 0;">You cannot afford this restoration yet.</p> <</if>> </div> <</if>> <<if $physicalTraits.includes("Ojou") && $ojou_bedchamberRestored>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">🛏️ Heiress's Rest</h3> <p style="color: #d4a5d4; line-height: 1.5; margin: 0 0 12px 0;">Sleep in her bed. Advance to 6am with full rest, plus Heiress's Repose for tomorrow: +20% to the following jobs: Negotiator, Cocktail Waitress, Model, Secretary, Mayor. Streams: Styling, Music, ASMR, Cooking.</p> <<link "<div style='background: #6a0dad; color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; cursor: pointer;'>Sleep here</div>">> <<run setup.ojouSleepBedchamber()>> <<goto `passage()`>> <</link>> </div> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 10px 0;">💄 Vanity Ritual</h3> <p style="color: #d4a5d4; line-height: 1.5; margin: 0 0 12px 0;">Sit at the vanity. A 30 minute beauty ritual grants the Polished buff (small Charisma kicker for the rest of the day).</p> <<if $ojou_lastVanityDay === ($dayNumber || 0)>> <p style="color: #51cf66; font-style: italic; margin: 0;">You are already polished for today.</p> <<else>> <<link "<div style='background: #6a0dad; color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; cursor: pointer;'>Perform vanity ritual</div>">><<run setup.ojouVanityRitual()>><<run window.advanceTime(30)>><<goto `passage()`>><</link>> <</if>> </div> <</if>> <<if !$ojou_transformed>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 20px; background: #1a0a2a; margin-bottom: 20px;"> <h3 style="color: #c9a0dc; margin: 0 0 12px 0;">👗 The Heirloom Kit</h3> <p style="color: #d4a5d4; line-height: 1.7; margin: 0 0 15px 0;">The wardrobe holds a single dress, immaculately preserved under glass. The jewelry case opens at a touch: pearls, a hair comb, a folding fan, a parasol. Every piece is hers. Every piece would fit you.</p> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 14px 32px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer; box-shadow: 0 0 18px rgba(201,160,220,0.5);'>Put it all on</div>">> <<goto "OjouTransformation">> <</link>> </div> <<else>> <div style="border: 3px solid #c9a0dc; border-radius: 10px; padding: 18px; background: #1a0a2a; margin-bottom: 20px;"> <p style="color: #d4a5d4; font-style: italic; margin: 0;">The vanity mirror reflects you. You are wearing her things now. They are yours.</p> </div> <</if>> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>← Back to the Drawing Room</div>">><<run window.advanceTime(3)>><<goto "BuriedDrawingRoom">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set _entryIdx = $ojou_journalEntriesRead>> <<set _entries = [ { title: "Entry the First", body: "My debut at the Spring Gala. Father introduced me to half the city. I curtseyed thirty seven times. My feet ached but my smile held. They called me radiant. I think I would have preferred to be called clever." }, { title: "Entry the Fourth", body: "Three hours at the piano this morning. My governess says I am improving. The new piece is by a composer Father imported from abroad. Mother does not approve of the foreign music. I find it the only honest thing in this house." }, { title: "Entry the Eleventh", body: "The engagement is dissolved. He was a fool and a coward and I am relieved. I do not say that aloud. Mother is in bed for the third day. Father has not spoken to me in two. The portraitists are still coming on Tuesday." }, { title: "Entry the Twenty Second", body: "I have not left the house in a month. The garden is enough. The library is enough. I have taken tea alone every afternoon and found it a comfort. The world outside is loud and the world inside is mine." }, { title: "Entry the Forty First", body: "Smoke. I can smell smoke. The servants are shouting. I should " } ]>> <<if _entryIdx >= _entries.length>> <div style="background: #0a0508; min-height: 100vh; padding: 30px;"> <h1 style="color: #c9a0dc; text-align: center;">📖 The journal ends.</h1> <div style="background: #1a0a2a; padding: 22px; border-radius: 12px; border: 2px solid #6a0dad; margin: 20px auto; max-width: 600px;"> <p style="color: #d4a5d4; font-style: italic; line-height: 1.8; text-align: center; margin: 0;">The remaining pages are scorched beyond reading. You close the cover gently.</p> </div> <div style="text-align: center;"> <<link "<div style='background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block;'>Close the journal</div>">><<goto "BuriedLibrary">><</link>> </div> </div> <<else>> <<set _entry = _entries[_entryIdx]>> <div style="background: #0a0508; min-height: 100vh; padding: 30px;"> <h1 style="color: #c9a0dc; text-align: center;">📖 <<print _entry.title>></h1> <div style="background: #1a0a2a; padding: 28px; border-radius: 12px; border: 2px solid #6a0dad; margin: 20px auto; max-width: 600px;"> <p style="color: #d4a5d4; line-height: 1.9; font-style: italic; margin: 0; font-size: 17px;"><<print _entry.body>></p> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Turn the page</div>">> <<run window.advanceTime(10)>> <<set $ojou_journalEntriesRead = $ojou_journalEntriesRead + 1>> <<goto "OjouJournalRead">> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<if $possessionActive>> <div style="max-width: 640px; margin: 30px auto; padding: 22px; background: #1a0a1a; border: 2px solid #c9a0dc; border-radius: 12px; text-align: center;"> <p style="color: #d4a5d4; font-size: 16px; line-height: 1.6; margin: 0 0 16px 0;">The dress refuses your hands. The pearls slip from your fingers. Whatever sleeps in these heirlooms knows you are not the one wearing your own skin tonight, and it will not be tricked into binding to a borrowed body.</p> <<link "<div style='background: #6a0dad; color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; cursor: pointer;'>Step back</div>">><<goto "BuriedBedchamber">><</link>> </div> <<else>> <<set _wasMale = ($gender === "male")>> <<set _chestOrder = ["flat masculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _preChest = ($appearance && $appearance.chestSize) ? $appearance.chestSize : "medium">> <<set _willGrowChest = (_chestOrder.indexOf(_preChest) < _chestOrder.indexOf("large"))>> <<set _isMature = ($appearance && $appearance.age === "Mature Adult")>> <<set _preHairColor = ($appearance && $appearance.hairColor) ? $appearance.hairColor : "Brown">> <<set _preHairLength = ($appearance && $appearance.hairLength) ? $appearance.hairLength : "short">> <<set _preSkinTone = ($appearance && $appearance.skinTone) ? $appearance.skinTone : "pale">> <<set _hairAlreadyBlonde = (_preHairColor === "Blonde" || _preHairColor === "Platinum Blonde")>> <<set _hairAlreadyLong = (_preHairLength === "long")>> <<set _skinAlreadyPale = (_preSkinTone === "pale")>> <<run setup.applyOjouTransformation()>> <<if !$physicalTraits.includes("Ojou")>><<run $physicalTraits.push("Ojou")>><</if>> <<set $ojou_transformed = true>> <<run setup.achievements.unlock("ojou_awakening")>> <<set _ojouImage = "Images/Transformation/Ojou_" + (_isMature ? "Mature" : "Adult") + ".webp">> <div style="background: linear-gradient(180deg, #0d0015 0%, #1a0a2e 50%, #0d0015 100%); min-height: 100vh; padding: 30px;"> <div style="max-width: 720px; margin: 0 auto; color: #ddd; font-size: 17px; line-height: 1.7;"> <p>You undress at her vanity. The dress, the pearls, the fan, the comb, all laid out like she meant for you to find them. You step into the corset and the silk pulls itself snug at your waist, hooks finding hooks without your help. A warm tingle climbs out of the fabric and into your spine. <em>Oh. That isn't me doing that.</em></p> <<if _wasMale>> <hr style="border: none; border-top: 1px solid #6a0dad; margin: 20px auto; width: 50%; opacity: 0.5;"> <p>Your jaw softens, your shoulders draw inward, your voice climbs an octave when you breathe out. Your hips flare with a slow audible shift of bone, weight settling into your thighs and rear until the corset is suddenly snug across a body it was clearly designed for. Between your thighs your cock softens, shrinks, and folds away into yourself. The heat blooming in its place is slick and aching, and the first pulse from that brand new pussy is so sharp you have to grip the vanity to stay standing. <em>Oh. That's mine now.</em></p> <</if>> <<if _willGrowChest>> <hr style="border: none; border-top: 1px solid #6a0dad; margin: 20px auto; width: 50%; opacity: 0.5;"> <<if _preChest === "flat" || _preChest === "flat masculine">> <p>Flesh swells beneath the bodice where there had been only skin. Tiny mounds push outward and keep pushing, your new nipples hardening against the silk. <em>Oh god. They're actually growing.</em> The corset stretches as new breasts fill the cups and then overflow them, eager and heavy and yours. You cup your hands around the swelling weight through the fabric and a low moan slips out at the contact.</p> <<elseif _preChest === "small">> <p>Your small breasts swell inside the corset, modest mounds growing past modest into proper. <em>Mmm. Bigger. Right where she wanted them.</em> The bodice stretches to meet the new shape and your hands rise to cup the growing weight through the silk, fingers spreading wider with every pulse of growth.</p> <<else>> <p>Your chest fills out inside the corset, a slow rich swell from medium into something fuller and heavier. The bodice that was nearly loose becomes snug, then perfectly fitted. <em>Mmm. Yes. This is the size she wore.</em> Your hands rise automatically to cup the new weight through the fabric.</p> <</if>> <</if>> <hr style="border: none; border-top: 1px solid #6a0dad; margin: 20px auto; width: 50%; opacity: 0.5;"> <p> <<if !_hairAlreadyLong>>Your hair grows down your back in long shivering waves.<<else>>Your already long hair thickens and lengthens further.<</if>> <<if _hairAlreadyBlonde>> The pale gold deepens into the exact rich blonde of the woman in the portrait.<<elseif _preHairColor === "Black">> The deep black bleeds out from root to tip and pure gold floods in to replace it. <em>Midnight to sunlight.</em><<elseif _preHairColor === "Brown">> The brown bleeds out and pure gold rushes in to replace it.<<elseif _preHairColor === "Red">> The red cools into honey, then into pure spun gold.<<else>> The color shifts and pales through every shade until it settles into the rich blonde of the woman in the portrait.<</if>> The strands gather themselves into two perfect drill curls that frame your face. <<if _isMature>>They sweep almost to your hips, thick and luxurious.<<else>>Soft ringlets sit at your shoulders.<</if>> </p> <p> <<if _skinAlreadyPale>>Your skin lightens further still, the faint warmth bleeding out until you match her porcelain.<<elseif _preSkinTone === "dark">>Your dark skin pales through caramel, honey, and ivory, settling into porcelain. <em>Oh. I look completely different.</em><<else>>Your tan pales to porcelain, the old warmth bleeding out of you.<</if>> The pearls warm against your throat, the comb clicks into your hair behind your ear, and the color of your eyes sharpens to a clear blue green that did not used to be yours.</p> <p>You straighten without meaning to, your chin lifting and your shoulders drawing back into a posture you have never held before. <em>Something in you settles into the shape of her as though you have always been meant to wear it.</em> The mirror shows you a stranger, and the stranger is you.</p> <div style="text-align: center; margin: 20px 0;"> <img @src="_ojouImage" alt="Ojou-sama" style="max-width: 100%; max-height: 600px; border-radius: 12px; border: 2px solid #c9a0dc; box-shadow: 0 0 30px rgba(201,160,220,0.6);" onerror="this.style.display='none';"> </div> <p>You raise the folding fan and flick it open in front of your face with a practiced motion you never learned but somehow already know. A small superior smile forms on your lips without permission, the kind of smile that knows precisely who in the room is in charge. <em>Her bearing has slipped into you as easily as her dress did, and you do not want to take it back off.</em> The laugh rises out of you in three perfect syllables, refined and a little cruel.</p> <p style="color: #c9a0dc; font-size: 22px; line-height: 1.4; margin: 18px 0; font-style: italic; text-align: center; text-shadow: 0 0 12px rgba(201,160,220,0.7);">"Ohohoho."</p> <p>You've become an Ojou-sama, refined and haughty and unmistakably high born.</p> <div style="background: #2a1a2a; padding: 16px; border-radius: 10px; border: 2px solid #c9a0dc; margin: 25px auto; max-width: 600px; text-align: center; box-shadow: 0 0 18px rgba(201,160,220,0.4);"> <p style="color: #c9a0dc; margin: 0 0 6px 0; font-weight: bold;">✨ Trait Gained: Ojou-sama ✨</p> <p style="color: #d4a5d4; margin: 0; font-size: 15px;">Money and refinement come to you more easily. Your hair holds its shape no matter what.</p> </div> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #c9a0dc 0%, #6a0dad 100%); color: white; padding: 14px 36px; border-radius: 8px; font-weight: bold; display: inline-block; cursor: pointer;'>Step away from the mirror</div>">> <<run window.advanceTime(30)>> <<goto "BuriedBedchamber">> <</link>> </div> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $readOniRiddle = true>> <div style="background: linear-gradient(180deg, #2a2418 0%, #1a1308 100%); min-height: 100vh; padding: 30px;"> <h1 style="color: #b89c5c; text-align: center; margin-bottom: 8px;">📜 The Verse of Three Cups</h1> <p style="color: #998866; text-align: center; font-style: italic; margin-bottom: 30px;">Roisin's grandmother brought it back from Sakaide. No one remembers what it means.</p> <div style="max-width: 600px; margin: 0 auto; padding: 30px; background: #1a1308; border: 2px solid #b89c5c; border-radius: 12px; font-family: serif; font-size: 17px; line-height: 1.9; color: #ddc4a0;"> <p class="oni-fade" style="font-style: italic; margin: 0 0 18px 0; animation-delay: 0.1s;">Only the body that does not sleep<br>may pour these cups.</p> <p class="oni-fade" style="margin: 0 0 18px 0; animation-delay: 1.0s;">When the sky shows no light at all,<br>climb where the mountain breathes fire by night.<br>Pour the first cup in the iron bowl set in stone.</p> <p class="oni-fade" style="margin: 0 0 18px 0; animation-delay: 2.0s;">When the moon shows half her face,<br>walk the salt grass to the place behind this house.<br>Pour the second cup in the bowl the tide remembers.</p> <p class="oni-fade" style="margin: 0; animation-delay: 3.0s;">When the moon is round and full,<br>find the hot spring high in the cold.<br>Pour the last cup. The demon will know its name.</p> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #6e4ea8; color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Back to the living room</div>">> <<goto "RoisinBeachHouse">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "HiddenGrove">> <div style="background: linear-gradient(180deg, #1a2418 0%, #0a140a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #88c87c; text-align: center;">⛩️ Hidden Grove</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2a3d2a 0%, #88c87c 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #88c87c;"> <p style="color: #0a140a; font-size: 16px; margin: 0; line-height: 1.6;">A small overgrown shrine tucked deep in the dunes. A weathered torii half buried in salt grass. A flat stone basin under a wooden canopy. The sound of waves a hundred feet away. The air here is older than the city.</p> </div> <div style="border: 3px solid #4fc3b8; border-radius: 10px; padding: 15px; background: #1a2424; margin-bottom: 20px;"> <h3 style="color: #4fc3b8; margin: 0 0 10px 0;">🍶 A Stone Basin</h3> <p style="font-size: 14px; color: #aaccc4; margin: 0 0 12px 0; line-height: 1.5;">A shallow stone basin set into the shrine's plinth. Black with age. Water marked where rain has touched it.</p> <<if $giftInventory && ($giftInventory.sake_bottle || 0) > 0>> <<link "<div style='background: #4fc3b8; color: #0a140a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Pour sake into the basin</div>">> <<run setup.oni && setup.oni.tryCupOfTides && setup.oni.tryCupOfTides()>> <<goto "HiddenGrove">> <</link>> <<else>> <p style="font-size: 13px; color: #888; font-style: italic; margin: 0;">You have no sake to pour.</p> <</if>> <<if $oniLastBowlMessage>> <p style="font-size: 14px; color: #ddd; font-style: italic; margin: 12px 0 0 0; line-height: 1.5;">$oniLastBowlMessage</p> <</if>> </div> <div style="text-align: center; margin: 28px 0;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #f4a460 0%, #87ceeb 100%); color: white; padding: 12px 28px; border-radius: 10px; cursor: pointer; font-weight: bold;'>Walk back to the beach house</div>">> <<run advanceTime(10)>> <<goto "RoisinBeachHouse">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _wasMale = $bodyParts && ($bodyParts.gender === "male" || $bodyParts.gender === "futa")>> <<set _chestWas = ($bodyParts && $bodyParts.chest) || "medium">> <<set _wasFlat = _chestWas === "flat" || _chestWas === "flat masculine" || _chestWas === "small">> <<set _wasHuge = _chestWas === "huge" || _chestWas === "giant" || _chestWas === "gigantic">> <<set _buttWas = ($bodyParts && $bodyParts.butt) || "medium">> <<set _wasSmallButt = _buttWas === "flat" || _buttWas === "small" || _buttWas === "medium">> <<set _wasBigButt = _buttWas === "huge" || _buttWas === "giant" || _buttWas === "gigantic">> <<set _hairWas = ($appearance && $appearance.hairColor) || "">> <<set _wasSilverish = _hairWas && (String(_hairWas).toLowerCase() === "silver" || String(_hairWas).toLowerCase() === "white" || String(_hairWas).toLowerCase() === "platinum blonde")>> <<set _oniDesc = (setup.fullTransformations && setup.fullTransformations.Oni && setup.fullTransformations.Oni.description) || "A horned demon of the Sakazuki cup. Long silver hair, fangs, claws, and the strength of mountain spirits.">> <div style="background: linear-gradient(180deg, #050d0a 0%, #0d2520 30%, #1a4d3e 50%, #0d2520 70%, #050d0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <!-- Header with glow effect --> <div class="oni-fade" style="text-align: center; margin-bottom: 30px; animation-delay: 0s;"> <h1 style="color: #88c8b8; font-size: 42px; margin: 0; text-shadow: 0 0 30px #88c8b8, 0 0 60px #1a5e4a;">🍶 AWAKENING 🍶</h1> </div> <!-- Result Banner --> <div class="oni-fade" style="background: linear-gradient(135deg, #1a5e4a 0%, #88c8b8 50%, #1a5e4a 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; box-shadow: 0 0 40px rgba(136,200,184,0.6), inset 0 0 30px rgba(0,0,0,0.25); border: 2px solid #88c8b8; text-align: center; animation-delay: 0.25s;"> <p style="color: #e8f4ec; margin: 0 0 10px 0; font-size: 18px; text-transform: uppercase; letter-spacing: 2px;">You have become</p> <p style="color: #fff; font-size: 48px; font-weight: bold; margin: 0; text-shadow: 0 0 20px rgba(255,255,255,0.7), 0 4px 8px rgba(0,0,0,0.5);">Oni</p> <p style="color: #d4ebe0; font-style: italic; margin: 15px 0 0 0; font-size: 16px;"><<print _oniDesc>></p> </div> <!-- Transformation Story Section --> <div class="oni-fade" style="background: linear-gradient(180deg, #0d2520 0%, #0a1814 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; border: 2px solid #88c8b8; box-shadow: 0 4px 20px rgba(0,0,0,0.6); animation-delay: 0.5s;"> <h2 style="color: #88c8b8; margin: 0 0 20px 0; text-align: center; font-size: 24px;">✨ The Sake Takes Hold ✨</h2> <div style="color: #d4ebe0; font-size: 17px; line-height: 2; text-align: justify;"> <p>Steam curls around your bare shoulders as you sit alone in the moonlit hot spring, the stone bowl of the Cup of Demons heavy in your hands. The carved fangs along its rim catch the silver light. <em>I drank it. I really drank it.</em> The sake was sweet at first, then bitter, then something else entirely. Heat blooms low in your belly and refuses to settle. Around you the spring goes very still, as if the mountain itself is holding its breath.</p> <<if _wasMale>> <p>The first change comes between your thighs. Your cock softens against your wishes, the heat draining out of it as the flesh begins to pull inward. <em>Wait. Wait, no.</em> A long, shuddering moan tears out of you as the pleasure hits, far more intense than anything you have ever felt. Your shaft shrinks away in waves of slick, electric warmth, the head splitting and folding into delicate pink lips. Your balls draw up and vanish into a new wet heat. When it is done you are open and slick and aching, a fresh pussy clenching around nothing, dripping into the spring water. <em>Oh fuck. I have a cunt. I have a cunt and it is so fucking wet.</em> Your hips crack and widen with bright, building pressure, settling lower and rounder. Your waist pulls inward. Your throat softens. You are a woman now. The water laps higher against your new curves and every ripple feels obscene.</p> <<else>> <p>The heat sinks lower until it pools between your thighs, your pussy clenching hard around nothing as a wet pulse settles in deep. <em>Oh god. Oh god, it is starting in me.</em> Every breath drags more steam over your bare skin and every breath leaves you wetter. Your hips ache as the demon magic reaches into your bones, telling your body what it is going to become.</p> <</if>> <<if _wasFlat>> <p>You look down at your bare chest in time to see the first changes. Your nipples stiffen to hard, hot points, dragging a high gasp out of you. Then flesh begins to push outward from nothing, soft mounds budding under the skin and swelling with each heartbeat. <em>They are growing. They are actually growing.</em> Wave after wave of pleasure pulses through your chest as they fill in heavy and full. Your hands cup them on instinct and overflow at once, the new weight pulling forward, your nipples thick and tingling against your palms. <em>So heavy. So full. So mine.</em> Huge demon tits sit on your chest where there was nothing a breath ago, every tiny movement making them wobble against the steam.</p> <<else>> <<if _wasHuge>> <p>Your already heavy chest pulses with the magic. The flesh does not simply grow this time, it reshapes. Denser, hotter, more sensitive, every nerve waking up at once. <em>Oh fuck, they feel different. They feel hungry.</em> Your nipples stand thick and dark and aching, and the weight of your reshaped tits drags a long moan out of you. They settle into the demonic body the magic is sculpting, huge and full and shamelessly inviting.</p> <<else>> <p>Your chest answers the heat next. Your nipples harden first, achingly stiff, drawing a soft cry out of you. Then your breasts swell, flesh pushing outward in slow heavy waves of pleasure until your old shape is gone. <em>Bigger. So much bigger.</em> Huge, full tits sit heavy on your chest, nipples thick and tingling, every breath making them shift against the steam. The growth alone almost makes you cum.</p> <</if>> <</if>> <p>Bone moves above your hairline. Two points of slick black pressure push up through your scalp, hot and unstoppable, curving back and back until twin ram horns sit heavy on your head. <em>Horns. I have horns.</em> Your ears stretch into elegant points. Your gums ache as fangs slide down behind your lips, sharp little promises against your tongue. Your fingernails darken and lengthen into glossy black claws, and when you flex your hands the claws catch the moonlight like wet ink. Every change lands with another pulse between your thighs.</p> <<if _wasSmallButt>> <p>The pressure drops to your hips next, and you cry out as the bones crack and widen for the first time in your life. Flesh swells behind you, your ass filling out from nothing into round, full, heavy demon curves. <em>Oh god, I can feel it growing.</em> Each surge of growth rocks another wet pulse through your cunt. By the time it slows you have a thick, generous backside that the water can no longer hide, the spring lapping against the underswell of your new cheeks.</p> <<else>> <<if _wasBigButt>> <p>Your already full hips ache and reshape with cracking pressure, your generous ass settling into demon weight that is somehow heavier than before. <em>Even more. There is even more of me now.</em> Each tiny shift sends fat warm jiggles through the new flesh and another wet throb up through your core.</p> <<else>> <p>Your hips ache and widen, the bones answering the magic in long bright waves. Your ass swells round and full behind you, flesh pushing outward until generous demon curves bounce against the water. <em>So much fuller. So much more of me.</em> The change leaves you flushed and panting and obscenely wet.</p> <</if>> <</if>> <<if _wasSilverish>> <p>Your already pale hair brightens further, color bleeding out at the roots and traveling down each strand until it falls around your horns in long pure silver. Your skin cools and pales beside it, milk white against the dark stone of the spring. Then your eyes change. The reflection that stares back at you from the water has bright green irises, slit faintly, wet with hunger.</p> <<else>> <p>Your hair drains of color from the roots out, strand by strand, until it falls around your horns in long pure silver, weightless and cool against your shoulders. Your skin pales next, color washing out of you until you glow milk white in the moonlight. Then your eyes change, the irises burning through to bright demon green in the water's reflection.</p> <</if>> <p>The hunger settles last. It moves into your chest and your belly and the wet heat between your thighs and just stays there, patient, awake. <em>I want to take. I want to take everything.</em> Your new cunt clenches hard around the thought alone and you have to bite your lip to keep from moaning out loud. The fangs catch your lip and the small bright sting of it makes you wetter still.</p> <p>You stand in the spring, water sheeting off the body you now wear. Silver hair. Black horns. Pale skin. Heavy tits and a full ass and a soaking demon cunt and claws that gleam wet in the moonlight. <em>This is me. This is what I am now. And I am so, so hungry.</em></p> </div> </div> <!-- Body Changes Section --> <div class="oni-fade" style="background: linear-gradient(180deg, #0d2520 0%, #0a1814 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; border: 2px solid #88c8b8; box-shadow: 0 4px 20px rgba(0,0,0,0.6); animation-delay: 0.75s;"> <h2 style="color: #88c8b8; margin: 0 0 25px 0; text-align: center; font-size: 24px;">🌀 Your Body Transforms 🌀</h2> <div style="color: #d4ebe0; font-size: 16px; line-height: 1.9;"> <div style="background: rgba(136,200,184,0.08); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #88c8b8;"> <p style="margin: 0;"><strong style="color: #88c8b8; font-size: 18px;">👹 Horns & Fangs</strong></p> <p style="margin: 10px 0 0 0;">Twin black ram horns curve back from your forehead, hot and heavy, branding you as something no longer mortal. Fangs sit sharp behind your lips. Your ears taper to elegant points. Your fingernails have grown into glossy black claws that gleam wet in the moonlight. <em>Every part of me is a weapon now. And every weapon is wet.</em></p> </div> <<if _wasFlat>> <div style="background: rgba(109,184,168,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #6db8a8;"> <p style="margin: 0;"><strong style="color: #6db8a8; font-size: 18px;">💗 Chest</strong></p> <p style="margin: 10px 0 0 0;">Your once flat chest is gone. Heavy huge tits sit on you now, full and warm and shamelessly sensitive, nipples thick and aching to be touched. <em>I have never had anything like this. They feel incredible.</em> Every shift of your shoulders sets them bouncing against the steam.</p> </div> <<elseif _wasHuge>> <div style="background: rgba(109,184,168,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #6db8a8;"> <p style="margin: 0;"><strong style="color: #6db8a8; font-size: 18px;">💗 Chest</strong></p> <p style="margin: 10px 0 0 0;">Your already heavy chest has been reshaped into demon flesh, huge and full and hotter than before, every nerve singing. <em>They feel hungry. Like the rest of me.</em> Your dark nipples stand thick and stiff against the cool night air.</p> </div> <<else>> <div style="background: rgba(109,184,168,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #6db8a8;"> <p style="margin: 0;"><strong style="color: #6db8a8; font-size: 18px;">💗 Chest</strong></p> <p style="margin: 10px 0 0 0;">Your breasts have swollen huge and heavy, full demon tits that wobble against the steam with every breath. <em>So much fuller than I was. So much more.</em> Your stiff nipples ache for any touch at all.</p> </div> <</if>> <<if _wasSmallButt>> <div style="background: rgba(184,224,208,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #b8e0d0;"> <p style="margin: 0;"><strong style="color: #b8e0d0; font-size: 18px;">🍑 Hips and Rear</strong></p> <p style="margin: 10px 0 0 0;">Where your hips were once narrow they now flare into full demon curves. A generous large ass sits behind you, round and warm and bouncing softly with every shift of your weight. <em>I have a body now. A real body. And it knows what it wants.</em></p> </div> <<elseif _wasBigButt>> <div style="background: rgba(184,224,208,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #b8e0d0;"> <p style="margin: 0;"><strong style="color: #b8e0d0; font-size: 18px;">🍑 Hips and Rear</strong></p> <p style="margin: 10px 0 0 0;">Your already full ass has been resettled into demon flesh, heavy and round and gleaming pale in the moonlight. Each tiny shift sends warm jiggles up through your core. <em>Every step is going to feel like this from now on. Good.</em></p> </div> <<else>> <div style="background: rgba(184,224,208,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #b8e0d0;"> <p style="margin: 0;"><strong style="color: #b8e0d0; font-size: 18px;">🍑 Hips and Rear</strong></p> <p style="margin: 10px 0 0 0;">Your hips have widened and your ass has swollen into round, generous demon curves that bounce gently as you move. <em>Heavier. Fuller. Mine.</em></p> </div> <</if>> <<if _wasMale>> <div style="background: rgba(93,184,160,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #5db8a0;"> <p style="margin: 0;"><strong style="color: #5db8a0; font-size: 18px;">🔥 Intimate Areas</strong></p> <p style="margin: 10px 0 0 0;">Your cock is gone. In its place is a fresh, slick demon cunt, the lips swollen and flushed and aching, your new clit standing out hard and sensitive. <em>It is so wet down there. I can feel the water on every part of it.</em> Every shift of your thighs draws another wet pulse out of you.</p> </div> <<else>> <div style="background: rgba(93,184,160,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #5db8a0;"> <p style="margin: 0;"><strong style="color: #5db8a0; font-size: 18px;">🔥 Intimate Areas</strong></p> <p style="margin: 10px 0 0 0;">Your pussy has been reshaped into a hot, hungry demon cunt, the lips swollen and shamelessly wet, your clit standing out thick and sensitive. <em>I have never been this wet in my life.</em> Every tiny movement of your thighs sends another bright pulse up into your belly.</p> </div> <</if>> <<if _wasSilverish>> <div style="background: rgba(200,200,220,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #cccce0;"> <p style="margin: 0;"><strong style="color: #cccce0; font-size: 18px;">🌙 Hair and Skin</strong></p> <p style="margin: 10px 0 0 0;">Your already pale hair has gone pure silver to the roots, falling long and weightless around your horns. Your skin has cooled to demon white, milk pale in the moonlight, and your eyes burn bright green in the reflection.</p> </div> <<else>> <div style="background: rgba(200,200,220,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #cccce0;"> <p style="margin: 0;"><strong style="color: #cccce0; font-size: 18px;">🌙 Hair and Skin</strong></p> <p style="margin: 10px 0 0 0;">Your old hair color has drained away from the roots out, leaving long pure silver hair falling around your horns. Your skin has paled to milk white. Your eyes burn bright green in the water's reflection. <em>I do not look human anymore. Good.</em></p> </div> <</if>> <div style="background: rgba(155,89,182,0.1); padding: 20px; border-radius: 10px; border-left: 4px solid #9b59b6;"> <p style="margin: 0;"><strong style="color: #9b59b6; font-size: 18px;">✨ Identity</strong></p> <p style="margin: 10px 0 0 0;">The hunger that lives in you now is not borrowed. It is yours. <em>I want to take. I want to fuck. I want everything I see to know who I am.</em> You are not a woman who was given a body. You are an Oni. The mountain spirits gave you their strength and the sake gave you their appetite. This is who you are now. This is who you were always going to be.</p> </div> </div> </div> <!-- Full Body Image --> <div class="oni-fade" style="text-align: center; margin-bottom: 30px; animation-delay: 1s;"> <h3 style="color: #88c8b8; margin-bottom: 20px;">Your New Form</h3> <div style="display: inline-block; padding: 5px; background: linear-gradient(135deg, #1a5e4a 0%, #88c8b8 100%); border-radius: 12px; border: 3px solid #88c8b8; box-shadow: 0 0 30px rgba(196,160,64,0.5);"> <img src="Images/Transformation/Oni_Female.webp" alt="Oni" style="max-width: 450px; max-height: 600px; border-radius: 8px; display: block;" onerror="this.parentElement.parentElement.style.display='none';"> </div> </div> <!-- Continue Button --> <div class="oni-fade" style="text-align: center; margin-top: 30px; animation-delay: 1.25s;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #1a5e4a 0%, #88c8b8 50%, #1a5e4a 100%); color: #fff; padding: 15px 40px; border-radius: 10px; font-weight: bold; font-size: 18px; box-shadow: 0 4px 18px rgba(196,160,64,0.5); text-shadow: 0 1px 2px rgba(0,0,0,0.5);'>Step out of the water</div>">> <<run setup.oni && setup.oni.completeTransformation && setup.oni.completeTransformation()>> <<goto "MountainHotSpring">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BlackMarketGoods">> <h1>💊 Black Market Goods</h1> <div style="padding: 20px; background: linear-gradient(135deg, #2d1a1a 0%, #1a0a0a 100%); border-radius: 15px; margin-bottom: 20px; border: 2px solid #ff4444;"> <p style="color: #ddc; font-size: 17px; margin: 0; line-height: 1.6;"> The old man pulls aside a curtain at the back of the shop and waves you toward a battered wooden crate. "Questions cost extra," he says. "Money up front. Buy or get out." </p> </div> <h2 style="color: #ff8080;">In Stock</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <div style="border: 2px solid #b85c5c; border-radius: 10px; padding: 15px; background: #2a1a1a;"> <h3 style="color: #ff8080; margin-top: 0;">🍶 Sake Bottle</h3> <p style="font-size: 14px; color: #ccc;">Clay bottle, foreign script. The dealer does not say where he gets it. $25,000.</p> <<link "<div style='background: #b85c5c; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Buy ($25,000)</div>">> <<if $money >= 25000>> <<set $money -= 25000>> <<set $giftInventory["sake_bottle"] = ($giftInventory["sake_bottle"] || 0) + 1>> <</if>> <<goto "BlackMarketGoods">> <</link>> </div> </div> <br> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #434343; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; font-size: 16px;'>← Back to Shady Shop</div>">> <<goto "ShadyShop">> <</link>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "QueshaTalk">> <div style="background: linear-gradient(180deg, #0f2a3a 0%, #1a1a1a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #d81b60; border-radius: 12px; padding: 25px;"> <h1 style="color: #d81b60; text-align: center;">💬 Talking with Quesha</h1> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <<set _qImg = setup.getNPCImage("Quesha Epo")>> <<if _qImg>> <div style="text-align: center; margin: 15px 0;"> <img @src="_qImg" style="max-width: 100%; max-height: 320px; border-radius: 8px; border: 2px solid rgba(216, 27, 96, 0.5); box-shadow: 0 0 15px rgba(216, 27, 96, 0.25);" onerror="this.style.display='none';"> </div> <</if>> <</if>> <<set _talkRoll = random(1, 4)>> <<if _talkRoll === 1>> <p style="color: #ddd; line-height: 1.7;">She trails her fingers in the water. "Most people who come here don't know it's here. I like that. Quiet is good."</p> <<elseif _talkRoll === 2>> <p style="color: #ddd; line-height: 1.7;">"You ever just sit and listen to water? Really listen? My grandmother said the water is always talking. You just have to slow down enough."</p> <<elseif _talkRoll === 3>> <p style="color: #ddd; line-height: 1.7;">She laughs softly at something only she can see in the water. "Sorry. Old memory. From back before the city."</p> <<else>> <p style="color: #ddd; line-height: 1.7;">"You should come by the shop sometime. Beach side. I'll show you the maps. I've been collecting them for years."</p> <</if>> <<run setup.addRelationshipPoints("Quesha Epo", 5)>> <<if setup.islandLore.isAskable("Quesha Epo")>> <div style="background:linear-gradient(135deg,#1a1430,#0e0a1c); border:2px solid #7a6aa8; border-radius:10px; padding:14px 16px; margin:0 auto 15px; max-width:620px;"> <p style="color:#cdbdf0; font-size:15px; line-height:1.6; margin:0 0 10px 0;">You steer the talk toward the island itself. How does this place work? How long has it stood?</p> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#7a6aa8,#4a3d70); color:white; padding:9px 22px; border-radius:9px; font-weight:bold; cursor:pointer;'>Ask about the island</div>">> <<if setup.canCombineTap()>> <<set $lastLocationBeforeAsk = $lastLocation>> <<run setup.islandLore.recordAsk("Quesha Epo")>> <<goto "IslandLoreAccount">> <</if>> <</link>> </div> <</if>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Back to the Lagoon</div>">> <<goto "HiddenLagoon">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "QueshaFirstMeet">> <div style="background: linear-gradient(180deg, #0f2a3a 0%, #1a1a1a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #4dd0e1; border-radius: 12px; padding: 25px;"> <h1 style="color: #4dd0e1; text-align: center;">🌊 The Lagoon</h1> <p style="color: #ddd; line-height: 1.7;">You push through the last of the brush and there it is. A still glass water lagoon, cliffs all around, sunlight slicing in from above. Out past the middle of the water something blue surfaces. A girl. Then a flash of something else, fluke shaped, gone before you can be sure.</p> <p style="color: #ddd; line-height: 1.7;">She sees you. There is a moment of absolute stillness. Then she ducks under, comes back up, and her shape has changed. Mostly human now. Mostly. She drifts to the shallows with her arms folded around her chest, blushing furiously.</p> <p style="color: #4dd0e1; font-style: italic; line-height: 1.7;">"Hi. Um. Hi. I didn't hear you coming. I'm Quesha. Quesha Epo. This is. Um. This is my lagoon. I mean, not legally, I just. I come here. Please don't. Please don't tell anyone."</p> <p style="color: #ddd; line-height: 1.7;">She introduces herself again, half flustered, and settles onto a flat rock with her legs in the water. She is older than you first thought, soft around the eyes, mother shaped. The fluke is gone, hidden, but the blue hair gives her away. She asks your name.</p> <p style="color: #ddd; line-height: 1.7;">You talk. She asks careful, gentle questions. When you mention the city she lights up at the word Sunfish and tells you about the dive shop she runs at the Beach. Quiet hours, mostly. She says she would be happy if you came by sometime. The way she says it makes it sound less like a polite offer and more like she really would.</p> <p style="color: #ddd; line-height: 1.7;">You promise you will. She smiles. The whole lagoon feels warmer.</p> /* Defensive init of $metNPCs and $relationships, then record this meeting. */ <<if !$metNPCs>><<set $metNPCs = []>><</if>> <<if !$relationships>><<set $relationships = {}>><</if>> <<if !$metNPCs.includes("Quesha Epo")>><<run $metNPCs.push("Quesha Epo")>><</if>> <<if !$relationships["Quesha Epo"]>><<set $relationships["Quesha Epo"] = { level: 1, points: 25 }>><</if>> /* Set intro complete LAST so a mid-scene save and reload replays the scene. */ <<set $queshaIntroComplete = true>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Continue</div>">> <<advancetime 60>> <<goto "HiddenLagoon">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "HiddenLagoon">> /* First visit triggers the intro encounter, then redirects back here cleanly. */ <<if !$queshaIntroComplete>> <<goto "QueshaFirstMeet">> <</if>> /* Phase 7: triangulation scene fires once when 4+ glyphs collected. */ <<if !$shrineGlyphsFound>><<set $shrineGlyphsFound = []>><</if>> <<if !setup.diving.QUESTLINES_DISABLED && $shrineGlyphsFound.length >= 4 && !$shrineTriangulationDone>> <<goto "ShrineTriangulation">> <</if>> <div style="background: linear-gradient(180deg, #0f2a3a 0%, #1a1a1a 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #4dd0e1; text-align: center; text-shadow: 0 2px 8px #4dd0e144;">🌊 Hidden Lagoon</h1> <div style="padding: 20px; background: rgba(0,0,0,0.4); border-radius: 12px; border: 2px solid #4dd0e1; margin-bottom: 25px;"> <p style="color: #ddd; line-height: 1.6; margin: 0;">The lagoon is glass still. Coral grows up the cliffs in soft pink shelves. Somewhere out past the deep middle Quesha's blue hair surfaces and dips again. The whole place smells like sunlight on warm rock.</p> </div> <h2 style="color: #4dd0e1;">Activities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-bottom: 25px;"> <div style="border: 3px solid #d81b60; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #d81b60; margin: 0 0 10px 0;">💬 Talk with Quesha</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Sit at the water's edge with her.</p> <<link "<div style='background: linear-gradient(135deg, #d81b60 0%, #880e4f 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>💬 Talk to Quesha</div>">> <<set $tradingWithNPC = setup.getNPCByName("Quesha Epo")>> <<set $preNPCLocation = "HiddenLagoon">> <<goto "NPCInteraction">> <</link>> </div> <<if !setup.diving.QUESTLINES_DISABLED && $shrineTriangulationDone && !$shrineFound>> <div style="border: 3px solid #ffd700; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🌅 Return to the Shrine</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Go with Quesha to the place past the cathedral.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Go With Her</div>">> <<goto "ShrineFinal">> <</link>> </div> <</if>> </div> <h2 style="color: #4dd0e1;">Travel</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;"> <div style="border: 3px solid #2ecc71; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); display: flex; flex-direction: column;"> <h3 style="color: #2ecc71; margin: 0 0 10px 0;">🌴 Back to Jungle</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Climb back through the vines the way you came.</p> <<link "<div style='background: linear-gradient(135deg, #2ecc71 0%, #1a7943 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Travel</div>">> <<advancetime 15>> <<goto "Jungle">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "QueshaDiveShop">> <div style="background: linear-gradient(180deg, #1a1a1a 0%, #0a1a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 900px; margin: 0 auto;"> <h1 style="color: #4dd0e1; text-align: center; text-shadow: 0 2px 8px #4dd0e144;">🤿 Quesha's Dive Shop</h1> <div style="background: rgba(0,0,0,0.4); border: 2px solid #4dd0e1; border-radius: 12px; padding: 18px; margin-bottom: 20px;"> <p style="color: #ddd; line-height: 1.5; margin: 0;">A small wooden shop set just back from the sand. Wet suits hang from pegs, a wall map studded with pushpins marks dive sites, and a counter with a hand painted sign says simply "HI". The room smells like salt and warm rope.</p> </div> <<set _ack = setup.diving.physicalTraitAck()>> <<if _ack>> <div style="background: linear-gradient(135deg, #2a1830 0%, #1a0a25 100%); border: 2px solid #d81b60; border-radius: 12px; padding: 18px; margin-bottom: 20px;"> <p style="color: #ffb3d0; font-style: italic; line-height: 1.6; margin: 0;">"<<= _ack.line>>"</p> </div> <<run setup.diving.commitAck(_ack)>> <</if>> <<if !setup.diving.canDive()>> <div style="background: #2a2a2a; border: 3px solid #4dd0e1; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h3 style="color: #4dd0e1; margin: 0 0 10px 0;">📘 Learn to Swim</h3> <p style="color: #ddd; line-height: 1.5;">"Before I take you out there I want to make sure you can swim properly. It takes a full day. Five hundred for my time."</p> <<if $money >= setup.drifterDiscount(500)>> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Learn ($<<= setup.drifterDiscount(500)>>, 8 hours)</div>">> <<set $money -= setup.drifterDiscount(500)>> <<if !$skills>><<set $skills = []>><</if>> <<if !$skills.includes("Swimming") && !$skills.includes("Swimmer")>> <<run $skills.push("Swimming")>> <</if>> <<set $queshaSwimmingTaught = true>> <<advancetime 480>> <<goto "QueshaDiveShop">> <</link>> <<else>> <p style="color: #ff6b6b; margin: 8px 0 0 0;">Not enough money.</p> <</if>> </div> <<else>> <<if !setup.diving.QUESTLINES_DISABLED && !$shrineQuestAccepted>> <div style="background: rgba(216,27,96,0.1); border: 2px solid #d81b60; border-radius: 12px; padding: 18px; margin: 18px 0;"> <h3 style="color: #d81b60; margin: 0 0 10px 0;">💭 A Story Quesha Wants to Share</h3> <p style="color: #ddd; line-height: 1.6;">Quesha sets a hand on the wall map and traces a circle around the open water. "My grandmother used to tell me a story. There's supposed to be a shrine somewhere out there, carved by the people who lived here before the city. I've been looking for years. Nothing."</p> <p style="color: #ddd; line-height: 1.6;">She glances at you, hopeful. "If you happen to find anything weird down there. Carvings. Old marks. Anything that doesn't look natural. Would you bring it back?"</p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 15px;"> <<link "<div style='background: #d81b60; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept</div>">> <<set $shrineQuestAccepted = true>> <<goto "QueshaDiveShop">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Maybe later</div>">> <<goto "QueshaDiveShop">> <</link>> </div> </div> <</if>> <<if !setup.diving.QUESTLINES_DISABLED && $relationships && $relationships["Quesha Epo"] && $relationships["Quesha Epo"].level >= 2 && !$queshaTrenchPermit>> <div style="background: rgba(255,183,77,0.1); border: 2px solid #ffb74d; border-radius: 12px; padding: 18px; margin: 18px 0;"> <h3 style="color: #ffb74d; margin: 0 0 10px 0;">📜 Trench Edge Permit</h3> <p style="color: #ddd; line-height: 1.6;">"You've earned my trust out there, so I'll set you up properly. If you want to dive past the wreck, you'll need a Trench Edge permit. The trench is no joke. Fifteen hundred covers the permit and a full safety briefing. Worth every coin."</p> <<if $money >= setup.drifterDiscount(1500)>> <<link "<div style='background: linear-gradient(135deg, #ffb74d 0%, #c97e3a 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Buy Permit ($<<= setup.drifterDiscount(1500)>>, 30 min)</div>">> <<set $money -= setup.drifterDiscount(1500)>> <<set $queshaTrenchPermit = true>> <<advancetime 30>> <<goto "QueshaDiveShop">> <</link>> <<else>> <p style="color: #ff6b6b; margin: 8px 0 0 0;">Not enough money.</p> <</if>> </div> <</if>> <<if !setup.diving.QUESTLINES_DISABLED && setup.diving.canStartStage2() && !$sunfishDayAccepted>> <div style="background: linear-gradient(135deg, #2a1f08 0%, #1a1408 100%); border: 2px solid #ffd700; border-radius: 12px; padding: 18px; margin: 18px 0;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">💛 An Old Idea</h3> <p style="color: #ddd; line-height: 1.6;">She looks restless behind the counter. "Been thinking. There used to be a festival here, before the city. Sunfish Day, they called it. I think we could bring it back. The shrine deserves a real day."</p> <p style="color: #ddd; line-height: 1.6;">She pulls out a folded list. "I have an idea who could help. If you'd be willing."</p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 15px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Accept</div>">> <<set $sunfishDayAccepted = true>> <<set $sunfishDayUnlocked = true>> <<goto "QueshaDiveShop">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Not now</div>">> <<goto "QueshaDiveShop">> <</link>> </div> </div> <</if>> <<if !setup.diving.QUESTLINES_DISABLED && $sunfishDayAccepted && !setup.diving.allRecruitsDone()>> <div style="background: rgba(255,215,0,0.08); border: 2px solid #ffd700; border-radius: 12px; padding: 18px; margin: 18px 0;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🌅 Sunfish Day Recruits (<<= setup.diving.recruitsCompletedCount()>> of 3)</h3> <p style="color: #ddd; line-height: 1.5; margin: 0 0 10px 0;">"The festival needs hands. See if any of these folks will pitch in."</p> <ul style="color: #ddd; line-height: 1.6; margin: 0; padding-left: 20px;"> <li><<if $queshaRecruitState.maidCafe>><span style="color: #6dd66a;">✓ Bun Bun at the Pufferfish (food)</span><<else>>Bun Bun at the Pufferfish (food)<</if>></li> <li><<if $queshaRecruitState.techStore>><span style="color: #6dd66a;">✓ Hammerhead Tech (speakers and lights)</span><<else>>Hammerhead Tech (speakers and lights)<</if>></li> <li><<if $queshaRecruitState.docks>><span style="color: #6dd66a;">✓ The Docks (lanterns and boats)</span><<else>>The Docks (lanterns and boats)<</if>></li> </ul> </div> <</if>> <<if !setup.diving.QUESTLINES_DISABLED && $sunfishDayAccepted && setup.diving.allRecruitsDone() && $sunfishDayYear === 0>> <div style="background: rgba(255,215,0,0.08); border: 2px solid #ffd700; border-radius: 12px; padding: 18px; margin: 18px 0;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🌅 Everyone's In</h3> <p style="color: #ddd; line-height: 1.6; margin: 0;">"That's all of them. Day one hundred of the year. Meet me at the shrine then. Bring a smile."</p> </div> <</if>> <<if $sunfishDayYear > 0>> <div style="background: rgba(255,215,0,0.06); border: 1px solid #c97e3a; border-radius: 10px; padding: 14px; margin: 14px 0;"> <p style="color: #ddd; font-style: italic; line-height: 1.5; margin: 0;">Sunfish Day has been held <<= $sunfishDayYear>> time<<if $sunfishDayYear !== 1>>s<</if>> now. The next one falls on day one hundred.</p> </div> <</if>> <<set _diveMode = setup.diving.resourceMode()>> <<if _diveMode === "refuser_feline">> <<if !$queshaAckedFeline>> <div style="background: #2a2a2a; border: 3px solid #4dd0e1; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h3 style="color: #4dd0e1; margin: 0 0 12px 0;">🤿 Pick a Dive Site</h3> <div style="display: grid; grid-template-columns: 1fr; gap: 12px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #4dd0e1; color: #4dd0e1; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🌊 Try a Dive</div>">> <<goto "DiveFelineRefusal">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; border: 3px solid #4dd0e1; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #4dd0e1; font-style: italic; line-height: 1.6; margin: 0;">"Not today." <span style="color: #888; font-style: normal;">(she says it for you)</span></p> </div> <</if>> <<elseif _diveMode === "sinker">> <<if !$queshaSinkerRescued>> <div style="background: #2a2a2a; border: 3px solid #ff6b6b; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h3 style="color: #ff6b6b; margin: 0 0 12px 0;">⚠️ The Water Will Not Hold You</h3> <p style="color: #ddd; line-height: 1.6;">You can feel it already, looking at the surf. Your bones are too heavy for this. Quesha is busy at the back of the shop and has not noticed you eyeing the water.</p> <div style="display: grid; grid-template-columns: 1fr; gap: 12px; margin-top: 12px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🌊 Attempt Anyway</div>">> <<goto "DiveSinkerRescue">> <</link>> </div> </div> <<else>> <div style="background: #2a2a2a; border: 3px solid #4dd0e1; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #4dd0e1; font-style: italic; line-height: 1.6; margin: 0;">"Hon, last time was a one time deal. Come back when you're a little more buoyant."</p> </div> <</if>> <<else>> <<if setup.hasDebuff("exhaustion")>> <div style="background: rgba(255,107,107,0.1); border: 2px solid #ff6b6b; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h3 style="color: #ff6b6b; margin: 0 0 12px 0;">😴 Too Tired to Dive</h3> <p style="color: #ddd; line-height: 1.6; margin: 0;">Quesha takes one look at you and shakes her head. "Not today, hon. You're already wrung out. Sit down, drink some water, come back when you've slept."</p> </div> <<else>> <div style="background: #2a2a2a; border: 3px solid #4dd0e1; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h3 style="color: #4dd0e1; margin: 0 0 12px 0;">🤿 Pick a Dive Site</h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #4dd0e1; color: #4dd0e1; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🪸 Coral Shelf (tier 1)</div>">> <<run setup.diving.startDive("coralShelf")>> <<goto "DiveNode">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dd0e1; color: #4dd0e1; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🚢 Shallow Wreck (tier 2)</div>">> <<run setup.diving.startDive("shallowWreck")>> <<goto "DiveNode">> <</link>> <<if $queshaTrenchPermit || setup.diving.QUESTLINES_DISABLED>> <<link "<div style='background: #1a1a1a; border: 2px solid #ffb74d; color: #ffb74d; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🌑 Trench Edge (tier 3)</div>">> <<run setup.diving.startDive("trenchEdge")>> <<goto "DiveNode">> <</link>> <</if>> </div> </div> <</if>> <</if>> <</if>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffb74d; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Back to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<if setup.slime && setup.slime.isActivityBlocked("dive")>><<goto "SlimeBlocked">><</if>> <<set $lastLocation = "DiveNode">> <<set _mode = setup.diving.resourceMode()>> <<set _res = setup.diving.getCurrentResource()>> <<set _resLabel = (_mode === "aquatic") ? "Stamina" : "Breath">> <<if _res <= 0>> <<set _result = setup.diving.surface(true)>> <<goto "DiveResult">> <</if>> <<if $diveCurrentNode === null || $diveCurrentNode === undefined>> <<if $rerollNextNode>> <<if $revealedNodes && $revealedNodes.length > 0>><<run $revealedNodes.shift()>><</if>> <<set $diveCurrentNode = setup.diving.rollNode($diveCurrentSite)>> <<set $rerollNextNode = false>> <<elseif setup.diving.hasUpgrade("obsessions_blindness") && random(1, 100) <= 50>> <<if $revealedNodes && $revealedNodes.length > 0>><<run $revealedNodes.shift()>><</if>> <<set $diveCurrentNode = setup.diving.rollNode($diveCurrentSite)>> <<elseif $revealedNodes && $revealedNodes.length > 0>> <<set $diveCurrentNode = $revealedNodes.shift()>> <<else>> <<set $diveCurrentNode = setup.diving.rollNode($diveCurrentSite)>> <</if>> <</if>> <<set _node = $diveCurrentNode>> <<set _cost = setup.diving.NODE_COSTS[_node]>> <<if _node === "shrineGlyph">><<set _glyphId = setup.diving.rollGlyph()>><</if>> <<if _node === "predator">><<set _predatorId = setup.diving.rollPredator($diveCurrentSite, $diveCurrentDepth)>><</if>> <<if setup.diving.tamedPassiveIs("revealEachTurn") && (!$revealedNodes || $revealedNodes.length === 0)>><<set $revealedNodes = [setup.diving.rollNode($diveCurrentSite)]>><</if>> <div style="background: linear-gradient(180deg, #051a25 0%, #0a0a0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <div style="background: rgba(0,0,0,0.5); border: 2px solid #4dd0e1; border-radius: 8px; padding: 12px; margin-bottom: 18px; text-align: center; color: #ddd;"> <span style="color: #4dd0e1; font-weight: bold;">Site:</span> <<= setup.diving.diveSites[$diveCurrentSite].name>> · <span style="color: #4dd0e1; font-weight: bold;">Time:</span> <<= setup.bunBunTasks._formatClock($timeInMinutes)>> · <span style="color: #4dd0e1; font-weight: bold;">Depth:</span> <<= $diveCurrentDepth>> · <span style="color: #4dd0e1; font-weight: bold;"><<= _resLabel>>:</span> <<= _res>> · <span style="color: #4dd0e1; font-weight: bold;">Loot:</span> <<= $diveLoot.length>> items </div> <<if $palidEyeActive>> <div style="background: linear-gradient(135deg, #2a0a0a 0%, #1a0505 100%); border: 3px solid #ff3030; border-radius: 12px; padding: 18px; margin-bottom: 20px; box-shadow: 0 0 25px rgba(255,48,48,0.4);"> <h3 style="color: #ff3030; margin: 0 0 8px 0; text-align: center;">👁 Hunted by the Palid Eye</h3> <p style="color: #ffb3b3; font-size: 13px; line-height: 1.5; margin: 0 0 12px 0; text-align: center;">Predators chase every node. You cannot surface safely. Drop the Eye to break the curse and lose its million dollar payout.</p> <div style="text-align: center;"> <<link "<span style='background: #ff3030; color: white; padding: 8px 18px; border-radius: 6px; font-weight: bold; font-size: 13px; cursor: pointer;'>Drop the Eye</span>">> <<run setup.diving.dropPalidEye()>> <<goto "DiveNode">> <</link>> </div> </div> <</if>> <div style="background: #1a1a1a; border: 2px solid #4dd0e1; border-radius: 12px; padding: 25px; margin-bottom: 20px;"> <<switch _node>> <<case "lootSmall">> <h3 style="color: #4dd0e1;">🐚 Small Pocket</h3> <p style="color: #ddd; line-height: 1.5;">A pocket of debris caught in the reef. Sea glass winks in the shadows.</p> <<case "lootLarge">> <h3 style="color: #4dd0e1;">💎 Large Pocket</h3> <p style="color: #ddd; line-height: 1.5;">Something heavier than the rest. Worth the air to reach it.</p> <<case "creatureDen">> <h3 style="color: #4dd0e1;">🦑 Creature Den</h3> <p style="color: #ddd; line-height: 1.5;">Something with eyes is in there. Anyone can reach in and grab a specimen, but Quick Hands gets you extra.</p> <<case "current">> <h3 style="color: #4dd0e1;">🌀 Current</h3> <p style="color: #ddd; line-height: 1.5;">A cool flow pulls you sideways. You can ride it down for free, but it picks where you end up.</p> <<case "airPocket">> <h3 style="color: #4dd0e1;">💨 <<if _mode === "aquatic">>Rest Cove<<else>>Air Pocket<</if>></h3> <p style="color: #ddd; line-height: 1.5;"><<if _mode === "aquatic">>A still pocket of calm. A chance to rest your arms.<<else>>A bubble caught against the rock. You gulp a lungful.<</if>></p> <<case "wreckCabin">> <h3 style="color: #4dd0e1;">⚓ Wreck Cabin</h3> <p style="color: #ddd; line-height: 1.5;">A cabin door swings on a single hinge. Crates and bundles sit inside, stiff with salt and time.</p> <<case "treasureTrove">> <h3 style="color: #ffd700;">👑 Treasure Trove</h3> <p style="color: #ddd; line-height: 1.5;">A heavy cache wedged under collapsed beams. Whoever stashed it never came back. You can carry a lot out of here, if you have the air.</p> <<case "predator">> <h3 style="color: #ff6b6b;"><<= (_predatorId && setup.diving.PREDATOR_DEFS[_predatorId]) ? setup.diving.PREDATOR_DEFS[_predatorId].name : "Predator">></h3> <p style="color: #ddd; line-height: 1.5;">Something big has noticed you. Slip past, hide, or stand and fight.</p> <<case "shrineGlyph">> <h3 style="color: #d81b60;">✨ Glyph</h3> <p style="color: #ddd; line-height: 1.5;">A carved mark on the stone, half eaten by coral but still unmistakable. Not natural. This is one of the things Quesha asked about.</p> <<if _glyphId>> <p style="color: #ffb3d0; font-style: italic; line-height: 1.5;">"<<= setup.diving.GLYPH_LORE[_glyphId]>>"</p> <</if>> <</switch>> <div style="margin-top: 18px; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px;"> /* Per-node primary actions. Phase 9b adds 2 alternates per loot-ish node type alongside the default Investigate. Each alternate has its own resource cost, optional stat check, and loot logic. */ <<set _actionLabel = (_node === "current") ? "Drift With It (-0 " + _resLabel + ", +1 Depth)" : "Investigate (-" + _cost + " " + _resLabel + ")">> <<link "<div style='background: #1a1a1a; border: 2px solid #4dd0e1; color: #4dd0e1; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'><<= _actionLabel>></div>">> <<if _node === "current">> /* Drift With It: free, just advances depth. The current pulled you sideways/down before you could resist. */ <<set $diveCurrentDepth += 1>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <<else>> <<set _failed = setup.diving.applyResourceCost(_cost)>> <<if _node === "airPocket">> <<if _mode === "aquatic">><<set $diveStamina += 10>><<else>><<set $diveBreath += 10>><</if>> <<elseif _node === "creatureDen">> /* Always drop a specimen via the rarity-weighted helper. Quick Hands no longer required (gives a bonus loot count instead). */ <<set _cdCount = setup.diving.rollLootItemCount(_node, $diveCurrentDepth)>> <<if $skills && $skills.includes("Quick Hands")>><<set _cdCount += 1>><</if>> <<for _cdI = 0; _cdI < _cdCount; _cdI++>> <<set _cdSpec = setup.diving.rollSpecimen($diveCurrentSite)>> <<if _cdSpec>><<run $diveLoot.push(_cdSpec)>><</if>> <</for>> <<elseif _node === "predator">> /* Always slip past safely. Higher dex/str (and Athletic Build) grants a trophy on top, pulled from rollTrophy which picks a site-appropriate one. Struggle-fire and the Palid Eye curse both make the bonus harder. */ <<set _prRoll = ($stats.dexterity || 0) + ($stats.strength || 0)/2 + random(1, 20)>> <<if $physicalTraits && $physicalTraits.includes("Athletic Build")>><<set _prRoll += 5>><</if>> <<if _mode === "struggle_fire">><<set _prRoll -= 5>><</if>> <<if $palidEyeActive>><<set _prRoll -= 10>><</if>> <<if _prRoll >= 40>> <<set _prTrophy = setup.diving.rollTrophy($diveCurrentSite, null)>> <<if _prTrophy>><<run $diveLoot.push(_prTrophy)>><</if>> <</if>> <<elseif _node === "shrineGlyph">> <<if !$shrineGlyphsFound>><<set $shrineGlyphsFound = []>><</if>> <<if _glyphId && $shrineGlyphsFound.indexOf(_glyphId) === -1>> <<run $shrineGlyphsFound.push(_glyphId)>> <</if>> <<else>> /* Generic loot nodes (lootSmall, lootLarge, wreckCabin, treasureTrove) roll multiple items based on depth via the phase-3 rollLootItemCount helper. */ <<set _lootCount = setup.diving.rollLootItemCount(_node, $diveCurrentDepth)>> <<for _lootI = 0; _lootI < _lootCount; _lootI++>> <<set _item = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _item>><<run $diveLoot.push(_item)>><</if>> <</for>> <<if _node === "treasureTrove" && $diveCurrentDepth >= 8 && random(1, 100) <= 15>> <<run setup.diving.grantDiveTrait()>> <</if>> <</if>> /* After ANY loot-ish node, roll for in-dive consumable and upgrade drops. The helpers themselves check the node type and rarity for chance + return null when nothing drops. */ <<if ["lootSmall","lootLarge","wreckCabin","creatureDen","predator","treasureTrove"].indexOf(_node) !== -1>> <<set _conDrop = setup.diving.rollConsumableDrop(_node, $diveCurrentSite)>> <<if _conDrop && setup.diving.consumableSlotsFree() > 0>> <<run setup.diving.addConsumable(_conDrop)>> <</if>> <<set _upDrop = setup.diving.rollUpgradeDrop(_node, $diveCurrentSite)>> <<if _upDrop>> <<run setup.diving.addUpgrade(_upDrop)>> <</if>> <</if>> <<if _failed>> <<set _result = setup.diving.surface(true)>> <<goto "DiveResult">> <<else>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</if>> <</if>> <</link>> /* Per-node alternate actions (Phase 9b). Each shows up alongside the Investigate button when the current node supports it. */ <<if _node === "lootSmall">> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; color: #51cf66; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Quick Grab (-3)</div>">> <<set _failed = setup.diving.applyResourceCost(3)>> <<set _qg = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _qg>><<run $diveLoot.push(_qg)>><</if>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #a855f7; color: #a855f7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Careful Search (-10)</div>">> <<set _failed = setup.diving.applyResourceCost(10)>> <<set _csCount = setup.diving.rollLootItemCount(_node, $diveCurrentDepth) + 1>> <<for _csI = 0; _csI < _csCount; _csI++>> <<set _csItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _csItem>><<run $diveLoot.push(_csItem)>><</if>> <</for>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<elseif _node === "lootLarge">> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; color: #ff6b6b; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>💪 Pry Open (-10)</div>">> <<set _failed = setup.diving.applyResourceCost(10)>> <<set _check = setup.diving.statCheck("strength", 25)>> <<set _poItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _poItem>><<run $diveLoot.push(_poItem)>><</if>> <<if _check.pass>> <<set _bonus = setup.diving.rollLootItem("wreckCabin", $diveCurrentSite, $diveCurrentDepth)>> <<if _bonus>><<run $diveLoot.push(_bonus)>><</if>> <</if>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #888; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Skip (-0)</div>">> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</link>> <<elseif _node === "wreckCabin">> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; color: #ff6b6b; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>💪 Force Door (-15)</div>">> <<set _failed = setup.diving.applyResourceCost(15)>> <<set _check = setup.diving.statCheck("strength", 30)>> <<set _fdItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _fdItem>><<run $diveLoot.push(_fdItem)>><</if>> <<if _check.pass>> <<set _fdBonus = setup.diving.rollLootItem("treasureTrove", $diveCurrentSite, $diveCurrentDepth)>> <<if _fdBonus>><<run $diveLoot.push(_fdBonus)>><</if>> <</if>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🤫 Quiet Entry (-5)</div>">> <<set _failed = setup.diving.applyResourceCost(5)>> <<set _check = setup.diving.statCheck("dexterity", 20)>> <<set _qeItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> /* Quiet Entry rerolls if the item is trash, on success. */ <<if _check.pass && _qeItem && _qeItem.rarity === "trash">> <<set _qeItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <</if>> <<if _qeItem>><<run $diveLoot.push(_qeItem)>><</if>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<elseif _node === "creatureDen">> <<link "<div style='background: #1a1a1a; border: 2px solid #ff69b4; color: #ff69b4; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>💖 Befriend (-8)</div>">> <<set _failed = setup.diving.applyResourceCost(8)>> <<set _check = setup.diving.statCheck("charisma", 30)>> <<set _bfSpec = setup.diving.rollSpecimen($diveCurrentSite)>> <<if _bfSpec>><<run $diveLoot.push(_bfSpec)>><</if>> <<if _check.pass && !_failed>> <<set $pendingTameCreature = setup.diving.rollTameable($diveCurrentSite)>> <<goto "DiveTame">> <<elseif _failed>> <<set _result = setup.diving.surface(true)>><<goto "DiveResult">> <<else>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</if>> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🤫 Sneak Past (-3)</div>">> <<set _failed = setup.diving.applyResourceCost(3)>> <<set _check = setup.diving.statCheck("dexterity", 25)>> <<if _check.pass>> <<set _spSpec = setup.diving.rollSpecimen($diveCurrentSite)>> <<if _spSpec>><<run $diveLoot.push(_spSpec)>><</if>> <</if>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<elseif _node === "predator">> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; color: #ff6b6b; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>⚔️ Fight</div>">> <<run setup.diving.startCombat(_predatorId)>> <<goto "DiveCombat">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dabf7; color: #4dabf7; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🌑 Hide (-5)</div>">> <<set _failed = setup.diving.applyResourceCost(5)>> <<set _check = setup.diving.statCheck("dexterity", 25)>> /* Hide never gives loot but is much cheaper and safer. Failure just means you used 5 breath for nothing. */ <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<elseif _node === "treasureTrove">> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; color: #51cf66; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>⚡ Quick Steal (-10)</div>">> <<set _failed = setup.diving.applyResourceCost(10)>> <<set _qsItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _qsItem>><<run $diveLoot.push(_qsItem)>><</if>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #ffd700; color: #ffd700; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>👑 Detailed Plunder (-25)</div>">> <<set _failed = setup.diving.applyResourceCost(25)>> <<set _dpCount = setup.diving.rollLootItemCount(_node, $diveCurrentDepth) + 2>> <<for _dpI = 0; _dpI < _dpCount; _dpI++>> <<set _dpItem = setup.diving.rollLootItem(_node, $diveCurrentSite, $diveCurrentDepth)>> <<if _dpItem>><<run $diveLoot.push(_dpItem)>><</if>> <</for>> <<if _failed>><<set _result = setup.diving.surface(true)>><<goto "DiveResult">><<else>><<set $diveCurrentNode = null>><<goto "DiveNode">><</if>> <</link>> <</if>> /* Contextual trait ability buttons — fire inline if the current node matches the ability's contextNodes list and charges remain. */ <<set _ctxAbs = setup.diving.getTraitAbilities().filter(function(a){ if (!a.contextNodes || a.contextNodes.length === 0) return false; if (a.contextNodes.indexOf(_node) === -1) return false; return setup.diving.getTraitAbilityCharges(a.traitName) > 0; })>> <<for _ctxI = 0; _ctxI < _ctxAbs.length; _ctxI++>> <<set _ctxAb = _ctxAbs[_ctxI]>> <<capture _ctxAb>> <<link "<div style='background: #1a1a1a; border: 2px solid #ffd700; color: #ffd700; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>✨ <<= _ctxAb.abilityName>></div>">> <<run setup.diving.useTraitAbility(_ctxAb.traitName)>> <<goto "DiveNode">> <</link>> <</capture>> <</for>> /* Descend deeper: fixed 10 cost, increments depth. */ <<link "<div style='background: #1a1a1a; border: 2px solid #ffb74d; color: #ffb74d; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Descend Deeper (-10)</div>">> <<set _failed = setup.diving.applyResourceCost(10)>> <<set $diveCurrentDepth += 1>> <<if _failed>> <<set _result = setup.diving.surface(true)>> <<goto "DiveResult">> <<else>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</if>> <</link>> /* Safe surface — locked out while Palid Eye is active. */ <<if $palidEyeActive>> <div style="background: #1a0505; border: 2px solid #ff3030; color: #ff3030; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; opacity: 0.8;">Cannot Surface · Hunted</div> <<else>> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; color: #51cf66; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Surface</div>">> <<set _result = setup.diving.surface(false)>> <<goto "DiveResult">> <</link>> <</if>> </div> <!-- Universal actions (Phase 9b): available on every node --> <div style="margin-top: 12px; padding-top: 12px; border-top: 1px dashed #333; display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px;"> <<if setup.diving.catchBreathRemaining() > 0>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dd0e1; color: #4dd0e1; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px;'>💨 Catch Your Breath (<<= setup.diving.catchBreathRemaining()>> left)</div>">> <<set $catchBreathUses = ($catchBreathUses || 0) + 1>> <<if _mode === "aquatic">> <<set _maxS = setup.diving.calculateMaxStamina()>> <<set $diveStamina = Math.min(($diveStamina || 0) + 15, _maxS)>> <<else>> <<set _maxB = setup.diving.calculateMaxBreath()>> <<set $diveBreath = Math.min(($diveBreath || 0) + 15, _maxB)>> <</if>> <<goto "DiveNode">> <</link>> <<else>> <div style="background: #1a1a1a; border: 2px solid #555; color: #777; padding: 8px; border-radius: 6px; text-align: center; font-size: 13px;">💨 Out of Breath (0 left)</div> <</if>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dd0e1; color: #4dd0e1; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px;'>👁 Look Around (-2)</div>">> <<run setup.diving.applyResourceCost(2)>> <<set $revealedNodes = [setup.diving.rollNode($diveCurrentSite)]>> <<goto "DiveNode">> <</link>> <<if !$diveRestUsed>> <<link "<div style='background: #1a1a1a; border: 2px solid #51cf66; color: #51cf66; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px;'>😴 Rest (+40, 1h)</div>">> <<set $diveRestUsed = true>> <<if _mode === "aquatic">> <<set _maxS = setup.diving.calculateMaxStamina()>> <<set $diveStamina = Math.min(($diveStamina || 0) + 40, _maxS)>> <<else>> <<set _maxB = setup.diving.calculateMaxBreath()>> <<set $diveBreath = Math.min(($diveBreath || 0) + 40, _maxB)>> <</if>> <<advancetime 60>> <<goto "DiveNode">> <</link>> <<else>> <div style="background: #1a1a1a; border: 2px solid #555; color: #777; padding: 8px; border-radius: 6px; text-align: center; font-size: 13px;">😴 Already Rested</div> <</if>> </div> <!-- Revealed node previews (set by Look Around, Solar Flare, Divine Light) --> <<if $revealedNodes && $revealedNodes.length > 0 && !setup.diving.hasUpgrade("obsessions_blindness")>> <div style="margin-top: 10px; padding: 8px 12px; background: rgba(77,208,225,0.08); border-left: 3px solid #4dd0e1; border-radius: 4px;"> <div style="color: #4dd0e1; font-size: 12px; font-weight: bold; margin-bottom: 4px;">Upcoming nodes:</div> <div style="color: #ddd; font-size: 13px;"><<= setup.diving.formatNodeList($revealedNodes)>></div> </div> <</if>> </div> <!-- Consumables panel (3 slots) --> <div style="background: #1a1a1a; border: 2px solid #4dabf7; border-radius: 12px; padding: 18px; margin-bottom: 16px;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">🎒 Consumables (<<= ($diveConsumables ? $diveConsumables.length : 0)>>/3)</h3> <<if !$diveConsumables || $diveConsumables.length === 0>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 0;">No consumables. Loot nodes sometimes drop them.</p> <<else>> <div style="display: grid; grid-template-columns: 1fr; gap: 8px;"> <<for _conI = 0; _conI < $diveConsumables.length; _conI++>> <<set _conItem = $diveConsumables[_conI]>> <<set _conIndex = _conI>> <<capture _conIndex, _conItem>> <div style="background: #0d0d0d; border: 1px solid #4dabf7; border-radius: 6px; padding: 10px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;"> <div style="flex: 1; min-width: 200px;"> <div style="color: #4dabf7; font-weight: bold; font-size: 14px;"><<= _conItem.name>></div> <div style="color: #aaa; font-size: 12px; line-height: 1.4;"><<= _conItem.description || "">></div> </div> <<link "<span style='background: #4dabf7; color: #0d0d0d; padding: 6px 14px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Use</span>">> <<run setup.diving.useConsumable(_conIndex)>> <<goto "DiveNode">> <</link>> </div> <</capture>> <</for>> </div> <</if>> </div> <!-- Trait Abilities panel (per-dive charges) --> <<set _abList = setup.diving.getTraitAbilities()>> <<if _abList.length > 0>> <div style="background: #1a1a1a; border: 2px solid #ffd700; border-radius: 12px; padding: 18px; margin-bottom: 16px;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🌟 Trait Abilities</h3> <div style="display: grid; grid-template-columns: 1fr; gap: 8px;"> <<for _abI = 0; _abI < _abList.length; _abI++>> <<set _ab = _abList[_abI]>> <<set _abCharges = setup.diving.getTraitAbilityCharges(_ab.traitName)>> <<capture _ab, _abCharges>> <<set _abColor = _abCharges > 0 ? "#ffd700" : "#666">> <div style="background: #0d0d0d; border: 1px solid <<= _abColor>>; border-radius: 6px; padding: 10px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;"> <div style="flex: 1; min-width: 220px;"> <div style="color: <<= _abColor>>; font-weight: bold; font-size: 14px;"><<= _ab.abilityName>> <span style="font-size: 11px; color: #aaa;">(<<= _ab.traitName>>)</span></div> <div style="color: #aaa; font-size: 12px; line-height: 1.4;"><<= _ab.description>></div> </div> <div style="display: flex; align-items: center; gap: 8px;"> <span style="color: <<= _abColor>>; font-weight: bold; font-size: 12px;"><<= _abCharges>> / <<= _ab.maxCharges>></span> <<if _abCharges > 0>> <<link "<span style='background: #ffd700; color: #1a1a1a; padding: 6px 14px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Use</span>">> <<run setup.diving.useTraitAbility(_ab.traitName)>> <<goto "DiveNode">> <</link>> <<else>> <span style="background: #333; color: #888; padding: 6px 14px; border-radius: 5px; font-weight: bold; font-size: 12px; font-style: italic;">Spent</span> <</if>> </div> </div> <</capture>> <</for>> </div> </div> <</if>> <!-- Tamed Companion panel --> <<set _comp = setup.diving.getTamedCreature()>> <<if _comp>> <div style="background: #1a1a1a; border: 2px solid #ff69b4; border-radius: 12px; padding: 18px; margin-bottom: 16px;"> <h3 style="color: #ff69b4; margin: 0 0 8px 0;">🐠 Companion: <<= _comp.name>></h3> <div style="color: #aaa; font-size: 12px; margin-bottom: 8px;"><strong style="color:#4dabf7;">Passive:</strong> <<= _comp.passiveDesc>></div> <div style="background: #0d0d0d; border: 1px solid #ff69b4; border-radius: 6px; padding: 10px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;"> <div style="flex: 1; min-width: 200px;"> <div style="color: #ffd700; font-weight: bold; font-size: 14px;"><<= _comp.activeName>></div> <div style="color: #aaa; font-size: 12px; line-height: 1.4;"><<= _comp.activeDesc>></div> </div> <div style="display: flex; align-items: center; gap: 8px;"> <span style="color: #ffd700; font-weight: bold; font-size: 12px;"><<= $tamedCreatureCharges || 0>> / <<= _comp.charges>></span> <<if ($tamedCreatureCharges || 0) > 0>> <<link "<span style='background: #ff69b4; color: #1a1a1a; padding: 6px 14px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Use</span>">> <<run setup.diving.useTamedActive()>> <<goto "DiveNode">> <</link>> <<else>> <span style="background: #333; color: #888; padding: 6px 14px; border-radius: 5px; font-weight: bold; font-size: 12px; font-style: italic;">Spent</span> <</if>> </div> </div> </div> <</if>> <!-- Upgrades panel (passive, last the dive) --> <div style="background: #1a1a1a; border: 2px solid #a855f7; border-radius: 12px; padding: 18px; margin-bottom: 16px;"> <h3 style="color: #a855f7; margin: 0 0 10px 0;">✨ Active Upgrades (<<= ($diveUpgrades ? $diveUpgrades.length : 0)>>)</h3> <<if !$diveUpgrades || $diveUpgrades.length === 0>> <p style="color: #888; font-style: italic; font-size: 13px; margin: 0;">No upgrades active. They drop rarely from loot nodes and vanish when you surface.</p> <<else>> <div style="display: grid; grid-template-columns: 1fr; gap: 8px;"> <<for _upI = 0; _upI < $diveUpgrades.length; _upI++>> <<set _upItem = $diveUpgrades[_upI]>> <<set _upColor = _upItem.cursed ? "#ff3030" : (_upItem.supernatural ? "#bd5fff" : "#a855f7")>> <div style="background: #0d0d0d; border: 1px solid <<= _upColor>>; border-radius: 6px; padding: 10px;"> <div style="color: <<= _upColor>>; font-weight: bold; font-size: 14px;"><<= _upItem.name>><<if _upItem.cursed>> <span style="font-size: 11px; color: #ff8080;">(cursed)</span><<elseif _upItem.supernatural>> <span style="font-size: 11px; color: #d99fff;">(supernatural)</span><</if>></div> <div style="color: #aaa; font-size: 12px; line-height: 1.4;"><<= _upItem.description || "">></div> </div> <</for>> </div> <</if>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DiveResult">> <<set _result = $diveLastResult>> <<if !$pendingLoot>><<set $pendingLoot = []>><</if>> <<if !$sunfishGoldRevealed>><<set $sunfishGoldRevealed = []>><</if>> <div style="background: linear-gradient(180deg, #1a1a1a 0%, #0a1a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 900px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #4dd0e1; border-radius: 12px; padding: 25px;"> <!-- Header (wiped / forced / safe) --> <<if _result && _result.wiped>> <h2 style="color: #ff3030; text-align: center; font-size: 28px; margin: 0 0 12px 0; text-shadow: 0 0 20px rgba(255,48,48,0.5);">💀 Devoured by the Deep</h2> <p style="color: #ffb3b3; line-height: 1.6;">The Palid Eye dragged everything down with it. You surface alone, lungs burning, hands empty. Whatever you found is somewhere far below now, gone with the curse that took it.</p> <p style="color: #ffb3b3; line-height: 1.6; font-style: italic;">Quesha pulls you onto the boat without saying a word. She has seen this look before.</p> <<elseif _result && _result.forced>> <h2 style="color: #ff6b6b; text-align: center; font-size: 28px; margin: 0 0 12px 0;">💢 Forced Surface</h2> <<if setup.diving.resourceMode() === "aquatic">> <p style="color: #ddd; line-height: 1.6;">Your arms gave out. You drifted back to the surface, tired but unharmed. You kept everything.</p> <<else>> <p style="color: #ddd; line-height: 1.6;">Your air ran out. You blacked out for the last few meters and surfaced gasping. Half your finds slipped from your grip on the way up.</p> <</if>> <<else>> <h2 style="color: #51cf66; text-align: center; font-size: 28px; margin: 0 0 12px 0;">✓ Surfaced Safe</h2> <p style="color: #ddd; line-height: 1.6;">You break the surface with everything you found. Quesha helps you onto the boat and starts sorting through the haul.</p> <</if>> <<if setup.diving.hasPalidTouch && setup.diving.hasPalidTouch()>> <p style="color: #d9a0a0; line-height: 1.6; font-style: italic; text-align: center; font-size: 13px; margin-top: 8px;">💀 Palid Touch lingers. Your stats are weakened until it fades.</p> <</if>> <<if setup.hasDebuff && setup.hasDebuff("dive_injury")>> <p style="color: #ffb088; line-height: 1.6; font-style: italic; text-align: center; font-size: 13px; margin-top: 8px;">🩹 Dive Injury. A predator wounded you. Reduced breath and stamina until it heals.</p> <</if>> <<if $diveNewTraits && $diveNewTraits.length > 0>> <div style="background: rgba(216,27,96,0.12); border: 2px solid #d81b60; border-radius: 8px; padding: 12px; margin-top: 14px;"> <p style="color: #ffb3d0; font-style: italic; line-height: 1.6; margin: 0;">Quesha looks you over as you climb aboard, head tilting. "The water has been working on you. You carry yourself different now. <<= $diveNewTraits.join(" and ")>>, if I had to put a word to it."</p> </div> <<set $diveNewTraits = []>> <</if>> <!-- Sunfish Gold reveal section --> <<if $sunfishGoldRevealed && $sunfishGoldRevealed.length > 0>> <div style="background: linear-gradient(135deg, #2a2010 0%, #1a1408 100%); border: 2px solid #ffd700; border-radius: 10px; padding: 16px; margin: 20px 0;"> <h3 style="color: #ffd700; margin: 0 0 10px 0; text-align: center; text-shadow: 0 0 12px rgba(255,215,0,0.4);">🟡 Sunfish Gold</h3> <p style="color: #ddd; text-align: center; font-size: 13px; margin: 0 0 12px 0;">The sealed bags split open in the daylight.</p> <div style="display: grid; grid-template-columns: 1fr; gap: 8px;"> <<for _sgI = 0; _sgI < $sunfishGoldRevealed.length; _sgI++>> <<set _sgVal = $sunfishGoldRevealed[_sgI]>> <<set _sgIndex = _sgI>> <<capture _sgIndex, _sgVal>> <<set _sgTier = _sgVal < 1000 ? "Fool's Gold" : _sgVal < 50000 ? "Modest Haul" : _sgVal < 250000 ? "Rich Strike" : _sgVal < 750000 ? "True Sunfish Gold" : "Mythic Sunfish Gold">> <<set _sgColor = _sgVal < 1000 ? "#8b7d3a" : _sgVal < 50000 ? "#d9b94e" : _sgVal < 250000 ? "#ffd700" : _sgVal < 750000 ? "#fff066" : "#fffa9c">> <div style="background: #0d0a04; border: 1px solid <<= _sgColor>>; border-radius: 6px; padding: 10px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;"> <div> <div style="color: <<= _sgColor>>; font-weight: bold; font-size: 14px;"><<= _sgTier>></div> <div style="color: #fff; font-weight: bold; font-size: 18px;">$<<= _sgVal.toLocaleString()>></div> </div> <<link "<span style='background: <<= _sgColor>>; color: #1a1a1a; padding: 8px 16px; border-radius: 5px; font-weight: bold; font-size: 13px; cursor: pointer;'>Claim</span>">> <<run setup.diving.claimSunfishGoldAt(_sgIndex)>> <<goto "DiveResult">> <</link>> </div> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 12px;"> <<link "<span style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 8px 18px; border-radius: 5px; font-weight: bold; font-size: 13px; cursor: pointer;'>Claim All</span>">> <<run setup.diving.claimAllSunfishGold()>> <<goto "DiveResult">> <</link>> </div> </div> <</if>> <!-- Pending loot choice section --> <<if $pendingLoot && $pendingLoot.length > 0>> <div style="background: #1a1a1a; border: 2px solid #4dabf7; border-radius: 10px; padding: 16px; margin: 20px 0;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">📦 Your Haul (<<= $pendingLoot.length>> items)</h3> <p style="color: #aaa; font-size: 13px; margin: 0 0 12px 0;">Sell for cash, salvage for scrap, or keep as crafting material. Trash items can only be sold or salvaged.</p> <!-- Bulk action row --> <div style="display: flex; flex-wrap: wrap; gap: 6px; justify-content: center; margin-bottom: 14px;"> <<link "<span style='background: #51cf66; color: #1a1a1a; padding: 6px 12px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Sell All</span>">> <<run setup.diving.sellAllPending()>> <<goto "DiveResult">> <</link>> <<link "<span style='background: #ffb74d; color: #1a1a1a; padding: 6px 12px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Salvage All</span>">> <<run setup.diving.salvageAllPending()>> <<goto "DiveResult">> <</link>> <<link "<span style='background: #4dabf7; color: #1a1a1a; padding: 6px 12px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Keep All</span>">> <<run setup.diving.keepAllPending()>> <<goto "DiveResult">> <</link>> <<link "<span style='background: #555; color: #ddd; padding: 6px 12px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Sell Trash Only</span>">> <<run setup.diving.sellTrashOnly()>> <<goto "DiveResult">> <</link>> </div> <!-- Per-item list --> <div style="display: grid; grid-template-columns: 1fr; gap: 6px;"> <<for _plI = 0; _plI < $pendingLoot.length; _plI++>> <<set _plItem = $pendingLoot[_plI]>> <<set _plIndex = _plI>> <<set _plColor = setup.diving.rarityColor(_plItem.rarity || "common")>> <<set _plRarLabel = setup.diving.rarityLabel(_plItem.rarity || "common")>> <<capture _plIndex, _plItem, _plColor, _plRarLabel>> <div style="background: #0d0d0d; border-left: 4px solid <<= _plColor>>; border-radius: 4px; padding: 8px 12px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;"> <div style="flex: 1; min-width: 180px;"> <div style="color: <<= _plColor>>; font-weight: bold; font-size: 14px;"><<= _plItem.name>></div> <div style="color: #888; font-size: 11px;"><<= _plRarLabel>> · $<<= ((typeof _plItem.value === "number") ? _plItem.value : 0).toLocaleString()>></div> </div> <div style="display: flex; flex-wrap: wrap; gap: 4px;"> <<if _plItem.id === "mystery_crate">> <<link "<span style='background: #51cf66; color: #1a1a1a; padding: 5px 10px; border-radius: 4px; font-weight: bold; font-size: 11px; cursor: pointer;'>Sell Sealed</span>">> <<run setup.diving.sellPendingItem(_plIndex)>> <<goto "DiveResult">> <</link>> <<link "<span style='background: #a855f7; color: #fff; padding: 5px 10px; border-radius: 4px; font-weight: bold; font-size: 11px; cursor: pointer;'>Open</span>">> <<run setup.diving.openMysteryCrateAt(_plIndex)>> <<goto "DiveResult">> <</link>> <<else>> <<link "<span style='background: #51cf66; color: #1a1a1a; padding: 5px 10px; border-radius: 4px; font-weight: bold; font-size: 11px; cursor: pointer;'>Sell</span>">> <<run setup.diving.sellPendingItem(_plIndex)>> <<goto "DiveResult">> <</link>> <<link "<span style='background: #ffb74d; color: #1a1a1a; padding: 5px 10px; border-radius: 4px; font-weight: bold; font-size: 11px; cursor: pointer;'>Salvage</span>">> <<run setup.diving.salvageItem(_plIndex)>> <<goto "DiveResult">> <</link>> <<if _plItem.rarity !== "trash">> <<link "<span style='background: #4dabf7; color: #1a1a1a; padding: 5px 10px; border-radius: 4px; font-weight: bold; font-size: 11px; cursor: pointer;'>Keep</span>">> <<run setup.diving.keepItem(_plIndex)>> <<goto "DiveResult">> <</link>> <</if>> <</if>> </div> </div> <</capture>> <</for>> </div> </div> <</if>> <!-- Running totals --> <div style="margin-top: 18px; padding: 14px; background: #1a1a1a; border-radius: 6px; text-align: center;"> <p style="color: #4dd0e1; margin: 0; font-size: 14px;"> Wallet: $<<= ($money || 0).toLocaleString()>> · Scrap: <<= ($diveScrap || 0)>> · Materials: <<= ($diveMaterials ? Object.keys($diveMaterials).length : 0)>> kinds </p> </div> <<advancetime 60>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Back to the Shop</div>">> <<if $pendingLoot && $pendingLoot.length > 0>><<run setup.diving.sellAllPending()>><</if>> <<if $sunfishGoldRevealed && $sunfishGoldRevealed.length > 0>><<run setup.diving.claimAllSunfishGold()>><</if>> <<goto "QueshaDiveShop">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DiveFelineRefusal">> <div style="background: linear-gradient(180deg, #1a1a1a 0%, #0a1a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #4dd0e1; border-radius: 12px; padding: 25px;"> <h2 style="color: #4dd0e1; text-align: center; font-size: 28px; margin: 0 0 12px 0;">🐾 Not Today</h2> <p style="color: #ddd; line-height: 1.7;">You step toward the shoreline and your body answers before your mind does. Ears flatten. Your tail lashes once, twice, then tucks tight against your spine. The waves lap the sand a finger's width from your toes and your whole skin says no.</p> <p style="color: #ddd; line-height: 1.7;">You walk back up the sand before you can stop yourself. The wet suit on the peg suddenly looks ridiculous. The dive map studded with pins looks ridiculous. The whole idea of submerging yourself in cold salt water looks ridiculous.</p> <p style="color: #ddd; line-height: 1.7;">Quesha is already coming around the counter, wiping her hands on a towel. She takes one look at your stance and her face softens into the most patient apology you have ever seen.</p> <p style="color: #4dd0e1; font-style: italic; line-height: 1.7;">"Oh, sorry, hon, I should have asked. Cats and water, right? It's okay. The reef will still be here when you switch back."</p> <p style="color: #ddd; line-height: 1.7;">She does not push. She does not laugh. She just gives you a small smile and goes back to whatever she was doing behind the counter, leaving you the dignity of finding your own way out.</p> <<set $queshaAckedFeline = true>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Continue</div>">> <<goto "QueshaDiveShop">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ShrineTriangulation">> <div style="background: linear-gradient(180deg, #0f2a3a 0%, #1a0a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.55); border: 2px solid #d81b60; border-radius: 12px; padding: 25px;"> <h1 style="color: #d81b60; text-align: center; text-shadow: 0 2px 8px #d81b6044;">🗺️ The Map Comes Together</h1> <p style="color: #ddd; line-height: 1.7;">You spread the glyph rubbings out across a flat rock at the lagoon's edge. Quesha leans over them, hair dripping onto the paper. The four marks line up. Then another. Her finger traces a slow spiral inward.</p> <p style="color: #ffb3d0; font-style: italic; line-height: 1.7;">"Oh. Oh, it's past the cathedral. It's been past the cathedral the whole time."</p> <p style="color: #ddd; line-height: 1.7;">She looks at you. Eyes shining. "Will you come with me?"</p> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 25px;"> <<link "<div style='background: #d81b60; color: white; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Of course</div>">> <<set $shrineTriangulationDone = true>> <<goto "ShrineFinal">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Not yet</div>">> <<set $shrineTriangulationDone = true>> <<goto "HiddenLagoon">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "ShrineFinal">> <div style="background: linear-gradient(180deg, #051a25 0%, #1a0a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.55); border: 3px solid #ffd700; border-radius: 12px; padding: 25px;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 2px 8px #ffd70044;">🌅 The Shrine</h1> <p style="color: #ddd; line-height: 1.7;">Down past the cathedral the water gets quiet. Past the noise of the reef, past the wreck lights, past anything you've seen in a dive log. The shrine is built into a wall of pale stone, half buried in coral, and the carving on the front is unmistakably a sunfish. Bigger than any sunfish you've ever seen. Older than the city.</p> <p style="color: #ddd; line-height: 1.7;">Quesha hangs in the water beside you. She doesn't speak. After a long moment she touches the carving very gently with her palm. The water seems to go warmer.</p> <p style="color: #ffb3d0; font-style: italic; line-height: 1.7;">"Thank you. For believing me."</p> <<set $shrineFound = true>> <<set $shrinePilgrim = true>> <<run setup.addRelationshipPoints("Quesha Epo", 100)>> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Surface (120 min)</div>">> <<advancetime 120>> <<goto "Beach">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SunfishShrine">> <<if !setup.diving.QUESTLINES_DISABLED && setup.diving.isFestivalDay() && setup.diving.allRecruitsDone() && $sunfishDayLastFiredDay !== $dayNumber>> <<goto "SunfishDayFestival">> <</if>> <div style="background: linear-gradient(180deg, #1a0a25 0%, #0a1a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 2px 8px #ffd70044;">🌅 Sunfish Shrine</h1> <div style="background: rgba(0,0,0,0.5); border: 2px solid #ffd700; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #ddd; line-height: 1.7; margin: 0;">The shrine sits in a pool of still light at the edge of the deep. Pale stone, coral grown in, the carved sunfish watching anyone who comes down. The water here is always a little warmer than it should be.</p> </div> <<if $shrineLastVisitDay === $dayNumber>> <div style="background: #2a2a2a; border: 2px solid #555; border-radius: 12px; padding: 18px; margin-bottom: 20px; text-align: center;"> <p style="color: #aaa; font-style: italic; margin: 0;">You've already paid your respects today. The shrine's warmth lingers.</p> </div> <<else>> <div style="background: #2a2a2a; border: 3px solid #ffd700; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">🙏 Pay Respects</h3> <p style="color: #ddd; line-height: 1.6;">Settle in front of the carving. Quiet your breath. Listen.</p> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Pay Respects (15 min)</div>">> <<set $shrineLastVisitDay = $dayNumber>> <<set _remaining = 1440 - $timeInMinutes>> <<if _remaining < 60>><<set _remaining = 60>><</if>> <<run setup.addBuff("shrine_pilgrim", _remaining)>> <<advancetime 15>> <<goto "SunfishShrine">> <</link>> </div> <</if>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #ffb74d; color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Back to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1408 0%, #0a0a1a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 2px 8px #ffd70044;">🌅 Bun Bun and the Festival</h1> <div style="background: rgba(0,0,0,0.5); border: 2px solid #ffd700; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">You catch Bun Bun in the kitchen between orders. Her ears twitch when you mention Sunfish Day. She listens with the soft attention she gives everything that matters.</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">"Food. For everyone. On the beach." She thinks for a moment, then nods slowly. "The cafe can bring it. Skewers. Sweet rice. Something cold. I will make it work."</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">She pats your arm and goes back to her station, already planning.</p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>"Thank you, Bun Bun."</div>">> <<set $queshaRecruitState.maidCafe = true>> <<advancetime 15>> <<goto "ThePufferfish">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Maybe later</div>">> <<goto "ThePufferfish">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1408 0%, #0a0a1a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 2px 8px #ffd70044;">🌅 Hammerhead Tech and the Festival</h1> <div style="background: rgba(0,0,0,0.5); border: 2px solid #ffd700; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">You explain to the clerk what you need. Speakers for the beach. Strings of small lights along the dunes. Maybe a portable amp for whoever ends up singing.</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">She thinks about it, taps her tablet, then grins. "We rent a festival kit out a couple times a year. I can have it ready on day one hundred. No charge if you bring it back in one piece."</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">She slides you a folded receipt. "That's your hold ticket. Don't lose it."</p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>"Deal. Thanks."</div>">> <<set $queshaRecruitState.techStore = true>> <<advancetime 15>> <<goto "TechStore">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Maybe later</div>">> <<goto "TechStore">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #1a1408 0%, #0a0a1a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 2px 8px #ffd70044;">🌅 The Dockworkers and the Festival</h1> <div style="background: rgba(0,0,0,0.5); border: 2px solid #ffd700; border-radius: 12px; padding: 20px; margin-bottom: 20px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">You wander down to the pier and find a small knot of dockworkers on a smoke break. You explain Quesha's idea. Sunfish Day. The shrine. Lanterns along the boats at sunset.</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">One of them, older, weathered, sets her cigarette aside. "My grandmother told me about that day. We thought it was just stories."</p> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">She looks at the others, then back at you. "We'll string the lanterns. We'll hang the buoys. You bring the rest."</p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>"Thank you. All of you."</div>">> <<set $queshaRecruitState.docks = true>> <<advancetime 15>> <<goto "Docks">> <</link>> <<link "<div style='background: #555; color: #ccc; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Maybe later</div>">> <<goto "Docks">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <div style="background: linear-gradient(180deg, #2a1f08 0%, #1a0a25 60%, #0a1a25 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 850px; margin: 0 auto;"> <h1 style="color: #ffd700; text-align: center; text-shadow: 0 2px 12px #ffd70066;">🌅 Sunfish Day</h1> <p style="color: #ffe082; text-align: center; font-style: italic; margin-top: 0;">Day one hundred. Year <<= setup.diving.currentYear()>>.</p> <div style="background: rgba(0,0,0,0.55); border: 2px solid #ffd700; border-radius: 14px; padding: 22px; margin-bottom: 22px;"> <p style="color: #ddd; line-height: 1.7; margin: 0 0 12px 0;">The shrine has not looked like this in a very long time. The pale stone is wrapped in marigolds and seagrass. Someone has lit small candles in clamshells along the path. The water beyond is calm and gold with the afternoon.</p> <p style="color: #ddd; line-height: 1.7; margin: 0;">Quesha is at the heart of it, barefoot in the sand, hair loose, arguing happily with someone about whether the music is loud enough. She catches sight of you and her whole face changes.</p> </div> <<if $queshaRecruitState.maidCafe>> <div style="background: rgba(255,215,0,0.08); border: 1px solid #c97e3a; border-radius: 10px; padding: 14px; margin: 12px 0;"> <p style="color: #ddd; line-height: 1.6; margin: 0;">Bun Bun and the rest of the cafe staff have set up long tables of food at the edge of the sand. Skewers, sweet rice, something cold in big glass jugs. Bun Bun catches your eye from behind the table and nods once, satisfied.</p> </div> <</if>> <<if $queshaRecruitState.techStore>> <div style="background: rgba(255,215,0,0.08); border: 1px solid #c97e3a; border-radius: 10px; padding: 14px; margin: 12px 0;"> <p style="color: #ddd; line-height: 1.6; margin: 0;">Speakers from Hammerhead Tech are propped on driftwood, threading slow music across the beach. As the sun lowers, the strings of small lights along the dunes flicker on one section at a time, like the festival is exhaling.</p> </div> <</if>> <<if $queshaRecruitState.docks>> <div style="background: rgba(255,215,0,0.08); border: 1px solid #c97e3a; border-radius: 10px; padding: 14px; margin: 12px 0;"> <p style="color: #ddd; line-height: 1.6; margin: 0;">Out on the water, the dockworkers have strung paper lanterns across every boat in the harbor. They drift in a slow line just past the surf, candles burning, reflections doubled in the calm water.</p> </div> <</if>> <div style="background: rgba(216,27,96,0.08); border: 2px solid #d81b60; border-radius: 12px; padding: 18px; margin: 20px 0;"> <h3 style="color: #d81b60; margin: 0 0 10px 0;">💛 Sunset with Quesha</h3> <<if $sunfishDayYear === 0>> <p style="color: #ddd; line-height: 1.7;">She finds you when the sun is finally low enough to be gold instead of white. The crowd is thinning out toward the water. She is barefoot, sandy, smiling like she has been smiling all day and is not done yet.</p> <p style="color: #ddd; line-height: 1.7;">"Thank you," she says simply. "It looks like the stories. I thought it would. I did not really believe it would."</p> <p style="color: #ddd; line-height: 1.7; margin: 0;">She watches the lanterns ride the swell for a long quiet moment, then turns her face toward yours. "Same time next year. Promise."</p> <<else>> <p style="color: #ddd; line-height: 1.7;">She finds you again at sunset, sandy and grinning, hair a little wilder than the year before. She has done this enough times now to know exactly when to come looking for you.</p> <p style="color: #ddd; line-height: 1.7; margin: 0;">"Year <<= setup.diving.currentYear()>>," she says, and laughs once. "Every time it gets better. Stay for the lanterns?"</p> <</if>> </div> <div style="margin-top: 30px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #ffd700 0%, #c97e3a 100%); color: #1a1a1a; padding: 14px 30px; border-radius: 8px; cursor: pointer; font-weight: bold; display: inline-block;'>Stay for the lanterns</div>">> <<set $sunfishDayYear += 1>> <<set $sunfishDayLastFiredDay = $dayNumber>> <<set $shrineLastVisitDay = $dayNumber>> <<advancetime 180>> /* Add the festival buff AFTER advancetime so it counts from post-festival game time, not the moment the player clicks. Prevents the buff expiring for evening attendees before they ever surface back at the Beach. */ <<set _remaining = 1440 - $timeInMinutes>> <<if _remaining < 120>><<set _remaining = 120>><</if>> <<run setup.addBuff("shrine_pilgrim", _remaining)>> <<goto "Beach">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DiveSinkerRescue">> <div style="background: linear-gradient(180deg, #051a25 0%, #0a0a0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #4dd0e1; border-radius: 12px; padding: 25px;"> <h1 style="color: #ff6b6b; text-align: center;">💢 Rescue</h1> <p style="color: #ddd; line-height: 1.7;">You step off the sandbar and the bottom drops out from under you. There is no swimming. There is no kicking. There is just the soft cold pull of the sea taking you down like you weigh exactly what you weigh, which is too much, and the surface getting smaller above your eyes.</p> <p style="color: #ddd; line-height: 1.7;">You see the silver flash of her tail before you see her. She comes down faster than anything has a right to move, blue hair fanning, eyes wide and not even a little embarrassed about the shape she is in. Her hands close on your shoulders. You feel her brace, kick once, twice, and then the world is going up instead of down.</p> <p style="color: #ddd; line-height: 1.7;">Air. Sand under your back. Her wet hair dripping onto your face. She is breathing hard, gills working at the side of her throat, one hand still flat on your sternum as if she is checking that you are real.</p> <p style="color: #4dd0e1; font-style: italic; line-height: 1.7;">"Okay. Okay, you're alright. Just... no more of that, please. Not while you're like this. I almost couldn't reach you, hon. Promise me you'll come back when you can swim again."</p> <p style="color: #ddd; line-height: 1.7;">She helps you up onto the warm sand. You sit there shaking for a long time while she fusses around you, draping a towel over your shoulders, checking your pulse with the focused care of someone who has done this before. She does not bill you for the dive. She does not bill you for the rescue. She just stays close until your hands stop trembling.</p> <<set $queshaSinkerRescued = true>> <<run setup.addDebuff("exhaustion")>> <<advancetime 90>> <div style="margin-top: 25px; text-align: center;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Continue</div>">> <<goto "QueshaDiveShop">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "BeachDiveWorkbench">> <<set _setIds = ["coralSet", "wreckSet", "trenchSet"]>> <<set _currentSet = setup.diving.currentGearSet()>> <div style="background: linear-gradient(180deg, #0a1f1a 0%, #0a0a0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 900px; margin: 0 auto;"> <!-- Header --> <div style="background: linear-gradient(135deg, #00bfa5 0%, #00695caa 100%); padding: 18px; border-radius: 12px; margin-bottom: 20px; border: 2px solid #00bfa5; box-shadow: 0 0 25px rgba(0,191,165,0.25);"> <h2 style="color: white; text-align: center; margin: 0; font-size: 26px; text-shadow: 0 2px 6px rgba(0,0,0,0.5);">🛠 Dive Workbench</h2> </div> <!-- Currently equipped --> <div style="background: #1a1a1a; border: 2px solid #00bfa5; border-radius: 10px; padding: 16px; margin-bottom: 20px;"> <h3 style="color: #00bfa5; margin: 0 0 8px 0;">Currently Equipped</h3> <<if _currentSet>> <<set _curDef = setup.diving.GEAR_SET_DEFS[_currentSet]>> <p style="color: #fff; font-weight: bold; margin: 0;"><<= _curDef.name>> · +<<= _curDef.breathBonus>> breath / +<<= _curDef.staminaBonus>> stamina</p> <p style="color: #aaa; font-size: 13px; line-height: 1.4; margin: 6px 0 0 0;"><<= _curDef.description>></p> <<else>> <p style="color: #aaa; font-style: italic; margin: 0;">Nothing yet. Coral Shelf gear is the place to start.</p> <</if>> </div> <!-- Resources at a glance --> <div style="background: #0d0d0d; border: 1px solid #333; border-radius: 6px; padding: 10px; margin-bottom: 20px; text-align: center; color: #ddd;"> <span style="color: #00bfa5; font-weight: bold;">Wallet:</span> $<<= ($money || 0).toLocaleString()>> · <span style="color: #00bfa5; font-weight: bold;">Scrap:</span> <<= $diveScrap || 0>> · <span style="color: #00bfa5; font-weight: bold;">Materials:</span> <<= $diveMaterials ? Object.keys($diveMaterials).length : 0>> kinds </div> <!-- Companion --> <div style="background: #1a1a1a; border: 2px solid #ff69b4; border-radius: 10px; padding: 16px; margin-bottom: 20px;"> <h3 style="color: #ff69b4; margin: 0 0 8px 0;">🐠 Companion</h3> <<set _wbComp = setup.diving.getTamedCreature()>> <<if _wbComp>> <div style="color: #fff; font-weight: bold;"><<= _wbComp.name>></div> <div style="color: #aaa; font-size: 13px; margin-top: 4px;"><strong style="color:#4dabf7;">Passive:</strong> <<= _wbComp.passiveDesc>></div> <div style="color: #aaa; font-size: 13px;"><strong style="color:#ffd700;">Active:</strong> <<= _wbComp.activeName>> (<<= _wbComp.charges>>/dive): <<= _wbComp.activeDesc>></div> <div style="text-align: center; margin-top: 10px;"> <<link "<span style='background: #ff6b6b; color: white; padding: 8px 16px; border-radius: 5px; font-weight: bold; font-size: 13px; cursor: pointer;'>Release <<= _wbComp.name>></span>">> <<run setup.diving.releaseCreature()>> <<goto "BeachDiveWorkbench">> <</link>> </div> <<else>> <p style="color: #888; font-style: italic; margin: 0;">No companion. Befriend a creature in a Creature Den while diving to gain one. You can keep one at a time.</p> <</if>> </div> <!-- Recipe cards --> <<for _sIdx = 0; _sIdx < _setIds.length; _sIdx++>> <<set _sId = _setIds[_sIdx]>> <<set _sDef = setup.diving.GEAR_SET_DEFS[_sId]>> <<set _sReport = setup.diving.gearSetCraftReport(_sId)>> <<set _sOwned = (_currentSet === _sId)>> <<set _sPassed = false>> <<if _currentSet === "wreckSet" && _sId === "coralSet">><<set _sPassed = true>><</if>> <<if _currentSet === "trenchSet" && (_sId === "coralSet" || _sId === "wreckSet")>><<set _sPassed = true>><</if>> <<capture _sId, _sDef, _sReport, _sOwned, _sPassed>> <<set _borderColor = _sOwned ? "#51cf66" : (_sPassed ? "#666" : (_sReport.can ? "#00bfa5" : "#ff6b6b"))>> <div style="background: #1a1a1a; border: 2px solid <<= _borderColor>>; border-radius: 10px; padding: 16px; margin-bottom: 16px;"> <div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; margin-bottom: 8px;"> <div> <h3 style="color: <<= _borderColor>>; margin: 0;"><<= _sDef.name>> <span style="font-size: 13px; color: #888;">(Tier <<= _sDef.tier>>)</span></h3> <div style="color: #00bfa5; font-size: 13px; margin-top: 2px;">+<<= _sDef.breathBonus>> breath / +<<= _sDef.staminaBonus>> stamina · <<= _sDef.timeMinutes>> min</div> </div> <<if _sOwned>> <span style="background: #51cf66; color: #1a1a1a; padding: 6px 14px; border-radius: 5px; font-weight: bold; font-size: 13px;">✓ Equipped</span> <<elseif _sPassed>> <span style="color: #888; font-style: italic; font-size: 13px;">Past tier</span> <</if>> </div> <p style="color: #ddd; font-size: 13px; line-height: 1.5; margin: 0 0 12px 0;"><<= _sDef.description>></p> <<if !_sOwned && !_sPassed>> <!-- Requirement rows --> <div style="background: #0d0d0d; border-radius: 6px; padding: 10px; margin-bottom: 10px;"> <<for _rIdx = 0; _rIdx < _sReport.rows.length; _rIdx++>> <<set _row = _sReport.rows[_rIdx]>> <<set _rowColor = _row.ok ? "#51cf66" : "#ff6b6b">> <div style="display: flex; justify-content: space-between; font-size: 13px; padding: 3px 0;"> <span style="color: #ddd;"><<= _row.label>></span> <span style="color: <<= _rowColor>>; font-weight: bold;"><<if _row.kind === "cash">>$<<= _row.have.toLocaleString()>> / $<<= _row.need.toLocaleString()>><<else>><<= _row.have>> / <<= _row.need>><</if>></span> </div> <</for>> <<if _sReport.reasons.length > 0>> <<for _rsnIdx = 0; _rsnIdx < _sReport.reasons.length; _rsnIdx++>> <p style="color: #ff8080; font-size: 12px; font-style: italic; margin: 6px 0 0 0;"><<= _sReport.reasons[_rsnIdx]>></p> <</for>> <</if>> </div> <!-- Craft button --> <div style="text-align: center;"> <<if _sReport.can>> <<link "<div style='background: linear-gradient(135deg, #00bfa5 0%, #00695c 100%); color: white; padding: 10px 24px; border-radius: 6px; font-weight: bold; cursor: pointer; display: inline-block;'>Craft <<= _sDef.name>></div>">> <<run setup.diving.craftGearSet(_sId)>> <<advancetime _sDef.timeMinutes>> <<goto "BeachDiveWorkbench">> <</link>> <<else>> <div style="background: #2a1010; color: #ff8080; padding: 10px 24px; border-radius: 6px; font-weight: bold; display: inline-block; opacity: 0.7;">Requirements not met</div> <</if>> </div> <</if>> </div> <</capture>> <</for>> <!-- Back --> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>← Back to Beach</div>">> <<goto "Beach">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DiveCombat">> <<set _c = $diveCombat>> <<set _mode = setup.diving.resourceMode()>> <<set _res = setup.diving.getCurrentResource()>> <<set _resLabel = (_mode === "aquatic") ? "Stamina" : "Breath">> <<if !_c>> /* Safety: no active combat, bounce back to the dive. */ <<goto "DiveNode">> <</if>> <div style="background: linear-gradient(180deg, #2a0a0a 0%, #0a0a0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <div style="background: rgba(0,0,0,0.5); border: 2px solid #ff6b6b; border-radius: 8px; padding: 12px; margin-bottom: 18px; text-align: center; color: #ddd;"> <span style="color: #ff6b6b; font-weight: bold;">Combat</span> · <span style="color: #4dd0e1; font-weight: bold;"><<= _resLabel>>:</span> <<= _res>> · <span style="color: #4dd0e1; font-weight: bold;">Round:</span> <<= _c.round>> </div> <div style="background: #1a1a1a; border: 3px solid #ff3030; border-radius: 12px; padding: 22px; margin-bottom: 20px; box-shadow: 0 0 25px rgba(255,48,48,0.2);"> <h2 style="color: #ff3030; margin: 0 0 6px 0; text-align: center; font-size: 26px;"><<= _c.name>><<if _c.boss>> <span style="font-size: 13px; color: #ffd700;">(BOSS)</span><<elseif _c.elite>> <span style="font-size: 13px; color: #a855f7;">(Elite)</span><</if>></h2> <!-- Predator HP bar --> <<set _hpPct = Math.max(0, Math.round((_c.hp / _c.maxHp) * 100))>> <div style="background: #0d0d0d; border-radius: 8px; height: 22px; margin: 12px 0 6px 0; overflow: hidden; border: 1px solid #ff3030;"> <<print '<div style="background: linear-gradient(90deg, #ff3030 0%, #ff6b6b 100%); height: 100%; width: ' + _hpPct + '%;"></div>'>> </div> <p style="color: #ddd; text-align: center; margin: 0; font-size: 13px;"><<= _c.hp>> / <<= _c.maxHp>> HP · Bite: <<= _c.attack>> <<= _resLabel>>/hit</p> <<if _c.lastLog>><p style="color: #ffd700; text-align: center; margin: 8px 0 0 0; font-size: 13px;"><<= _c.lastLog>></p><</if>> </div> <!-- Combat actions --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 16px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #ff6b6b; color: #ff6b6b; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>⚔️ Attack (<<= setup.diving.estimatePlayerDamage().min>>-<<= setup.diving.estimatePlayerDamage().max>>)</div>">> <<set _r = setup.diving.combatAttack(0)>> <<if _r.predatorDead>> <<run setup.diving.combatRewards()>> <<goto "DiveCombatWin">> <<elseif _r.playerDrowned>> <<run setup.diving.combatLoss()>> <<goto "DiveResult">> <<else>> <<goto "DiveCombat">> <</if>> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #4dabf7; color: #4dabf7; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>🏊 Flee</div>">> <<set _f = setup.diving.combatFlee()>> <<if _f.escaped>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <<elseif _f.playerDrowned>> <<run setup.diving.combatLoss()>> <<goto "DiveResult">> <<else>> <<goto "DiveCombat">> <</if>> <</link>> </div> <!-- Trait combat moves --> <<set _cmbAbs = setup.diving.getCombatAbilities()>> <<if _cmbAbs.length > 0>> <div style="background: #1a1a1a; border: 2px solid #ffd700; border-radius: 10px; padding: 14px; margin-bottom: 16px;"> <h3 style="color: #ffd700; margin: 0 0 8px 0; font-size: 15px;">🌟 Trait Combat Moves</h3> <div style="display: grid; grid-template-columns: 1fr; gap: 6px;"> <<for _cai = 0; _cai < _cmbAbs.length; _cai++>> <<set _ca = _cmbAbs[_cai]>> <<set _caCharges = setup.diving.getCombatAbilityCharges(_ca.traitName)>> <<capture _ca, _caCharges>> <div style="background: #0d0d0d; border: 1px solid <<= _caCharges > 0 ? '#ffd700' : '#666'>>; border-radius: 6px; padding: 8px 10px; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px;"> <div style="flex: 1; min-width: 180px;"> <div style="color: <<= _caCharges > 0 ? '#ffd700' : '#888'>>; font-weight: bold; font-size: 13px;"><<= _ca.abilityName>> <span style="color: #aaa; font-size: 11px;">(<<= _ca.traitName>>)</span></div> <div style="color: #aaa; font-size: 11px;"><<= _ca.desc>></div> </div> <div style="display: flex; align-items: center; gap: 8px;"> <span style="color: <<= _caCharges > 0 ? '#ffd700' : '#888'>>; font-weight: bold; font-size: 12px;"><<= _caCharges>>/<<= _ca.charges>></span> <<if _caCharges > 0>> <<link "<span style='background: #ffd700; color: #1a1a1a; padding: 6px 12px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Use</span>">> <<set _r = setup.diving.useCombatAbility(_ca.traitName)>> <<if _r.predatorDead>> <<run setup.diving.combatRewards()>><<goto "DiveCombatWin">> <<elseif _r.playerDrowned>> <<run setup.diving.combatLoss()>><<goto "DiveResult">> <<else>> <<goto "DiveCombat">> <</if>> <</link>> <<else>> <span style="background: #333; color: #888; padding: 6px 12px; border-radius: 5px; font-size: 12px; font-style: italic;">Spent</span> <</if>> </div> </div> <</capture>> <</for>> </div> </div> <</if>> <!-- Tamed companion active (free) --> <<set _ccomp = setup.diving.getTamedCreature()>> <<if _ccomp && ($tamedCreatureCharges || 0) > 0>> <div style="background: #1a1a1a; border: 2px solid #ff69b4; border-radius: 10px; padding: 14px; margin-bottom: 16px;"> <h3 style="color: #ff69b4; margin: 0 0 8px 0; font-size: 15px;">🐠 <<= _ccomp.name>>: <<= _ccomp.activeName>> (<<= $tamedCreatureCharges>>)</h3> <<link "<div style='background: #ff69b4; color: #1a1a1a; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Use <<= _ccomp.activeName>></div>">> <<run setup.diving.useTamedActive()>> <<goto "DiveCombat">> <</link>> </div> <</if>> <!-- Consumable panic-heals (free action) --> <<if $diveConsumables && $diveConsumables.length > 0>> <div style="background: #1a1a1a; border: 2px solid #4dabf7; border-radius: 10px; padding: 14px; margin-bottom: 16px;"> <h3 style="color: #4dabf7; margin: 0 0 8px 0; font-size: 15px;">🎒 Use a Consumable (free)</h3> <div style="display: grid; grid-template-columns: 1fr; gap: 6px;"> <<for _cci = 0; _cci < $diveConsumables.length; _cci++>> <<set _ccItem = $diveConsumables[_cci]>> <<set _ccIndex = _cci>> <<capture _ccIndex, _ccItem>> <div style="background: #0d0d0d; border: 1px solid #4dabf7; border-radius: 6px; padding: 8px 10px; display: flex; justify-content: space-between; align-items: center; gap: 8px;"> <span style="color: #4dabf7; font-size: 13px;"><<= _ccItem.name>></span> <<link "<span style='background: #4dabf7; color: #0d0d0d; padding: 5px 12px; border-radius: 5px; font-weight: bold; font-size: 12px; cursor: pointer;'>Use</span>">> <<run setup.diving.combatUseConsumable(_ccIndex)>> <<goto "DiveCombat">> <</link>> </div> <</capture>> <</for>> </div> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DiveCombatWin">> <<set _s = $diveCombatResult>> <div style="background: linear-gradient(180deg, #0a2a0a 0%, #0a0a0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #51cf66; border-radius: 12px; padding: 25px;"> <h2 style="color: #51cf66; text-align: center; font-size: 28px; margin: 0 0 12px 0;">⚔️ <<if _s && _s.boss>>Boss Slain<<elseif _s && _s.elite>>Elite Slain<<else>>Predator Slain<</if>></h2> <p style="color: #ddd; line-height: 1.6; text-align: center;">You drove off the <<= _s ? _s.name : "predator">> and stripped it for everything worth taking.</p> <<if _s && _s.loot && _s.loot.length > 0>> <div style="background: #1a1a1a; border-radius: 8px; padding: 14px; margin: 18px 0;"> <h3 style="color: #51cf66; margin: 0 0 8px 0; font-size: 15px;">Spoils</h3> <div style="display: grid; grid-template-columns: 1fr; gap: 4px;"> <<for _li = 0; _li < _s.loot.length; _li++>> <<set _lit = _s.loot[_li]>> <<set _lc = setup.diving.rarityColor(_lit.rarity || "common")>> <div style="color: <<= _lc>>; font-size: 14px;">+ <<= _lit.name>> <span style="color: #888; font-size: 12px;">(<<= setup.diving.rarityLabel(_lit.rarity || "common")>>)</span></div> <</for>> </div> </div> <</if>> <<if _s && _s.newTrait>> <p style="color: #ffd700; line-height: 1.6; text-align: center; font-style: italic; margin-top: 14px;">Something shifts in you as the creature falls. You feel <<= _s.newTrait>>.</p> <</if>> <div style="text-align: center; margin-top: 22px;"> <<link "<div style='background: linear-gradient(135deg, #4dd0e1 0%, #00838f 100%); color: white; padding: 12px 24px; border-radius: 6px; cursor: pointer; font-weight: bold; display: inline-block;'>Continue Diving</div>">> <<set $diveCombatResult = null>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DiveTame">> <<set _newId = $pendingTameCreature>> <<set _new = _newId ? setup.diving.CREATURE_DEFS[_newId] : null>> <<set _cur = setup.diving.getTamedCreature()>> <<if !_new>> <<goto "DiveNode">> <</if>> <div style="background: linear-gradient(180deg, #0a2a2a 0%, #0a0a0a 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto; background: rgba(0,0,0,0.5); border: 2px solid #ff69b4; border-radius: 12px; padding: 25px;"> <h2 style="color: #ff69b4; text-align: center; font-size: 26px; margin: 0 0 12px 0;">💖 A Creature Trusts You</h2> <p style="color: #ddd; line-height: 1.6; text-align: center;">A <<= _new.name>> drifts close and stays. It will follow you on your dives if you let it.</p> <div style="background: #1a1a1a; border: 2px solid #ff69b4; border-radius: 8px; padding: 14px; margin: 18px 0;"> <div style="color: #ff69b4; font-weight: bold; font-size: 16px;"><<= _new.name>></div> <div style="color: #aaa; font-size: 13px; margin-top: 4px;"><strong style="color:#4dabf7;">Passive:</strong> <<= _new.passiveDesc>></div> <div style="color: #aaa; font-size: 13px;"><strong style="color:#ffd700;">Active:</strong> <<= _new.activeName>> (<<= _new.charges>>/dive): <<= _new.activeDesc>></div> </div> <<if _cur>> <p style="color: #ffb088; line-height: 1.5; text-align: center; font-size: 13px;">You already travel with a <<= _cur.name>>. You can only keep one companion. Taming the <<= _new.name>> releases your <<= _cur.name>>.</p> <</if>> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 20px;"> <<link "<div style='background: #ff69b4; color: #1a1a1a; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Tame the <<= _new.name>></div>">> <<run setup.diving.tameCreature(_newId)>> <<set $pendingTameCreature = null>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</link>> <<link "<div style='background: #555; color: #ddd; padding: 12px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'><<if _cur>>Keep my <<= _cur.name>><<else>>Leave it<</if>></div>">> <<set $pendingTameCreature = null>> <<set $diveCurrentNode = null>> <<goto "DiveNode">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes secOn{0%{box-shadow:0 0 0 rgba(60,220,120,0);}40%{box-shadow:0 0 42px rgba(60,220,120,0.75);}100%{box-shadow:0 0 18px rgba(60,220,120,0.4);}} .ct-row{display:flex;justify-content:center;gap:28px;flex-wrap:wrap;padding:10px 0 4px;} .ct-col{display:flex;flex-direction:column;align-items:center;gap:7px;} .ct{position:relative;width:94px;height:226px;border-radius:46px/30px;border:3px solid #3a4a40;background:linear-gradient(180deg,rgba(180,210,230,0.05),rgba(120,150,170,0.03));overflow:hidden;cursor:pointer;box-shadow:0 0 14px rgba(0,0,0,0.5),inset 0 0 18px rgba(0,0,0,0.55);transition:box-shadow 0.3s ease,border-color 0.3s ease;} .ct:hover{border-color:#5aa0ff;box-shadow:0 0 26px rgba(70,150,255,0.4),inset 0 0 18px rgba(0,0,0,0.55);} .ct-residue{position:absolute;left:0;right:0;bottom:0;height:11%;background:linear-gradient(180deg,rgba(80,150,255,0.18),rgba(40,90,200,0.4));} .ct-residue::before{content:'';position:absolute;left:0;right:0;top:0;height:4px;background:rgba(150,200,255,0.4);} .ct-broken{cursor:default;opacity:0.72;border-color:#4a3f3f;clip-path:polygon(0 17%,16% 5%,33% 15%,50% 3%,67% 14%,84% 6%,100% 17%,100% 100%,0 100%);box-shadow:inset 0 0 18px rgba(0,0,0,0.6);} .ct-broken:hover{border-color:#4a3f3f;box-shadow:inset 0 0 18px rgba(0,0,0,0.6);} .ct-puddle{position:absolute;left:10%;right:10%;bottom:0;height:9px;border-radius:50%;background:rgba(70,140,255,0.28);} .ct-crack{position:absolute;background:rgba(170,200,235,0.28);} .ct-cap{color:#9ccc65;font-size:13px;font-weight:bold;letter-spacing:1px;} .sec{border-radius:10px;padding:16px 18px;border:2px solid;} .sec-armed{background:linear-gradient(135deg,#2a1212 0%,#180b0b 100%);border-color:#c0392b;} .sec-off{background:linear-gradient(135deg,#0e2417 0%,#08160e 100%);border-color:#3cdc78;animation:secOn 1.2s ease-out;} .sec-dot{width:12px;height:12px;border-radius:50%;display:inline-block;margin-right:8px;vertical-align:middle;} .sec-dot-armed{background:#ff5b4d;box-shadow:0 0 10px rgba(255,80,60,0.85);} .sec-dot-off{background:#3cdc78;box-shadow:0 0 10px rgba(60,220,120,0.85);} .sec-status{font-weight:bold;letter-spacing:2px;font-size:14px;} </style> <div style="background:#060f06;min-height:100vh;padding:20px;"> <h1 style="color:#8cff66;text-align:center;text-shadow:0 0 12px rgba(140,255,102,0.4);">🧪 The Overgrown Lab</h1> <div style="padding:20px;background:linear-gradient(135deg,#0c1f0c 0%,#08140a 100%);border-radius:15px;margin-bottom:25px;border:2px solid #8cff66;box-shadow:0 0 25px rgba(140,255,102,0.15);"> <p style="color:#dfe;font-size:17px;margin:0;line-height:1.7;">The jungle has all but eaten this place. Shattered glassware crunches underfoot, and thick vines pour through a collapsed section of the roof. Along the back wall stand three tall containment tubes, empty now, their glass clouded with age, only a shallow skin of blue residue pooled in the bottom of each.</p> </div> <h2 style="color:#8cff66;border-bottom:2px solid #2a4a1a;padding-bottom:8px;text-align:center;">Containment Tubes</h2> <<set _vatHasTF = ($physicalTraits || []).concat($mentalTraits || []).some(function(t){ return t !== "Slime" && setup.isTransformationTrait && setup.isTransformationTrait(t); })>> <p style="text-align:center;color:#9aa;font-size:14px;margin:0 0 6px;">Three tubes, tall enough to hold a person, standing empty. A control beside each one still glows. There is room inside to climb in.</p> <div class="ct-row"> <<for _ti = 0; _ti < 3; _ti++>> <div class="ct-col"> <<if $slimeTubeBroken && _ti === 0>> <div class="ct ct-broken"><div class="ct-puddle"></div><div class="ct-crack" style="left:30%;top:26%;width:2px;height:42%;transform:rotate(20deg);"></div><div class="ct-crack" style="left:56%;top:20%;width:2px;height:52%;transform:rotate(-13deg);"></div><div class="ct-crack" style="left:44%;top:34%;width:2px;height:34%;transform:rotate(6deg);"></div></div> <span class="ct-cap" style="color:#8a7a7a;">Shattered</span> <<else>> <<link "<div class='ct'><div class='ct-residue'></div></div>">> <<if $physicalTraits.includes("Slime")>> <<replace "#tube-msg">><span style="color:#7fb8ff;">You lean a gooey hand against the glass and the blue residue inside leans back, recognizing its own. There is nothing left for it to do to you. You already are what it makes.</span><</replace>> <<elseif _vatHasTF>> <<replace "#tube-msg">><span style="color:#c97a7a;">The tube reads the shape already worked into your flesh and the residue draws back from the glass, baffled. It cannot lay slime over another transformation. You would have to be your own plain self again before it would take.</span><</replace>> <<elseif $physicalTraits.includes("slime")>> <<goto "OvergrownLabSlimeChamber">> <<else>> <<replace "#tube-msg">><span style="color:#c97a7a;">You thumb the control and the tube clicks, whirs, then goes dead. Nothing floods in. The mechanism does not stir for ordinary flesh.</span><</replace>> <</if>> <</link>> <span class="ct-cap">Climb In</span> <</if>> </div> <</for>> </div> <div id="tube-msg" style="text-align:center;margin:12px 0 24px;min-height:18px;line-height:1.5;"></div> <h2 style="color:#8cff66;border-bottom:2px solid #2a4a1a;padding-bottom:8px;text-align:center;">The Mixing Station</h2> <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));gap:15px;margin-bottom:25px;"> <div style="border:3px solid #5a7a3a;border-radius:10px;padding:15px;background:#161e12;opacity:0.95;display:flex;flex-direction:column;"> <h3 style="color:#9ccc65;margin:0 0 10px 0;">⚗️ The Apparatus</h3> <p style="font-size:14px;color:#9aa;margin:0 0 12px 0;line-height:1.5;flex-grow:1;">A rack of cracked test tubes and a row of empty basins waits beneath the fume hood. Drop ingredients into the apparatus, give it a mix, and see what comes out.</p> <<link "<div style='display:inline-block;background:linear-gradient(135deg,#5a9e3a 0%,#8cff66 100%);color:#06140a;padding:10px 22px;border-radius:6px;cursor:pointer;font-weight:bold;text-align:center;'>Use the Mixing Station</div>">> <<advancetime 5>> <<goto "OvergrownLabMix">> <</link>> </div> </div> <h2 style="color:#8cff66;border-bottom:2px solid #2a4a1a;padding-bottom:8px;text-align:center;">Security System</h2> <div style="margin-bottom:25px;"> <<if $labSecurityDisabled>> <div class="sec sec-off"> <div><span class="sec-dot sec-dot-off"></span><span class="sec-status" style="color:#7df0a8;">SECURITY OFFLINE</span></div> <p style="color:#cfe;font-size:14px;line-height:1.5;margin:10px 0 0;">The lockout is dead. The door reads open to anyone now. You can walk in straight from the Jungle, or from your camp, without the handshake.</p> </div> <<elseif $physicalTraits.includes("Automaton")>> <div class="sec sec-armed"> <div><span class="sec-dot sec-dot-armed"></span><span class="sec-status" style="color:#ff8f8f;">SECURITY ARMED</span></div> <p style="color:#e7c3c3;font-size:14px;line-height:1.5;margin:10px 0 14px;">A lockout console still guards the lab. Your servos slip into the maintenance port the old staff never could. Bring the whole system down and the door stays open for good.</p> <<link "<div style='display:inline-block;background:linear-gradient(135deg,#7a2f2f 0%,#c0392b 100%);color:white;padding:10px 22px;border-radius:6px;cursor:pointer;font-weight:bold;'>Override and Disable Security</div>">> <<set $labSecurityDisabled = true>> <<goto "OvergrownLab">> <</link>> </div> <<else>> <div class="sec sec-armed"> <div><span class="sec-dot sec-dot-armed"></span><span class="sec-status" style="color:#ff8f8f;">SECURITY ARMED</span></div> <p style="color:#e7c3c3;font-size:14px;line-height:1.5;margin:10px 0 0;">A lockout console still guards the lab, its maintenance port sealed behind a hardware handshake. Only an automaton interface can override it.</p> </div> <</if>> </div> <div style="text-align:center;margin-top:25px;"> <<link "<div style='display:inline-block;background:#2ecc71;color:white;padding:12px 25px;border-radius:6px;cursor:pointer;font-weight:bold;'>Return to Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$combinerIngredients>><<set $combinerIngredients = []>><</if>> <<set _owned = setup.labCombiner.owned()>> <div style="background:#060f06; min-height:100vh; padding:16px;"> <h1 style="color:#8cff66; text-align:center; text-shadow:0 0 12px rgba(140,255,102,0.4);">⚗️ The Mixing Station</h1> <p style="color:#9ccc65; text-align:center; margin:0 auto 16px auto; max-width:620px; font-size:14px; line-height:1.5;">Combine up to 5 ingredients in the apparatus. Some pairings follow known recipes. Anything else fuses into a brand new trait, all your own, shaped by what you put in. Combinations that make no sense come out flawed.</p> <!-- result banner --> <<if $lastMixResult>> <<if $lastMixResult.kind === "already">> <div style="background:#2a2618; border:2px solid #d4a017; border-radius:12px; padding:16px; margin-bottom:20px; text-align:center;"> <p style="color:#e8c24a; font-weight:bold; font-size:18px; margin:0 0 6px 0;">You already have this trait</p> <p style="color:#eee; font-size:16px; margin:0 0 6px 0;"><<print $lastMixResult.name>></p> <p style="color:#c9b87a; font-size:13px; margin:0;">Nothing happened, and your ingredients were left untouched.</p> </div> <<elseif $lastMixResult.kind === "blocked">> <div style="background:#0a1626; border:2px solid #4aa8ff; border-radius:12px; padding:16px; margin-bottom:20px; text-align:center;"> <p style="color:#8cc8ff; font-weight:bold; font-size:18px; margin:0 0 6px 0;">The orb stays inert</p> <p style="color:#bcd6ee; font-size:13px; margin:0;"><<print $lastMixResult.message>></p> </div> <<elseif $lastMixResult.kind === "oncedone">> <div style="background:#2a2618; border:2px solid #d4a017; border-radius:12px; padding:16px; margin-bottom:20px; text-align:center;"> <p style="color:#e8c24a; font-weight:bold; font-size:18px; margin:0 0 6px 0;">This can only be made once</p> <p style="color:#eee; font-size:16px; margin:0 0 6px 0;"><<print $lastMixResult.name>></p> <p style="color:#c9b87a; font-size:13px; margin:0;">You have already crafted it. Your ingredients were left untouched.</p> </div> <<elseif $lastMixResult.kind === "special">> <div style="background:linear-gradient(135deg,#3a2e08 0%,#5a4810 100%); border:2px solid #ffd700; border-radius:12px; padding:18px; margin-bottom:20px; text-align:center; box-shadow:0 0 28px rgba(255,215,0,0.35);"> <p style="color:#ffd700; font-weight:bold; font-size:21px; margin:0 0 8px 0; text-shadow:0 0 12px rgba(255,215,0,0.5);">✨ Something Extraordinary ✨</p> <p style="color:#fff; font-size:22px; font-weight:bold; margin:0 0 8px 0;"><<print $lastMixResult.name>></p> <<if $lastMixResult.note>><p style="color:#e8d9a0; font-size:14px; font-style:italic; margin:0;"><<print $lastMixResult.note>></p><</if>> </div> <<elseif $lastMixResult.negative>> <div style="background:#2a1414; border:2px solid #c0392b; border-radius:12px; padding:18px; margin-bottom:20px; text-align:center; box-shadow:0 0 22px rgba(192,57,43,0.25);"> <p style="color:#ff7a6b; font-weight:bold; font-size:20px; margin:0 0 8px 0;">⚠️ A Flawed Trait Forms</p> <p style="color:#ffd9d3; font-size:18px; margin:0 0 6px 0;"><<print $lastMixResult.name>></p> <<if $lastMixResult.bonus>><p style="color:#e8a59c; font-size:14px; margin:0;"><<print setup.labCombiner.bonusText($lastMixResult.bonus)>></p><</if>> </div> <<else>> <div style="background:linear-gradient(135deg,#10301a 0%,#1a4a28 100%); border:2px solid #8cff66; border-radius:12px; padding:18px; margin-bottom:20px; text-align:center; box-shadow:0 0 24px rgba(140,255,102,0.25);"> <p style="color:#8cff66; font-weight:bold; font-size:20px; margin:0 0 8px 0;">✨ A New Trait Forms</p> <p style="color:#eaffea; font-size:18px; margin:0 0 6px 0;"><<print $lastMixResult.name>></p> <<if $lastMixResult.bonus>><p style="color:#bfe6a0; font-size:14px; margin:0;"><<print setup.labCombiner.bonusText($lastMixResult.bonus)>></p><</if>> </div> <</if>> <<set $lastMixResult = null>> <</if>> <!-- failure banner --> <<if $lastMixFailed>> <div style="background:#2a2020; border:2px solid #ff6b6b; border-radius:12px; padding:16px; margin-bottom:20px; text-align:center;"> <p style="color:#ff6b6b; font-weight:bold; margin:0 0 6px 0;">✗ The mixture curdles</p> <p style="color:#ccc; font-size:14px; margin:0;"><<print $lastMixMessage>></p> </div> <<set $lastMixFailed = false>> <</if>> <!-- selected ingredients --> <div style="background:#0d160c; border:3px solid #8cff66; border-radius:10px; padding:16px; margin-bottom:18px;"> <h3 style="color:#8cff66; margin:0 0 12px 0; text-align:center;">In the Apparatus (<<print $combinerIngredients.length>>/5)</h3> <div style="display:flex; flex-wrap:wrap; gap:8px; justify-content:center; min-height:40px;"> <<if $combinerIngredients.length === 0>> <p style="color:#6a8a5a; margin:0;">Select up to 5 ingredients below.</p> <<else>> <<for _i, _key range $combinerIngredients>> <<capture _i, _key>> <<set _rec = setup.labCombiner.lookup(_key)>> <<link `"<div style='background:#16210f; color:#cfe; border:2px solid #5a7a3a; padding:8px 12px; border-radius:8px; cursor:pointer;'>" + (_rec.icon ? _rec.icon + " " : "") + _rec.name + " <span style='color:#888;'>✕</span></div>"`>> <<run setup.labCombiner.removeAt($combinerIngredients, _i)>> <<goto "OvergrownLabMix">> <</link>> <</capture>> <</for>> <</if>> </div> <<if $combinerIngredients.length > 0>> <div style="text-align:center; margin-top:12px;"> <<link "<span style='color:#888; cursor:pointer;'>Clear All</span>">> <<set $combinerIngredients = []>> <<goto "OvergrownLabMix">> <</link>> </div> <</if>> </div> <!-- available ingredients --> <div style="background:#0a120a; border:2px solid #3a5a2a; border-radius:10px; padding:16px; margin-bottom:18px;"> <h3 style="color:#9ccc65; margin:0 0 12px 0; text-align:center;">Your Ingredients</h3> <<if _owned.length === 0>> <p style="color:#6a8a5a; text-align:center; margin:0;">You have no usable ingredients yet. Gather ores, crops, fish, dive loot, or gifts, or cook some food, then come back.</p> <<else>> <div style="display:flex; flex-wrap:wrap; gap:8px; justify-content:center; max-height:320px; overflow-y:auto;"> <<for _ing range _owned>> <<capture _ing>> <<set _selCount = $combinerIngredients.filter(function(k){ return k === _ing.key; }).length>> <<set _remaining = _ing.qty - _selCount>> <<if $combinerIngredients.length < 5 && _remaining > 0 && (_ing.key !== "orb:blue_orb" || setup.labCombiner.orbUnlocked($combinerIngredients))>> <<link `"<div style='background:#16210f; color:#cfe; border:2px solid #5a7a3a; padding:8px 12px; border-radius:8px; cursor:pointer; min-height:40px;'>" + (_ing.icon ? _ing.icon + " " : "") + _ing.name + " <span style='color:#7fae50;'>x" + _remaining + "</span></div>"`>> <<run $combinerIngredients.push(_ing.key)>> <<goto "OvergrownLabMix">> <</link>> <<else>> <div style="background:#10160e; color:#5a6a4a; border:2px solid #2a3a1a; padding:8px 12px; border-radius:8px;"><<print _ing.icon ? _ing.icon + ' ' : ''>><<print _ing.name>> <span style="color:#445566;">x<<print _remaining>></span></div> <</if>> <</capture>> <</for>> </div> <</if>> </div> <!-- mix button --> <div style="text-align:center; margin-bottom:18px;"> <<if $combinerIngredients.length >= 2>> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#5a9e3a 0%,#8cff66 100%); color:#06140a; padding:14px 36px; border-radius:8px; font-weight:bold; font-size:17px; cursor:pointer;'>⚗️ Mix</div>">> <<set $lastMixResult = setup.labCombiner.apply($combinerIngredients)>> <<if $lastMixResult.success>><<set $combinerIngredients = []>><</if>> <<goto "OvergrownLabMix">> <</link>> <<else>> <div style="display:inline-block; background:#2a2a2a; color:#888; padding:14px 36px; border-radius:8px;">Select at least 2 ingredients to mix</div> <</if>> </div> <div style="text-align:center; margin-top:10px; display:flex; gap:10px; justify-content:center; flex-wrap:wrap;"> <<link `"<div style='display:inline-block; background:#3a5a2a; color:#cfe; border:2px solid #5a7a3a; padding:10px 22px; border-radius:6px; cursor:pointer; font-weight:bold;'>📖 Known Recipes (" + ($discoveredRecipes ? $discoveredRecipes.filter(function(r){ return r && Array.isArray(r.ingredients); }).length : 0) + ")</div>"`>> <<goto "OvergrownLabRecipes">> <</link>> <<link "<div style='display:inline-block; background:#2ecc71; color:white; padding:10px 24px; border-radius:6px; cursor:pointer; font-weight:bold;'>Back to the Lab</div>">> <<goto "OvergrownLab">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !$discoveredRecipes>><<set $discoveredRecipes = []>><</if>><<set _combRecipes = $discoveredRecipes.filter(function(r){ return r && Array.isArray(r.ingredients); })>> <div style="background:#060f06; min-height:100vh; padding:16px;"> <h1 style="color:#8cff66; text-align:center; text-shadow:0 0 12px rgba(140,255,102,0.4);">📖 Known Recipes</h1> <p style="color:#9ccc65; text-align:center; margin:0 auto 16px auto; max-width:600px; font-size:14px; line-height:1.5;">Recipes you have discovered by making them at the Mixing Station. <<print _combRecipes.length>> found so far.</p> <<if _combRecipes.length === 0>> <div style="background:#0a120a; border:2px solid #3a5a2a; border-radius:10px; padding:24px; text-align:center; max-width:600px; margin:0 auto;"> <p style="color:#6a8a5a; margin:0; line-height:1.6;">You haven't discovered any recipes yet. Experiment at the Mixing Station: when a combination produces a known trait, it gets recorded here so you can make it again.</p> </div> <<else>> <div style="max-width:640px; margin:0 auto; display:flex; flex-direction:column; gap:10px;"> <<for _r range _combRecipes>> <div style="background:#0d160c; border:2px solid #5a7a3a; border-radius:10px; padding:12px 14px;"> <div style="color:#8cff66; font-weight:bold; font-size:16px; margin-bottom:4px;"><<print _r.trait>></div> <div style="color:#cfe; font-size:14px; line-height:1.5;"><<print setup.labCombiner.recipeIngredientsHtml(_r.ingredients)>></div> </div> <</for>> </div> <</if>> <div style="text-align:center; margin-top:18px;"> <<link "<div style='display:inline-block; background:#2ecc71; color:white; padding:10px 24px; border-radius:6px; cursor:pointer; font-weight:bold;'>Back to the Mixing Station</div>">> <<goto "OvergrownLabMix">> <</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes scnPulse {0%{box-shadow:0 0 0 rgba(40,150,255,0);}50%{box-shadow:0 0 42px rgba(40,150,255,0.85),0 0 90px rgba(40,150,255,0.45);}100%{box-shadow:0 0 26px rgba(40,150,255,0.6);}} @keyframes scnPulseRed {0%{box-shadow:0 0 0 rgba(255,60,60,0);}50%{box-shadow:0 0 42px rgba(255,60,60,0.85),0 0 90px rgba(255,60,60,0.45);}100%{box-shadow:0 0 26px rgba(255,60,60,0.6);}} @keyframes scnSweep {0%{transform:translateY(-115%);opacity:0;}12%{opacity:1;}88%{opacity:1;}100%{transform:translateY(250%);opacity:0;}} @keyframes scnReject {0%,100%{transform:translateX(0);}20%{transform:translateX(-7px);}40%{transform:translateX(7px);}60%{transform:translateX(-5px);}80%{transform:translateX(5px);}} .scn{position:relative;width:280px;height:172px;margin:0 auto;border-radius:14px;background:linear-gradient(145deg,#2c3137 0%,#181b1f 55%,#0e1013 100%);border:2px solid #3c434c;box-shadow:inset 0 2px 6px rgba(255,255,255,0.05),inset 0 -8px 20px rgba(0,0,0,0.6),0 6px 16px rgba(0,0,0,0.5);overflow:hidden;cursor:pointer;transition:border-color 0.4s ease,background 0.6s ease;} .scn-grid{position:absolute;inset:0;background-image:repeating-linear-gradient(0deg,rgba(120,140,160,0.05) 0 1px,transparent 1px 16px),repeating-linear-gradient(90deg,rgba(120,140,160,0.05) 0 1px,transparent 1px 16px);} .scn-touch{position:absolute;left:50%;top:46%;width:88px;height:108px;transform:translate(-50%,-50%);border:2px dashed rgba(150,170,190,0.28);border-radius:44px 44px 40px 40px;transition:border-color 0.4s ease,box-shadow 0.4s ease;} .scn-beam{position:absolute;left:0;right:0;top:0;height:40px;background:linear-gradient(to bottom,rgba(60,170,255,0) 0%,rgba(80,185,255,0.6) 50%,rgba(60,170,255,0) 100%);opacity:0;pointer-events:none;} .scn-label{position:absolute;bottom:12px;left:0;right:0;text-align:center;font-size:12px;letter-spacing:3px;color:#6b7682;font-weight:bold;transition:color 0.4s ease;} .scn-active{background:linear-gradient(145deg,#16324f 0%,#0c2238 55%,#06121f 100%);border-color:#3aa8ff;animation:scnPulse 1.2s ease-in-out infinite;} .scn-active .scn-touch{border-color:rgba(110,200,255,0.85);box-shadow:0 0 18px rgba(70,180,255,0.6);} .scn-active .scn-label{color:#8fd6ff;} .scn-active .scn-beam{animation:scnSweep 1.15s ease-in-out infinite;} .scn-deny{background:linear-gradient(145deg,#4f1616 0%,#380c0c 55%,#1f0606 100%);border-color:#ff4d4d;animation:scnReject 0.5s ease,scnPulseRed 1.4s ease-in-out infinite;} .scn-deny .scn-touch{border-color:rgba(255,120,120,0.85);box-shadow:0 0 18px rgba(255,80,80,0.6);} .scn-deny .scn-label{color:#ff9090;} .scn-deny .scn-beam{background:linear-gradient(to bottom,rgba(255,60,60,0) 0%,rgba(255,90,90,0.6) 50%,rgba(255,60,60,0) 100%);animation:scnSweep 1.15s ease-in-out infinite;} </style> <div style="background:#060f06;min-height:100vh;padding:20px;"> <h1 style="color:#8cff66;text-align:center;text-shadow:0 0 12px rgba(140,255,102,0.4);">An Abandoned Laboratory</h1> <div style="padding:20px;background:linear-gradient(135deg,#0c1f0c 0%,#08140a 100%);border-radius:15px;margin-bottom:25px;border:2px solid #8cff66;box-shadow:0 0 25px rgba(140,255,102,0.15);"> <p style="color:#dfe;font-size:17px;margin:0;line-height:1.7;">You shoulder through a thicket and your foot comes down on something that crunches. Not a branch. Glass. The jungle has grown thick over a low concrete building, its windows long shattered. But the door is intact, sealed flush into the concrete, far too clean for a place this old. There is no handle, no lock you can pick. Only a smooth gray panel set into the wall beside it, dark and dormant, a faint dashed outline marking where a palm should rest.</p> </div> <div style="text-align:center;margin-bottom:8px;"> <<link "<div id='scn-panel' class='scn'><div class='scn-grid'></div><div class='scn-touch'></div><div class='scn-beam'></div><div class='scn-label' id='scn-label'>PALM SCANNER · STANDBY</div></div>">> <<if $physicalTraits.includes("Automaton")>> <<set $overgrownLabUnlocked = true>> <<set $discoveredOvergrownLab = true>> <<run $("#scn-panel").removeClass("scn-deny").addClass("scn-active").css("pointer-events","none")>> <<run $("#scn-label").text("AUTHORIZING ACCESS")>> <<timed 1.4s>><<run $("#scn-label").text("ACCESS GRANTED")>><</timed>> <<timed 2.4s>><<goto "OvergrownLab">><</timed>> <<else>> <<run $("#scn-panel").addClass("scn-deny")>> <<run $("#scn-label").text("ACCESS DENIED")>> <<replace "#door-scan-msg">><div style="margin:14px auto 0;max-width:460px;padding:14px;background:#1a0f0f;border:1px solid #6a3a3a;border-radius:8px;color:#c97a7a;line-height:1.5;">The panel flares red and stays sealed. Whatever wakes this mechanism, it is not a hand of flesh and blood.</div><</replace>> <</if>> <</link>> </div> <p style="text-align:center;color:#7a8a7a;font-size:13px;margin:0 0 14px;">Press your palm to the scanner.</p> <div id="door-scan-msg" style="text-align:center;"></div> <div style="text-align:center;margin-top:25px;"> <<link "<div style='display:inline-block;background:#2ecc71;color:white;padding:12px 25px;border-radius:6px;cursor:pointer;font-weight:bold;'>Back into the Jungle</div>">> <<goto "Jungle">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if $physicalTraits.includes("Slime")>> <div style="background:#040a16;min-height:100vh;padding:30px 20px;color:#dfe;text-align:center;"> <p style="font-size:17px;line-height:1.7;">The tube fills and laps at you and settles. You are already slime through and through; there is nothing more for it to take.</p> <div style="margin-top:24px;"><<link "<div style='display:inline-block;background:#2ecc71;color:white;padding:12px 25px;border-radius:6px;cursor:pointer;font-weight:bold;'>Climb back out</div>">><<goto "OvergrownLab">><</link>></div> </div> <<else>> <<set _slGender = $bodyParts.gender>> <<set _slChest = $bodyParts.chest>> <<set _slButt = $bodyParts.butt>> <<set _slGen = $bodyParts.genitals>> <<set _slSkin = $appearance.skinTone>> <<set _slHairC = ($appearance.hairColor || "dark").toLowerCase()>> <<set _slHairS = $appearance.hairStyle>> <<set _slHairLen = (_slHairS === "long") ? "long " : ((_slHairS === "short") ? "short " : "")>> <<set _slChestW = (_slChest === "flat masculine" || _slChest === "flat") ? "flat" : ((_slChest === "small") ? "modest" : ((_slChest === "medium") ? "soft" : ((_slChest === "large") ? "full" : "heavy")))>> <<set _slButtW = (_slButt === "flat masculine" || _slButt === "flat") ? "slim" : ((_slButt === "small") ? "trim" : ((_slButt === "medium") ? "round" : ((_slButt === "large") ? "plush" : "ample")))>> <style> @keyframes slFade{from{opacity:0;transform:translateY(12px);}to{opacity:1;transform:translateY(0);}} .sl-fade{animation:slFade 1.6s ease-in forwards;} @keyframes slGlow{0%{box-shadow:0 0 18px rgba(70,150,255,0.3);}50%{box-shadow:0 0 60px rgba(70,150,255,0.65);}100%{box-shadow:0 0 18px rgba(70,150,255,0.3);}} </style> <div style="background:#040a16;min-height:100vh;padding:24px 20px;color:#dfe;max-width:680px;margin:0 auto;"> <div class="sl-fade" style="padding:6px 0;"> <p style="font-size:17px;line-height:1.75;">The lid hisses down and seals you in. For one breath the tube is dry and silent around you. Then jets cough to life below your feet and warm blue fluid pumps in fast, climbing your <<print _slSkin>> skin, swallowing your ankles, your thighs, pouring up into the dip of your waist. It is not cold and it is not water. It moves with intent, and it goes straight for the soft, secret places, sliding into every crease at once until your breath stutters and your knees go weak.</p> </div> <<timed 3s>><div class="sl-fade" style="padding:6px 0;"> <p style="font-size:17px;line-height:1.75;">The blue swallows you to the chest and you moan helplessly, because it is everywhere. It laps between your thighs, pools against your sex, slides slick over your nipples until they stiffen and ache. It is like being touched by a dozen warm, eager tongues that already know exactly how you like it. Your skin starts to give under the attention, softening, the edges of you turning slick and translucent blue. Your <<print _slHairLen>>hair fans out and unravels strand by strand, the <<print _slHairC>> bleeding away into the glow, and you are panting now, hips rolling against nothing, shamefully eager for whatever comes next.</p> </div><</timed>> <<timed 6.5s>><div class="sl-fade" style="padding:6px 0;"> <p style="font-size:17px;line-height:1.75;">Then the melt reaches your sex and the pleasure turns blinding. <<if _slGen === "both">>Your cock goes rock hard and your pussy clenches desperate around the warmth, both of them spasming at once, and then the slime takes them together in a single shattering flood of release that pours straight out of you into the blue.<<elseif _slGen.includes("penis")>>Your cock throbs once, twice, achingly stiff, and then the slime closes around it and it melts mid orgasm, the head dissolving in a white hot rush of bliss that whites out your vision and tears a cry from your throat.<<else>>Your pussy clenches and gushes around the slick intrusion, slick and greedy and right on the edge, and then it dissolves mid orgasm, the pleasure pouring out of you and into the warm blue until there is nothing left to clench.<</if>> Your <<print _slChestW>> chest and your <<print _slButtW>> rear smear into the same hungry heat, and you are cumming and coming apart at the same time, melting like wax in the arms of a lover. Whatever you were before, every last solid inch of you runs together in the blue.</p> </div><</timed>> <<timed 10s>><div class="sl-fade" style="padding:6px 0;"> <p style="font-size:17px;line-height:1.75;">For a long, floating moment you are nothing but a scattered blue cloud of yourself, every particle still twitching with aftershocks. Then the slime decides it wants you back, and it gathers you, kneading and pressing, dragging your scattered self into one dense, dripping knot. And where it presses, it builds you bigger. Your hips crack wide and flare. Your waist nips in sharp. Something swells up out of your chest and keeps swelling, round and heavy and full, soft new nipples forming hard and oversensitive at the peaks.</p> </div><</timed>> <<timed 13.5s>> <<run setup.applyFullTransformation("Slime")>> <<run $physicalTraits.delete("slime")>> <<set $slimeTubeBroken = true>> <div class="sl-fade" style="padding:6px 0;text-align:center;"> <p style="font-size:17px;line-height:1.75;text-align:left;">You come back together and open eyes that are not quite your own. You are translucent blue from your toes to the wet shine of your hair, glossy and soft and obscenely bouncy. Your new breasts sit huge and heavy and jiggling on your chest, your hips a wide slick weight, and between your thighs a needy new pussy drips clear blue down the inside of your leg. Every part of you is a busty, gluey handful, and every part of you is buzzing for more. Then the gremlin glee floods in, bright and loose and feral. <i>heheh... look at these TITS... I am all squishy and slippery and so, so wet... I wanna touch EVERYTHING...</i></p> <img src="Images/Transformation/Slime_Female.webp" style="max-width:300px;width:80%;height:auto;border-radius:12px;margin-top:8px;animation:slGlow 3s ease-in-out infinite;"> </div> <</timed>> <<timed 17s>><div class="sl-fade" style="padding:6px 0;"> <p style="font-size:17px;line-height:1.75;">The tube cannot hold you, and honestly, why should it. You grind your slick new body against the glass, still shivering and overstimulated, then plant both gooey hands flat and shove. The cylinder cracks, spiderwebs, then bursts in a warm blue wave, and you pour out across the lab floor with a wet, delighted slap before reforming on your feet, giggling. You bounce your own ridiculous new tits in both hands just to feel them wobble, snicker, and cast around the lab for something to poke, something to squeeze, something to get into. You have become a Slime Girl. Busty, blue, dripping wet, and absolutely full of mischief.</p> <div style="text-align:center;margin-top:18px;"> <<link "<div style='display:inline-block;background:linear-gradient(135deg,#3a7ad0 0%,#7fb8ff 100%);color:#04122a;padding:12px 26px;border-radius:8px;cursor:pointer;font-weight:bold;'>Peel yourself off the floor</div>">> <<goto "OvergrownLab">> <</link>> </div> </div><</timed>> </div> <</if>> <</nobr>>
<<nobr>> <style>@keyframes tcpFade{from{opacity:0;}to{opacity:1;}}.tcp{animation:tcpFade 1.6s ease-in forwards;}</style> <div style="background:#000;min-height:100vh;padding:60px 20px;text-align:center;"> <div class="tcp"><p style="color:#3a4452;font-size:18px;">The white goes whiter. The ground tips sideways and slides out from under you...</p></div> <<timed 2.6s>> <div class="tcp"><p style="color:#4a5563;font-size:18px;">...</p></div> <</timed>> <<timed 4.6s>> <div class="tcp"> <p style="color:#8a97a8;font-size:17px;line-height:1.7;">You wake on the floor of the Nest, stiff and aching, with no memory of how you got back.</p> <div style="margin-top:24px;"><<link "<div style='display:inline-block;background:linear-gradient(135deg,#8B9DAF 0%,#6a7a8a 100%);color:white;padding:14px 36px;border-radius:10px;cursor:pointer;font-weight:bold;'>Sit up</div>">><<goto "The Nest">><</link>></div> </div> <</timed>> </div> <</nobr>>
<<nobr>> <<set _preChest = $bodyParts.chest>> <<set _preGenitals = $bodyParts.genitals>> <<set _preGender = $bodyParts.gender>> <<set _preHair = String($appearance.hairColor)>> <<set _preSkin = String($appearance.skinTone)>> <<set _hadBreasts = ["small","medium","large","huge","giant","gigantic"].includes(_preChest)>> <<set _hadVagina = String(_preGenitals).indexOf("vagina") !== -1>> <<if !$physicalTraits.includes("Femboy")>><<run $physicalTraits.push("Femboy")>><</if>> <<run setup.applyTransformationSilent("Femboy")>> <<set $activeTransformation = "Femboy">> <<set _femboyReturn = $lastLocation || "The Nest">> <div style="background: linear-gradient(180deg, #0d0015 0%, #1a0a2e 30%, #2d1052 50%, #1a0a2e 70%, #0d0015 100%); min-height: 100vh; padding: 20px;"> <div style="max-width: 800px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 20px;"> <h1 style="color: #e08bd8; font-size: 42px; margin: 0; text-shadow: 0 0 30px #e08bd8, 0 0 60px #8b5cb8;">🔮 TRANSFORMATION 🔮</h1> </div> <div style="background: linear-gradient(135deg, #8b5cb8 0%, #d96bd9 50%, #8b5cb8 100%); padding: 30px; border-radius: 15px; margin-bottom: 30px; box-shadow: 0 0 40px rgba(139,92,184,0.6), inset 0 0 30px rgba(255,255,255,0.1); border: 2px solid #e08bd8; text-align: center;"> <p style="color: #f3d9ff; margin: 0 0 10px 0; font-size: 18px; text-transform: uppercase; letter-spacing: 2px;">You have become</p> <p style="color: white; font-size: 48px; font-weight: bold; margin: 0; text-shadow: 0 0 20px rgba(255,255,255,0.8), 0 4px 8px rgba(0,0,0,0.5);">Femboy</p> </div> <h2 style="color: #e08bd8; margin: 0 0 20px 0; text-align: center; font-size: 24px;">✨ The Transformation Begins ✨</h2> <p style="color: #e8d5f0; font-size: 16px; line-height: 1.8;">You feel the seventh can meet your lips, the cold fizz turning to warmth the instant it touches your tongue. You feel it slide down and pool low in your belly, then sink lower still, and a shiver of want runs through you as it starts. Heat blooms under your skin, and you feel your body let go and begin to remake itself.</p> <div style="background: rgba(255,107,157,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ff6b9d;"> <p style="margin: 0 0 8px 0;"><strong style="color: #ff6b9d; font-size: 18px;">💗 Chest</strong></p> <p style="color: #e8d5f0; font-size: 15px; line-height: 1.7; margin: 0;"><<if _hadBreasts>>You feel your <<print _preChest>> breasts soften and shrink, the weight of them melting down flat against your ribs until there is nothing left but a smooth, trim, boyish chest. You feel your nipples stiffen in the cool air, more sensitive than they have ever been.<<else>>You feel your already flat chest stay smooth and boyish, and you feel your nipples tighten and go sensitive as the heat rolls through you.<</if>></p> </div> <div style="background: rgba(255,107,53,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #ff6b35;"> <p style="margin: 0 0 8px 0;"><strong style="color: #ff6b35; font-size: 18px;">🔥 Intimate Areas</strong></p> <p style="color: #e8d5f0; font-size: 15px; line-height: 1.7; margin: 0;"><<if _hadVagina>>You feel the slick heat between your legs gather and reshape. You feel your pussy draw up and push outward as a soft cock takes its place, and you feel it fill and stiffen almost at once, twitching as a flood of new nerves lights up. You feel a snug pair of balls settle warm beneath, and you gasp at how good the ache of it feels. You feel your new cock standing flushed and eager against your belly.<<else>>You feel your cock stir and harden, the change pouring through it like a current until you feel it standing stiff and flushed against your slim new belly. You feel your balls draw up tight, and the pleasure of it leaves you breathless.<</if>> You feel your sex lock into a boyish masculine shape, aching and ready, and you know it cannot be traded away while the bloom holds.</p> </div> <div style="background: rgba(216,180,240,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #c79be8;"> <p style="margin: 0 0 8px 0;"><strong style="color: #c79be8; font-size: 18px;">💜 Hair & Skin</strong></p> <p style="color: #e8d5f0; font-size: 15px; line-height: 1.7; margin: 0;">You feel the <<print _preHair.toLowerCase()>> drain from your hair strand by strand and flood back as a soft light purple that catches the light like petals. You feel your <<print _preSkin>> skin cool and lighten to a smooth, pale, fair glow, and you feel every inch of it left newly sensitive and warm.</p> </div> <div style="background: rgba(155,89,182,0.1); padding: 20px; border-radius: 10px; margin-bottom: 20px; border-left: 4px solid #9b59b6;"> <p style="margin: 0 0 8px 0;"><strong style="color: #9b59b6; font-size: 18px;">✨ Identity</strong></p> <p style="color: #e8d5f0; font-size: 15px; line-height: 1.7; margin: 0;">You feel your shoulders draw in, your waist cinch, and your hips round into a gentle sway. You feel yourself settle as a boy, soft and pretty and fully adult, a femboy from head to toe, your cock hard and your cheeks flushed.</p> </div> <<if !$imageSettings>><<set $imageSettings = {imagesEnabled: true, eroticImagesEnabled: true}>><</if>> <<if $imageSettings.eroticImagesEnabled !== false>> <div style="text-align: center; margin-bottom: 30px;"> <h3 style="color: #e08bd8; margin-bottom: 20px;">Your New Form</h3> <div style="display: inline-block; padding: 5px; background: linear-gradient(135deg, #b07fd0 0%, #8b5cb8 100%); border-radius: 12px; border: 3px solid #b07fd0; box-shadow: 0 0 20px rgba(176,127,208,0.5);"> <img src="Images/Transformation/Femboy.webp" alt="Femboy" style="max-width: 450px; max-height: 600px; border-radius: 8px; display: block;" onerror="this.parentElement.parentElement.style.display='none';"> </div> </div> <</if>> <p style="color: #f0d4ff; font-size: 18px; line-height: 1.8; text-align: center; margin-bottom: 24px;">You stand there fully changed. You feel the flat boyish chest, the stiff cock and balls between your legs, the soft light purple hair, the smooth pale skin, and the adult male body locked femboy through and through. You feel flushed, hard, and aching, every part of you newly sensitive. You have become a femboy.</p> <div style="text-align: center; margin-top: 20px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #8b5cb8 0%, #4a2d6b 100%); color: white; padding: 15px 40px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 18px; box-shadow: 0 0 20px rgba(139,92,184,0.5); border: 2px solid #c79be8;'>Continue</div>">> <<goto _femboyReturn>> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<if !(setup.slime.isPlayerSlimeBodied() || $slimePossessionActive)>> <<goto "Inventory">> <<else>> <div style="max-width: 760px; margin: 0 auto; padding: 16px;"> <h2 style="color: #51e0a8; margin-top: 0;">🫧 Slime Powers</h2> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #51e0a8; margin-bottom: 14px;"> <div style="color: #51e0a8; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Stored Slime</div> <div style="color: #d6f5e8; font-size: 22px; font-weight: bold;"><<= $slimeStored>> <span style="color:#6a7a8a; font-size:15px;">/ <<= $slimeStorageMax>></span></div> <div style="height: 8px; background: #0d0d1a; border-radius: 5px; overflow: hidden; margin-top: 8px;"><div style="height:100%; width: <<= Math.min(100, Math.round(($slimeStored / Math.max(1,$slimeStorageMax)) * 100))>>%; background: linear-gradient(90deg, #2bb583, #6effc0);"></div></div> </div> <<if setup.slime.isPlayerSlimeBodied()>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #51e0a8; margin-bottom: 14px;"> <div style="color: #51e0a8; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Reshape Yourself</div> <div style="color:#9aa7b5; font-size:11px; margin-bottom:8px;">Chest <span style="color:#5a6a7a;">(now <<= $bodyParts.chest>>)</span></div> <div style="display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px;"><<for _s range setup.chestSizeOrder>><<capture _s>><<link "<div style='background: linear-gradient(135deg, #2bb583, #6effc0); color: #06281e; padding: 7px 14px; border-radius: 8px; font-weight: bold; cursor: pointer; font-size:13px;'><<= _s>></div>">><<run setup.slime.setOwnChest(_s)>><<goto "SlimePanel">><</link>><</capture>><</for>></div> <div style="color:#9aa7b5; font-size:11px; margin-bottom:8px;">Butt <span style="color:#5a6a7a;">(now <<= $bodyParts.butt>>)</span></div> <div style="display:flex; flex-wrap:wrap; gap:8px; margin-bottom:10px;"><<for _s range setup.buttSizeOrder>><<capture _s>><<link "<div style='background: linear-gradient(135deg, #2bb583, #6effc0); color: #06281e; padding: 7px 14px; border-radius: 8px; font-weight: bold; cursor: pointer; font-size:13px;'><<= _s>></div>">><<run setup.slime.setOwnButt(_s)>><<goto "SlimePanel">><</link>><</capture>><</for>></div> <div style="color:#9aa7b5; font-size:11px; margin-bottom:8px;">Genitals <span style="color:#5a6a7a;">(now <<= $bodyParts.genitals>>)</span></div> <div style="display:flex; flex-wrap:wrap; gap:8px;"><<for _g range ["vagina","penis","both"]>><<capture _g>><<link "<div style='background: linear-gradient(135deg, #2bb583, #6effc0); color: #06281e; padding: 7px 14px; border-radius: 8px; font-weight: bold; cursor: pointer; font-size:13px;'><<= _g>></div>">><<run setup.slime.setOwnGenitals(_g)>><<goto "SlimePanel">><</link>><</capture>><</for>></div> </div> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #2bb583; margin-bottom: 14px;"> <div style="color: #2bb583; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Thicken Your Mass</div> <<if $slimeStorageMax >= 1000>> <div style="color:#9aa7b5; font-size:13px;">Your mass cannot hold any more. Max 1000.</div> <<elseif $slimeStored >= 100>> <<link "<div style='display:inline-block; background: linear-gradient(135deg, #2bb583, #6effc0); color: #06281e; padding: 10px 20px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(43,181,131,0.5);'>Spend 100 slime for +100 capacity</div>">><<run setup.slime.upgradeCapacity()>><<goto "SlimePanel">><</link>> <<else>> <div style="color:#9aa7b5; font-size:13px;">Absorb more food. You need 100 stored slime to thicken your mass.</div> <</if>> </div> <</if>> <<if $slimePossessionActive>> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #e08bd8; margin-bottom: 14px;"> <div style="color: #e08bd8; font-size: 12px; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; letter-spacing: 1px;">Reshape This Body</div> <div style="color:#9aa7b5; font-size:12px; margin-bottom:10px;">Spend stored slime to sculpt the body you wear. The changes stay on them after you leave.</div> <div style="display:flex; flex-wrap:wrap; gap:10px;"> <<if $bodyParts.chest === "flat" || $bodyParts.chest === "flat masculine">> <<link "<div style='background: linear-gradient(135deg, #e08bd8, #f3c4ef); color: #2a0a26; padding: 10px 18px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(224,139,216,0.4);'>💗 Give breasts (30)</div>">><<run setup.slimePossession.giveBreasts()>><<goto "SlimePanel">><</link>> <<else>> <<set _ci = setup.chestSizeOrder.indexOf($bodyParts.chest)>> <<if _ci >= 0 && _ci < setup.chestSizeOrder.length - 1>> <<set _nc = setup.chestSizeOrder[_ci + 1]>> <<link "<div style='background: linear-gradient(135deg, #e08bd8, #f3c4ef); color: #2a0a26; padding: 10px 18px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(224,139,216,0.4);'>💗 Grow chest to <<= _nc>> (<<= setup.slime.SCULPT_COSTS[_nc]>>)</div>">><<run setup.slimePossession.growChest()>><<goto "SlimePanel">><</link>> <<else>> <div style="color:#9aa7b5; font-size:13px; align-self:center;">Chest maxed.</div> <</if>> <</if>> <<set _bi = setup.buttSizeOrder.indexOf($bodyParts.butt)>> <<if _bi >= 0 && _bi < setup.buttSizeOrder.length - 1>> <<set _nb = setup.buttSizeOrder[_bi + 1]>> <<link "<div style='background: linear-gradient(135deg, #e08bd8, #f3c4ef); color: #2a0a26; padding: 10px 18px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(224,139,216,0.4);'>🍑 Grow butt to <<= _nb>> (<<= setup.slime.SCULPT_COSTS[_nb]>>)</div>">><<run setup.slimePossession.growButt()>><<goto "SlimePanel">><</link>> <<else>> <div style="color:#9aa7b5; font-size:13px; align-self:center;">Rear maxed.</div> <</if>> <<link "<div style='background: linear-gradient(135deg, #e08bd8, #f3c4ef); color: #2a0a26; padding: 10px 18px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(224,139,216,0.4);'>⚧ Swap gender (100)</div>">><<run setup.slimePossession.swapGender()>><<goto "SlimePanel">><</link>> </div> </div> <<set _exitLoc = $slimePossessionBodyLocation || $lastLocation || "The Nest">> <div style="background: #1a1a2e; padding: 12px; border-radius: 10px; border-left: 4px solid #b5572b; margin-bottom: 14px;"> <<if $inRelationshipScene>><div style="color:#e6b09a; font-size:13px; line-height:1.5;">🚪 You cannot slip out of this body in the middle of an intimate moment. Finish what you are doing first.</div><<else>><<link "<div style='display:inline-block; background: linear-gradient(135deg, #b5572b, #e07a45); color: white; padding: 10px 22px; border-radius: 8px; font-weight: bold; cursor: pointer; box-shadow: 0 0 10px rgba(181,87,43,0.5);'>🚪 Exit this body</div>">><<run setup.slimePossession.revertSlimePossession()>><<goto _exitLoc>><</link>><</if>> </div> <</if>> <<set _backLoc = $lastLocation || "The Nest">> <<link "<div style='display:inline-block; background: #2a2a3e; color: #aab5c5; padding: 9px 20px; border-radius: 8px; cursor: pointer;'>Done</div>">><<goto _backLoc>><</link>> </div> <</if>> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _ii, _n range $npcs>><<if (_n.originalName || _n.name) === $slimeTargetName>><<set _npc = _n>><</if>><</for>> <<if !_npc>> <<goto "NPCInteraction">> <<else>> <<set _chance = setup.slimePossession.stealthChance()>> <<set _success = setup.slimePossession.rollStealth()>> <div style="background: linear-gradient(135deg, #0a1f1a 0%, #0d2e22 100%); min-height: 100vh; padding: 20px; color: #d6f5e8;"> <div style="max-width: 700px; margin: 0 auto;"> <h2 style="color: #51e0a8;">You ooze toward <<= _npc.name>></h2> <<if _success>> <p style="font-size:16px;line-height:1.8;">Silent and shapeless, you flow up behind them unseen. There is a gap, a parting of lips, a softer way in, and you pour yourself inside.</p> <div style="text-align:center;margin-top:18px;"><<link "<div style='display:inline-block;background:#2bb583;color:#06281e;padding:12px 28px;border-radius:8px;font-weight:bold;cursor:pointer;'>Slip inside them</div>">><<goto "SlimePossessEntry">><</link>></div> <<else>> <p style="font-size:16px;line-height:1.8;">You are a heartbeat too slow. <<= _npc.name>> turns, catches the wet shimmer of you, and recoils with a yelp. The moment is gone.</p> <<advancetime 15>> <<if $relationships[_npc.name]>><<set $relationships[_npc.name].points = ($relationships[_npc.name].points || 0) - 1>><</if>> <div style="text-align:center;margin-top:18px;"><<link "<div style='display:inline-block;background:#1a4d3e;color:#d6f5e8;padding:12px 28px;border-radius:8px;cursor:pointer;'>Back away</div>">><<goto "NPCInteraction">><</link>></div> <</if>> <p style="color:#5a7a6e;font-size:12px;margin-top:14px;">Sneak chance was <<= _chance>> percent.</p> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set _npc = null>> <<for _ii, _n range $npcs>><<if (_n.originalName || _n.name) === $slimeTargetName>><<set _npc = _n>><</if>><</for>> <<if _npc>><<run setup.slimePossession.applySlimePossession(_npc)>><</if>> <<set _loc = $slimePossessionBodyLocation || $lastLocation || "The Nest">> <div style="background: linear-gradient(135deg, #0a1f1a 0%, #0d2e22 100%); min-height: 100vh; padding: 20px; color: #d6f5e8;"> <div style="max-width: 700px; margin: 0 auto;"> <h1 style="color: #51e0a8; text-align: center;">🫧 Inside</h1> <p style="font-size:17px;line-height:1.8;">You spread thin and pour into the warm dark, filling every hollow until their body fits you like a glove. Their hands flex. Yours now. You wear them from the inside out, your slime curled snug behind their ribs.</p> <p style="font-size:17px;line-height:1.8;">You keep your own purse and your own coin, but their face, their name, and the shape of their life are yours to wear until you choose to slither free.</p> <div style="text-align:center;margin-top:20px;"><<link "<div style='display:inline-block;background:#2bb583;color:#06281e;padding:12px 28px;border-radius:8px;font-weight:bold;cursor:pointer;'>Continue</div>">><<goto _loc>><</link>></div> </div> </div> <</nobr>>
<<nobr>> <<set _back = $lastLocation || "The Nest">> <div style="background: linear-gradient(160deg, #06140f, #0a241a); min-height: 60vh; padding: 30px 16px; color: #d6f5e8; text-align:center;"> <div style="max-width: 560px; margin: 0 auto;"> <h2 style="color:#51e0a8;">🛧 Not in This Form</h2> <p style="font-size:16px; line-height:1.7;">A slime has no hands for a rod, no grip for a pick, no breath to hold for a dive. You will have to wear another body, or shed this one, before you can.</p> <div style="margin-top:18px;"><<link "<div style='display:inline-block;background:#163a2e;color:#aee5d0;padding:10px 24px;border-radius:8px;cursor:pointer;'>Back</div>">><<goto _back>><</link>></div> </div> </div> <</nobr>>
<<nobr>> <<if !$cerberusHeadNames>><<set $cerberusHeadNames = { left: "", right: "" }>><</if>> <<if $cerbLeftName === undefined>><<set $cerbLeftName = "">><</if>> <<if $cerbRightName === undefined>><<set $cerbRightName = "">><</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 40px 20px; color: #eee;"> <div style="max-width: 600px; margin: 0 auto; background: #2a2a2a; border: 3px solid #c0392b; border-radius: 12px; padding: 30px; box-shadow: 0 4px 8px rgba(0,0,0,0.5);"> <h1 style="color: #e74c3c; margin-top: 0; text-align: center;">Three Heads, Three Names</h1> <p style="color: #ccc; line-height: 1.5;">Your body has taken the shape of a Cerberus. Two new heads have risen beside your own. Your own head keeps the name $firstName. Name the other two. All three share the family name $lastName.</p> <div style="margin: 20px 0;"> <label style="color: #ccc; display: block; margin-bottom: 5px;">Left head's first name:</label> <<textbox "$cerbLeftName" "">> </div> <div style="margin: 20px 0;"> <label style="color: #ccc; display: block; margin-bottom: 5px;">Right head's first name:</label> <<textbox "$cerbRightName" "">> </div> <<if $cerberusNameMsg>><div style="color:#ff6b6b; text-align:center; margin-bottom:12px; font-weight:bold;"><<= $cerberusNameMsg>></div><</if>> <<link "<div style='background: linear-gradient(135deg, #c0392b 0%, #e74c3c 100%); color: white; padding: 14px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; font-size: 16px;'>Confirm Names</div>">> <<if $cerbLeftName && $cerbLeftName.trim() !== "" && $cerbRightName && $cerbRightName.trim() !== "">> <<set $cerberusHeadNames.left = $cerbLeftName.trim()>> <<set $cerberusHeadNames.right = $cerbRightName.trim()>> <<set $cerberusNamed = true>> <<set $cerberusNameMsg = "">> <<run setup.ensureCerberusHeads()>> <<set _dest = $cerberusReturnPassage || "The Nest">> <<goto _dest>> <<else>> <<set $cerberusNameMsg = "Please name both heads.">> <<goto "CerberusNaming">> <</if>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.prostitute.injectCSS()>> <<set _client = $prostCurrentClient>> <<set _pCenter = setup.getCerberusHeadPersona("center")>> <<set _pLeft = setup.getCerberusHeadPersona("left")>> <<set _pRight = setup.getCerberusHeadPersona("right")>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a28 50%, #2a0a1f 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div class="prost-fade" style="background: rgba(20, 10, 30, 0.85); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #c93068; box-shadow: 0 0 30px rgba(201,48,104,0.35);"> <h3 style="color: #c93068; text-align: center; margin-bottom: 15px;">🐺 Cerberus: Three Mouths, One Hunger</h3> <<set _them = _client.gender === "female" ? "her" : (_client.gender === "male" ? "him" : "them")>> <<set _they = _client.gender === "female" ? "she" : (_client.gender === "male" ? "he" : "they")>> <<set _their = _client.gender === "female" ? "her" : (_client.gender === "male" ? "his" : "their")>> <p class="prost-prose"><<= _client.name>> stops mid-sentence when the three of you turn toward <<= _them>> at once, three sets of eyes catching the low light from three necks that share one warm body. For a moment <<= _they>> just breathes, pulse jumping at the throat, caught somewhere between nerves and a hunger that wins out fast. "All three of you," <<= _they>> manages. "Together." It is not a question, and none of you intend to answer it with words.</p> <p class="prost-prose prost-fade-delay1"><span @style="'color: ' + _cCenter + ';'"><<if _pCenter.dominant>><<print _nCenter>> takes <<= _them>> by the jaw and tips <<= _them>> up, voice low and certain. "You came for a good time. We are going to ruin you for anyone else."<<elseif _pCenter.flirty>><<print _nCenter>> leans in with a slow, knowing smile, lips brushing close enough to feel. "Three mouths, sweetheart. Try to keep up."<<elseif _pCenter.professional>><<print _nCenter>> meets <<= _them>> with calm, unhurried confidence, hands settling at <<= _their>> waist. "Relax. We know exactly what we are doing."<<else>><<print _nCenter>> draws <<= _them>> in close and warm, breath ghosting over <<= _their>> skin. "There you are. We have got you."<</if>></span> <span @style="'color: ' + _cLeft + ';'"><<if _pLeft.bitchy>><<print _nLeft>> smirks against <<= _their>> ear, all teeth and impatience. "Do not just stand there. You wanted us."<<elseif _pLeft.energetic>><<print _nLeft>> is already nipping eager little kisses down <<= _their>> neck, restless and grinning. "Come on, come on, this is going to be so good."<<elseif _pLeft.confident>><<print _nLeft>> drags a slow line along <<= _their>> collarbone with quiet certainty. "You are in very good hands."<<else>><<print _nLeft>> tilts toward <<= _them>> with a teasing flick of the tongue. "Hello, gorgeous."<</if>></span></p> <p class="prost-prose prost-fade-delay2"><span @style="'color: ' + _cRight + ';'"><<if _pRight.submissive>><<print _nRight>> presses softer kisses to the other side of <<= _their>> throat, shy but eager, lashes low. "Is this okay? Tell us if it is too much."<<elseif _pRight.kind>><<print _nRight>> soothes a warm hand down <<= _their>> spine, gentling the tremor out of <<= _them>>. "Easy. Let us take care of you."<<elseif _pRight.awkward>><<print _nRight>> fumbles a kiss to <<= _their>> cheek first, then laughs and finds <<= _their>> mouth properly. "Sorry, three of us is a lot to coordinate."<<else>><<print _nRight>> brushes a flirty, lingering kiss to the corner of <<= _their>> jaw. "Do not worry. We share beautifully."<</if>></span> Three sets of lips, three different rhythms working <<= _them>> at once, and <<= _client.name>> sags back into the shared warmth of your body with a shudder, already past the point of turning back.</p> </div> <div class="prost-fade-delay3" style="text-align: center; margin-top: 20px;"> <<link "<div class='prost-btn' style='background: linear-gradient(135deg, #c93068, #ffd700); color: #1a0a2e; border: none; padding: 14px 28px; border-radius: 10px; font-size: 16px; font-weight: bold; cursor: pointer; display: inline-block;'>Begin...</div>">> <<set $prostSatisfaction += 20>> <<goto "ProstServiceSelect">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<run setup.ensureCerberusHeads()>> <<set $lastLocation = "CerberusSelfMakeout">> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a28 50%, #2a0a1f 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div style="background: rgba(20, 10, 30, 0.85); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #c77dff; box-shadow: 0 0 30px rgba(199,125,255,0.35);"> <h3 style="color: #c77dff; text-align: center; margin-bottom: 15px;">💋 Three Mouths, One Body</h3> <p>You lock the bedroom door and lean back against it. Alone at last, with no one to keep up appearances for. On their three necks your heads turn toward one another, and the same idea lands in all of you at once. A slow grin spreads across all three mouths.</p> <p style="text-align: center; color: #c9a9ff; margin-top: 18px;">Which mouth leans in first?</p> <div style="display: flex; flex-direction: column; gap: 12px; margin-top: 12px;"> <<link "<div style='background: #ffd700; color: #1a0a2e; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'><<print _nCenter>> leans in</div>">><<set $cerbMakeoutLead = "center">><<goto "CerberusSelfMakeoutFinish">><</link>> <<link "<div style='background: #c93068; color: white; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'><<print _nLeft>> leans in</div>">><<set $cerbMakeoutLead = "left">><<goto "CerberusSelfMakeoutFinish">><</link>> <<link "<div style='background: #c77dff; color: #1a0a2e; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'><<print _nRight>> leans in</div>">><<set $cerbMakeoutLead = "right">><<goto "CerberusSelfMakeoutFinish">><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "CerberusSelfMakeoutFinish">> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a28 50%, #2a0a1f 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div style="background: rgba(20, 10, 30, 0.85); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #c77dff; box-shadow: 0 0 30px rgba(199,125,255,0.35);"> <<switch $cerbMakeoutLead>> <<case "center">> <p><span @style="'color: ' + _cCenter + ';'"><<print _nCenter>> turns first</span>, the mouth that still wears your name, and catches <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>></span> in a slow kiss. <span @style="'color: ' + _cRight + ';'"><<print _nRight>></span> presses in close from the other side, unwilling to be left out, until all three of you are tangled together.</p> <<case "left">> <p><span @style="'color: ' + _cLeft + ';'"><<print _nLeft>> moves first</span>, bold and certain, and takes <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>></span> by the jaw to kiss her properly. <span @style="'color: ' + _cRight + ';'"><<print _nRight>></span> leans in to taste the side of your throat, and the warmth pools low in your shared belly.</p> <<case "right">> <p><span @style="'color: ' + _cRight + ';'"><<print _nRight>> leans in first</span>, soft and searching, and brushes her mouth over <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>></span>. <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>></span> growls a laugh and joins from the other side, and the three of you melt into each other.</p> <</switch>> <p style="text-align: center; color: #c9a9ff; margin-top: 18px;">How do you finish?</p> <div style="display: flex; flex-direction: column; gap: 12px; margin-top: 12px;"> <<link "<div style='background: #2a1a3a; color: #e0d0f0; border: 1px solid #c77dff; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>Slow and tender</div>">><<set $cerbMakeoutFinish = "gentle">><<goto "CerberusSelfMakeoutClimax">><</link>> <<link "<div style='background: #2a1a3a; color: #e0d0f0; border: 1px solid #c93068; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>Rough and hungry</div>">><<set $cerbMakeoutFinish = "rough">><<goto "CerberusSelfMakeoutClimax">><</link>> <<link "<div style='background: #2a1a3a; color: #e0d0f0; border: 1px solid #ffd700; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; cursor: pointer;'>All three at once</div>">><<set $cerbMakeoutFinish = "together">><<goto "CerberusSelfMakeoutClimax">><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "CerberusSelfMakeoutClimax">> <<if typeof setup.satisfySlutSexualNeeds === "function">><<run setup.satisfySlutSexualNeeds()>><</if>> <<if typeof setup.satisfyCheshireCatSexualNeeds === "function">><<run setup.satisfyCheshireCatSexualNeeds()>><</if>> <<if $physicalTraits.includes("Honeybee")>><<set $honeyInventory = ($honeyInventory || 0) + 1>><</if>> <<set _nLead = setup.getCerberusHeadName($cerbMakeoutLead)>> <<set _cLead = setup.cerberusHeadColors[$cerbMakeoutLead]>> <<set _nCenter = setup.getCerberusHeadName("center")>> <<set _nLeft = setup.getCerberusHeadName("left")>> <<set _nRight = setup.getCerberusHeadName("right")>> <<set _cCenter = setup.cerberusHeadColors.center>> <<set _cLeft = setup.cerberusHeadColors.left>> <<set _cRight = setup.cerberusHeadColors.right>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a28 50%, #2a0a1f 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div style="background: rgba(20, 10, 30, 0.85); border-radius: 15px; padding: 25px; max-width: 650px; margin: 20px auto; border: 2px solid #c77dff; box-shadow: 0 0 30px rgba(199,125,255,0.35);"> <<switch $cerbMakeoutFinish>> <<case "gentle">> <p>You take it slow. <span @style="'color: ' + _cLead + ';'"><<print _nLead>></span> sets the pace, unhurried and deep, while the other two trade soft kisses along your shared jaw and throat. The pleasure builds in long, gentle waves until your whole body shivers through a quiet, shared release, and the three of you breathe out together.</p> <<case "rough">> <p>You do not hold back. <span @style="'color: ' + _cLead + ';'"><<print _nLead>></span> kisses you hard and greedy, and the other two answer in kind, biting and panting, three mouths fighting for the same heat. It crashes over all of you at once, sharp and overwhelming, and you ride it out shaking against the door.</p> <<case "together">> <p>You stop choosing and simply let go. <span @style="'color: ' + _cCenter + ';'"><<print _nCenter>></span>, <span @style="'color: ' + _cLeft + ';'"><<print _nLeft>></span> and <span @style="'color: ' + _cRight + ';'"><<print _nRight>></span> move as one, perfectly in time, and when the peak hits it hits all three of you in the same instant. You cry out in a ragged chorus and sag, boneless and satisfied.</p> <</switch>> <div style="background: #1a1a1a; padding: 16px; border-radius: 10px; margin: 18px 0;"><p style="color: #51cf66; margin: 0;">✓ Feeling satisfied</p></div> <<run advanceTime(25)>> <div style="text-align: center;"> <<link "<div style='display: inline-block; background: #667eea; color: white; padding: 12px 30px; border-radius: 8px; font-weight: bold; cursor: pointer;'>Clean up and continue</div>">><<goto `setup.getCurrentHome()`>><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoWolfStatue">> <<set _alt = setup.cerberusAltar>> <<if !_alt.hasHeat()>> <div style="background: linear-gradient(135deg, #1a0500 0%, #2a0a00 100%); min-height: 100vh; padding: 20px; color: #ffd0c0;"> <div style="max-width: 640px; margin: 20px auto; padding: 24px; background: rgba(30,8,0,0.85); border: 2px solid #ff5722; border-radius: 14px;"> <h2 style="color: #ff8a65; text-align: center;">Too Hot to Approach</h2> <p>The instant you step toward the statue the heat slams into you like a wall, searing and immediate. Without some way to bear it you cannot get anywhere near the stone.</p> <div style="text-align:center; margin-top:18px;"><<link "<div style='display:inline-block; background:#667eea; color:white; padding:12px 28px; border-radius:8px; font-weight:bold;'>Back away</div>">><<goto "Volcano">><</link>></div> </div></div> <<elseif _alt.isComplete() && _alt.isFullMoonNight() && _alt.canFeed()>> <<set $cerberusAltarPrimed = true>> <<goto "CerberusTransformation">> <<else>> <div style="background: linear-gradient(135deg, #0d0015 0%, #1a0a28 50%, #2a0a1f 100%); min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #e0d0f0;"> <div style="max-width: 680px; margin: 20px auto; padding: 25px; background: rgba(20,10,30,0.85); border: 2px solid #c77dff; border-radius: 15px; box-shadow: 0 0 30px rgba(199,125,255,0.35);"> <h2 style="color: #c77dff; text-align: center; margin: 0 0 14px 0;">The Broken Wolf</h2> <p>The headless wolf waits in the shimmering heat, its chest and skull long gone. Fourteen runes ring its base, most of them cold and dark. Worn into the stone beneath them, words wait to be read.</p> <div style="background: #120820; border-left: 3px solid #c77dff; padding: 14px 18px; margin: 16px 0; font-style: italic; color: #d8c8f0; line-height: 1.7;"> Headless I wait where the mountain bleeds fire.<br>A wolf I was. Make me whole and I will make you more than one.<br>Wear your hide while you feed me, or I will not stir.<br><br> Twice, the self that no grave can keep.<br>Then three more truths of you: the heart that wears no leash, the furnace where your blood should be, and the twin that answers you from glass.<br><br> From the deep, four fish: one that swims like sickness, one that is all bone, one whose very name is severity, and one that swims as fear.<br>From the world, five wonders: a flame asleep in stone, a stare like a striped cat, a fruit that tastes of wanting, a thing too strange to name, and a shard of a drowned god.<br><br> Light every mark, and three heads will wake as one. But not by daylight, and not beneath a lesser moon. Come to me when the moon is full and the sun is drowned, and only then will I rise. </div> <p style="text-align:center; color:#c9a9ff;">Runes alight: <<print _alt.litCount()>> / <<print _alt.TOTAL_RUNES>></p> <div style="display:flex; flex-wrap:wrap; gap:6px; justify-content:center; margin:10px 0 18px 0;"> <<for _i = 0; _i < _alt.litCount(); _i++>><span style="font-size:20px;">🔥</span><</for>> <<for _i = 0; _i < (_alt.TOTAL_RUNES - _alt.litCount()); _i++>><span style="font-size:20px; opacity:0.25;">◯</span><</for>> </div> <<if $cerberusAltarMsg>> <div style="background:#2a1020; border:1px solid #c93068; border-radius:8px; padding:10px 14px; margin-bottom:16px; text-align:center; color:#ffb0c8; font-style:italic;"><<print $cerberusAltarMsg>></div> <<set $cerberusAltarMsg = "">> <</if>> <<if _alt.isComplete()>> <div style="background:#1a0a28; border:1px solid #c77dff; border-radius:8px; padding:14px; text-align:center; color:#c77dff;">Every rune burns, yet the stone stays cold and still. It waits for the beast to stand before it when the moon is full and the sun is drowned.</div> <<elseif !_alt.canFeed()>> <div style="background:#1a0a28; border:1px solid #c93068; border-radius:8px; padding:14px; text-align:center; color:#ffb0c8; font-style:italic;">Only the beast may feed me. Come back wearing your hide.</div> <<else>> <h3 style="color:#ffd700; border-bottom:1px solid #4a3a1a; padding-bottom:6px;">Imbue a piece of yourself</h3> <div style="display:flex; flex-wrap:wrap; gap:8px; margin-bottom:18px;"> <<for _t range _alt.offerableTraits()>> <<capture _t>> <<set _btn = "<div style='background:#2a1a3a; border:1px solid #ffd700; color:#ffd700; padding:6px 12px; border-radius:6px; cursor:pointer;'>" + _t + "</div>">> <<link _btn>> <<set _res = _alt.imbueTrait(_t)>> <<if _res === "accepted">><<set $cerberusAltarMsg = "The stone drinks it from you. A rune flares to life.">><<else>><<set $cerberusAltarMsg = _alt.hint("trait")>><</if>> <<goto "VolcanoWolfStatue">> <</link>> <</capture>> <</for>> </div> <h3 style="color:#51cf66; border-bottom:1px solid #1a4a2a; padding-bottom:6px;">Lay an offering at its base</h3> <div style="display:flex; flex-wrap:wrap; gap:8px;"> <<for _it range _alt.offerableItems()>> <<capture _it>> <<set _btn = "<div style='background:#1a2a1a; border:1px solid #51cf66; color:#a8e6a0; padding:6px 12px; border-radius:6px; cursor:pointer;'>" + _it.name + "</div>">> <<link _btn>> <<set _res = _alt.sacrificeItem(_it.id)>> <<if _res === "accepted">><<set $cerberusAltarMsg = "The flames take it. A rune flares to life.">><<else>><<set $cerberusAltarMsg = _alt.hint("item")>><</if>> <<goto "VolcanoWolfStatue">> <</link>> <</capture>> <</for>> </div> <</if>> <div style="text-align:center; margin-top:22px;"><<link "<div style='display:inline-block; background:#667eea; color:white; padding:12px 28px; border-radius:8px; font-weight:bold;'>Step back from the heat</div>">><<goto "Volcano">><</link>></div> </div></div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "CerberusTransformation">> <<run setup.applyFullTransformation("Cerberus")>> <<run setup.ensureCerberusHeads()>> <<set _pL = setup.getCerberusHeadPersona("left")>> <<set _pR = setup.getCerberusHeadPersona("right")>> <<set _cL = setup.cerberusHeadColors.left>> <<set _cR = setup.cerberusHeadColors.right>> <<set _fullBody = setup.getPlayerFullBodyImage()>> <style> @keyframes cerbLava { 0% { background-position: 50% 0%; } 100% { background-position: 50% 100%; } } @keyframes cerbBurn { 0%, 100% { box-shadow: 0 0 22px rgba(255,90,0,0.55), 0 0 55px rgba(255,40,0,0.4), inset 0 0 30px rgba(255,110,0,0.22); border-color: #ff5a1e; } 50% { box-shadow: 0 0 46px rgba(255,150,0,0.92), 0 0 100px rgba(255,70,0,0.6), inset 0 0 52px rgba(255,95,0,0.42); border-color: #ffc14d; } } @keyframes cerbGlow { 0%, 100% { text-shadow: 0 0 12px rgba(255,90,0,0.75), 0 0 26px rgba(255,40,0,0.5); } 50% { text-shadow: 0 0 24px rgba(255,150,0,0.95), 0 0 54px rgba(255,80,0,0.7); } } @keyframes cerbEmber { 0% { transform: translateY(0) scale(1); opacity: 0; } 12% { opacity: 0.9; } 100% { transform: translateY(-170px) scale(0.35); opacity: 0; } } @keyframes cerbPulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 0.9; } } .cerb-lava-bg { background: linear-gradient(180deg, #140300 0%, #3a0c00 22%, #6e1a00 46%, #a02c00 56%, #3a0c00 82%, #100200 100%); background-size: 100% 280%; animation: cerbLava 14s ease-in-out infinite alternate; position: relative; overflow: hidden; } .cerb-lava-bg::before { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 40%; background: radial-gradient(125% 95% at 50% 125%, rgba(255,95,0,0.6), rgba(255,45,0,0.18) 45%, transparent 70%); pointer-events: none; animation: cerbPulse 3.4s ease-in-out infinite; } .cerb-burn-box { animation: cerbBurn 2.6s ease-in-out infinite; position: relative; z-index: 2; } .cerb-burn-title { animation: cerbGlow 2.6s ease-in-out infinite; } .cerb-ember { position: absolute; bottom: -10px; width: 7px; height: 7px; border-radius: 50%; background: radial-gradient(circle, #ffe6a0 0%, #ff7a1a 55%, rgba(255,80,0,0) 72%); animation: cerbEmber linear infinite; pointer-events: none; z-index: 1; } </style> <div class="cerb-lava-bg" style="min-height: 100vh; padding: 20px; font-family: Georgia, serif; color: #f0d8c8;"> <div class="cerb-ember" style="left: 7%; animation-duration: 4.2s; animation-delay: 0s;"></div> <div class="cerb-ember" style="left: 21%; animation-duration: 5.3s; animation-delay: 1.1s;"></div> <div class="cerb-ember" style="left: 38%; animation-duration: 3.6s; animation-delay: 0.6s;"></div> <div class="cerb-ember" style="left: 55%; animation-duration: 4.9s; animation-delay: 1.8s;"></div> <div class="cerb-ember" style="left: 71%; animation-duration: 3.9s; animation-delay: 0.3s;"></div> <div class="cerb-ember" style="left: 88%; animation-duration: 5.6s; animation-delay: 2.3s;"></div> <div class="cerb-burn-box" style="max-width: 680px; margin: 20px auto; padding: 26px; background: rgba(24,8,4,0.9); border: 2px solid #ff5a1e; border-radius: 15px;"> <h2 class="cerb-burn-title" style="color: #ffb24d; text-align: center;">Three Heads, One Body</h2> <p>The last rune catches and the whole ring flares white hot. The broken wolf drinks it down and starts to build itself back, stone flowing up over the empty shoulders, and the heat pouring off the altar washes over your skin until every inch of you is flushed and slick and aching with it.</p> <p>The wolf turns toward you whole now, three muzzles where there were none, six eyes bright and fixed on you. It does not attack. It presses its newly made body flush against yours, chest to chest, and then it sinks into you, melting through your skin like molten metal poured into a mold. The feeling of it filling you is obscene. You gasp, knees buckling, heat blooming low in your belly and rolling outward in waves you cannot stop.</p> <p>Your wolf's body answers it, greedy for more. Your spine arches as two new necks push up from your shoulders, and the stretch of it, the sheer fullness, drags a moan out of all three of your heads at once. Two more heads rise beside your own and open their eyes, and the very first thing each of them feels is how good your shared body feels, lit up and trembling and desperate for it.</p> <p>You come apart standing there, all three mouths panting, and then it is over. The change settles in, warm and easy, and the body you are left with already feels like your own.</p> <p>For a long moment the three of you only breathe together, learning the weight of a shared spine, the strange new pull of looking in three directions at once. Then the new mouths find their voices.</p> <p><span @style="'color:'+_cL+';'"><<if _pL.dominant>>One of them speaks first, low and certain, already used to being obeyed. "So. This is what we are now. Good."<<elseif _pL.flirty>>One of them speaks first, a slow grin curling through the words. "Mmm. I am going to enjoy being more than one of you."<<elseif _pL.shy>>One of them speaks first, hushed and wide-eyed. "Oh. Oh, there is so much of us now. I can feel all of it."<<elseif _pL.bitchy>>One of them speaks first, sharp and satisfied. "Finally. Room enough for everything I deserve."<<elseif _pL.kind>>One of them speaks first, gentle and a little awed. "We are all right. We are all still here. All of us."<<else>>One of them speaks first, tasting the new words on a new tongue. "We are awake. We are here. We are real."<</if>></span></p> <p><span @style="'color:'+_cR+';'"><<if _pR.dominant>>The other answers at once, hungry and eager. "Then let us not waste a single night of it."<<elseif _pR.kind>>The other answers, warm and steadying. "Easy now. We are together, and we always will be."<<elseif _pR.flirty>>The other answers with a low, delighted laugh. "Three mouths. Think of everything we can do with three mouths."<<elseif _pR.bitchy>>The other answers, smug and unimpressed. "Do try to keep pace with me."<<elseif _pR.shy>>The other answers in a small voice, leaning into the others. "It is less frightening, knowing you are both here too."<<else>>The other answers, drinking in the shared body. "All of this. Every inch of it is ours now."<</if>></span></p> <p>Your own voice joins in, and the three of you talk over each other for a second before falling into an easy rhythm. It is a strange feeling, but not a bad one.</p> <div style="background:#2a0a06; border:1px solid #ff7a1a; border-radius:8px; padding:12px; text-align:center; color:#ffb24d; font-weight:bold; margin-top:16px; box-shadow:0 0 18px rgba(255,90,0,0.35);">Your Werewolf has become Cerberus.</div> <<if _fullBody>> <div style="text-align:center; margin-top:24px;"><h3 style="color:#ffb24d; margin-bottom:12px;">Your New Form</h3><div style="display:inline-block; padding:5px; border-radius:12px; border:3px solid #ff5a1e; box-shadow:0 0 30px rgba(255,95,0,0.55);"><img @src="_fullBody" style="max-width:430px; max-height:620px; border-radius:8px; display:block;" onerror="this.parentElement.parentElement.style.display='none';"></div></div> <</if>> <div style="text-align:center; margin-top:24px;"><<link "<div style='display:inline-block; background:#c93068; color:#ffffff; padding:12px 30px; border-radius:8px; font-weight:bold; box-shadow:0 0 16px rgba(201,48,104,0.5);'>Name your new heads</div>">><<set $cerberusReturnPassage = "Volcano">><<goto "CerberusNaming">><</link>></div> </div></div> <</nobr>>
<<nobr>> <<set $lastLocation = "DreamDimension">> <div class="dream-starfield" style="min-height: 100vh; padding: 20px;"> <h1 style="color: #a78bfa; text-align: center; text-shadow: 0 0 18px rgba(167,140,250,0.7); letter-spacing: 2px;">💤 Dream Dimension</h1> <div style="padding: 22px; background: linear-gradient(135deg, rgba(167,140,250,0.22) 0%, rgba(129,74,200,0.18) 100%); border-radius: 16px; margin: 0 auto 24px auto; max-width: 720px; border: 2px solid #a78bfa; box-shadow: 0 0 30px rgba(167,140,250,0.35);"> <p style="color: #e6dcff; font-size: 16px; line-height: 1.7; margin: 0; text-align: center;"> The ground is not ground. It is a pale drift of light that holds your weight only because it has decided to, and the sky is that same soft violet in every direction you turn. Islands of remembered places float at the edge of sight: a corner of a kitchen, a stretch of beach, a doorway you almost recognize. </p> </div> <h2 style="color: #CE93D8; margin: 0 auto 12px auto; max-width: 900px;">Company</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; max-width: 900px; margin: 0 auto 24px auto;"> <div style="border: 3px solid #a78bfa; border-radius: 10px; padding: 15px; background: #16102a; display: flex; flex-direction: column;"> <h3 style="color: #a78bfa; margin: 0 0 10px 0;">🌙 Clair</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">She is sitting on nothing in particular, watching you arrive the way a cat watches a door open.</p> <<set _clairNPC = setup.getNPC("Clair")>> <<if _clairNPC>> <<link "<div style='background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 12px 24px; border-radius: 10px; cursor: pointer; font-weight: bold; text-align: center; margin-top: 10px;'>Talk to Clair</div>">> <<goto "ClairDreamTalk">> <</link>> <</if>> </div> <<set _clairTraining = false>> <<if setup.witchSpells.trainingStepActive("Twinning") || setup.witchSpells.trainingStepActive("Lucid Rest") || setup.witchSpells.trainingStepActive("Entrancement")>><<set _clairTraining = true>><</if>> <<if _clairTraining>> <div style="border: 3px solid #4dabf7; border-radius: 10px; padding: 15px; background: #101a28; display: flex; flex-direction: column;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">🪄 Practice with Clair</h3> <p style="font-size: 14px; color: #aaa; margin: 0 0 10px 0; line-height: 1.4;">One session per spell per night. Time barely passes here, but the effort is real.</p> <<for _tsn range ["Twinning", "Lucid Rest", "Entrancement"]>> <<capture _tsn>> <<if setup.witchSpells.trainingStepActive(_tsn) && $spellTrainingDay[_tsn] !== $dayNumber>> <<set _plabel = "<div style='background: #1f4068; color: #cfe8ff; padding: 8px 14px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 6px;'>Practice " + _tsn + " (" + ($spellTraining[_tsn] || 0) + "/" + setup.witchSpells.DEFS[_tsn].sessions + ")</div>">> <<link _plabel>> <<if setup.witchSpells.canTap()>> <<set $practiceSpell = _tsn>> <<set $practiceReturn = "DreamDimension">> <<goto "SpellPractice">> <</if>> <</link>> <<elseif setup.witchSpells.trainingStepActive(_tsn)>> <div style='background: #12203a; color: #6c86a8; padding: 8px 14px; border-radius: 8px; text-align: center; margin-top: 6px;'>Practiced <<print _tsn>> tonight. Come back after a day.</div> <</if>> <</capture>> <</for>> </div> <</if>> </div> <h2 style="color: #CE93D8; margin: 0 auto 12px auto; max-width: 900px;">The Dream</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; max-width: 900px; margin: 0 auto 24px auto;"> <div style="border: 3px solid #6c5b8e; border-radius: 10px; padding: 15px; background: #141021;"> <h3 style="color: #b9a8dd; margin: 0 0 10px 0;">🪞 The Reflecting Pool</h3> <p style="font-size: 14px; color: #aaa; margin: 0; line-height: 1.4;">A still pool that does not show your face. It shows somewhere you have been: pier lights, the violet glow of the coven, snow coming down without a sound. It ripples when you look too long, as if it knows it is being watched back.</p> <<if $questData && $questData.active && $questData.active["clair_twinning"] && !$clairMemoryShared>> <div style="text-align: center; margin-top: 12px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 10px 20px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 13px;'>Draw up a memory for Clair</div>">><<if setup.witchSpells.canTap()>><<goto "DreamMemoryPool">><</if>><</link>></div> <</if>> </div> <div style="border: 3px solid #6c5b8e; border-radius: 10px; padding: 15px; background: #141021;"> <h3 style="color: #b9a8dd; margin: 0 0 10px 0;">🏝️ The Drifting Islands</h3> <p style="font-size: 14px; color: #aaa; margin: 0; line-height: 1.4;">Pieces of remembered places wander past like slow traffic. If you stand on one it carries you nowhere in particular, gently, and sets you down where you started. Clair says they are other people's favorite rooms.</p> </div> <<if $questData && $questData.active && $questData.active["clair_lucidrest"] && !$clairNightmareSoothed>> <div style="border: 3px solid #b03a5b; border-radius: 10px; padding: 15px; background: #1a0e14; grid-column: 1 / -1;"> <h3 style="color: #ff6b8a; margin: 0 0 10px 0;">🕳️ The Far Corner</h3> <p style="font-size: 14px; color: #d8b0bb; margin: 0 0 12px 0; line-height: 1.5;">Where the violet light thins to nothing, something is snarled. It has no single shape, only an array of sharp mouths and black tendrils knotted around itself, gnawing a dream that will not end. Clair keeps well back. "That is the one," she says softly. "I cannot touch it. It would only bite down harder."</p> <<set _divineFish = setup.playerHasTrait("Divine Sunfish")>> <<set _blessedFish = setup.playerHasTrait("Blessed") && setup.playerHasTrait("Sunfish")>> <<if _divineFish || _blessedFish>> <div style="text-align: center;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #ff6b8a 0%, #b03a5b 100%); color: white; padding: 10px 22px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 13px;'>Approach the nightmare</div>">><<if setup.witchSpells.canTap()>><<goto "DreamNightmareBanish">><</if>><</link>></div> <<else>> <p style="color: #cc9999; font-style: italic; font-size: 14px; margin: 0;">Clair studies you and shakes her head. "Not yet. To face this you must bear a fish blessed in holy light. Not a thing you can carry in your hand, but what you are. Come back when that light is in you."</p> <</if>> </div> <</if>> </div> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 13px 30px; border-radius: 10px; font-weight: bold; cursor: pointer; box-shadow: 0 0 18px rgba(167,140,250,0.55); letter-spacing: 1px;'>Wake up</div>">> <<set _wake = $dreamReturnPassage || "The Nest">> <<goto _wake>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<if !setup.witchSpells.isSpellcaster()>><<goto "The Nest">><</if>> <<set _prevPsg = previous()>> <<set _back = (_prevPsg && ["Spellbook", "GlamourSpell", "ClairTransformationScene", "SpellPractice", "DreamMemoryPool", "DreamNightmareBanish", "DreamFirstMeeting"].indexOf(_prevPsg) === -1) ? _prevPsg : ($lastLocation || "The Nest")>> <div style="background: radial-gradient(circle at 50% 20%, #1a0a2e 0%, #0d0518 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #e040fb; text-align: center; text-shadow: 0 0 15px rgba(224,64,251,0.6);">📖 Spellbook</h1> <div style="text-align: center; margin-bottom: 18px;"> <span style="color: #CE93D8; font-size: 15px;">Mana: <<print ($witchMana || 0) + " / " + ($witchManaMax || 100)>></span> </div> <<if $clairFirstMeetingDone>> <div style="text-align: center; margin-bottom: 18px;"> <<if $dreamwalkEnabled>> <<link "<span style='color: #a78bfa; border: 1px solid #a78bfa; border-radius: 8px; padding: 6px 14px; cursor: pointer;'>💤 Dreamwalk on sleep: ON</span>">><<if setup.witchSpells.canTap()>><<set $dreamwalkEnabled = false>><<goto "Spellbook">><</if>><</link>> <<else>> <<link "<span style='color: #666; border: 1px solid #666; border-radius: 8px; padding: 6px 14px; cursor: pointer;'>💤 Dreamwalk on sleep: OFF</span>">><<if setup.witchSpells.canTap()>><<set $dreamwalkEnabled = true>><<goto "Spellbook">><</if>><</link>> <</if>> </div> <</if>> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 15px; max-width: 900px; margin: 0 auto;"> <<set _spellNames = Object.keys(setup.witchSpells.DEFS)>> <<for _si = 0; _si < _spellNames.length; _si++>> <<set _sn = _spellNames[_si]>> <<set _sd = setup.witchSpells.DEFS[_sn]>> <<capture _sn, _sd>> <<if setup.witchSpells.knows(_sn)>> <div style="border: 2px solid #e040fb; border-radius: 10px; padding: 14px; background: #1c1028;"> <h3 style="color: #e040fb; margin: 0 0 8px 0;"><<print _sd.icon>> <<print _sn>></h3> <p style="color: #bba8cc; font-size: 13px; line-height: 1.4; margin: 0 0 10px 0;"><<print _sd.desc>></p> <<if _sn === "Glamour">> <<if ($witchMana || 0) >= 15>> <<link "<div style='background: #7b1fa2; color: white; padding: 8px 16px; border-radius: 8px; cursor: pointer; text-align: center;'>Cast (15 mana)</div>">> <<if setup.witchSpells.canTap()>> <<run setup.witchSpells.spendMana(15)>> <<goto "GlamourSpell">> <</if>> <</link>> <<else>> <div style="color: #666; text-align: center;">Not enough mana</div> <</if>> <<elseif _sn === "Lucid Rest">> <<if $lucidRestActive>> <div style="color: #a78bfa; text-align: center;">Active. Your next sleep will rest you fully at no time cost.</div> <<elseif ($witchMana || 0) >= 30>> <<link "<div style='background: #7b1fa2; color: white; padding: 8px 16px; border-radius: 8px; cursor: pointer; text-align: center;'>Cast (30 mana)</div>">> <<if setup.witchSpells.canTap()>> <<run setup.witchSpells.spendMana(30)>> <<set $lucidRestActive = true>> <<goto "Spellbook">> <</if>> <</link>> <<else>> <div style="color: #666; text-align: center;">Not enough mana</div> <</if>> <<elseif _sn === "Twinning">> <<if $clairFormActive>> <<link "<div style='background: #4a3760; color: white; padding: 8px 16px; border-radius: 8px; cursor: pointer; text-align: center;'>Return to your witch form (free)</div>">> <<if setup.witchSpells.canTap()>> <<run setup.clairForm.revert()>> <<goto "Spellbook">> <</if>> <</link>> <<elseif ($witchMana || 0) >= 40>> <<link "<div style='background: #7b1fa2; color: white; padding: 8px 16px; border-radius: 8px; cursor: pointer; text-align: center;'>Cast (40 mana)</div>">> <<if setup.witchSpells.canTap()>> <<if $clairFirstTransformDone>> <<run setup.witchSpells.spendMana(40)>> <<run setup.clairForm.apply()>> <<goto "Spellbook">> <<else>> <<run setup.witchSpells.spendMana(40)>> <<goto "ClairTransformationScene">> <</if>> <</if>> <</link>> <<else>> <div style="color: #666; text-align: center;">Not enough mana</div> <</if>> <<elseif _sd.category === "combat">> <div style="color: #888; text-align: center; font-size: 13px;">Combat ability. Available while diving.</div> <<elseif _sn === "Tendril Conjury">> <div style="color: #888; text-align: center; font-size: 13px;">Cast when initiating intimacy with a partner.</div> <<else>> <div style="color: #888; text-align: center; font-size: 13px;">Cast while talking to someone.</div> <</if>> </div> <<elseif setup.witchSpells.trainingStepActive(_sn)>> <div style="border: 2px solid #4dabf7; border-radius: 10px; padding: 14px; background: #101a28;"> <h3 style="color: #4dabf7; margin: 0 0 8px 0;"><<print _sd.icon>> <<print _sn>></h3> <p style="color: #9ab8d0; font-size: 13px; margin: 0;">In training with <<print _sd.teacher>>: <<print ($spellTraining[_sn] || 0) + " of " + _sd.sessions>> sessions.</p> </div> <<elseif $questData && $questData.active && $questData.active[_sd.questId]>> <div style="border: 2px solid #ffd700; border-radius: 10px; padding: 14px; background: #201c10;"> <h3 style="color: #ffd700; margin: 0 0 8px 0;"><<print _sd.icon>> <<print _sn>></h3> <p style="color: #ccc; font-size: 13px; margin: 0;"><<print _sd.teacher>> has set you a task before the lessons can begin.</p> </div> <<else>> <div style="border: 2px solid #333; border-radius: 10px; padding: 14px; background: #141414;"> <h3 style="color: #555; margin: 0 0 8px 0;">? ? ?</h3> <p style="color: #444; font-size: 13px; margin: 0;">An unlearned spell.</p> </div> <</if>> <</capture>> <</for>> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #333; color: white; padding: 10px 26px; border-radius: 8px; cursor: pointer;'>Close</div>">> <<goto _back>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _questTarget = $questDialogueTarget || $xanitharQuestTarget || "">> <<set $questReturnPassage = (_questTarget.indexOf("clair_") === 0) ? "ClairDreamTalk" : "NPCTalk">> <div style="background: #0a0014; min-height: 100vh; padding: 20px;"> <<if _questTarget && _questTarget.indexOf("clair_") === 0>> <div style="background: #2a2a2a; padding: 15px 20px; border-radius: 12px; margin-bottom: 15px; border: 2px solid #a78bfa; box-shadow: 0 0 20px rgba(167,139,250,0.3);"> <div style="color: #a78bfa; font-size: 22px; font-weight: bold; text-align: center;">🌙 Clair</div> </div> <<else>> <div style="background: #2a2a2a; padding: 15px 20px; border-radius: 12px; margin-bottom: 15px; border: 2px solid #e040fb; box-shadow: 0 0 20px rgba(224,64,251,0.3);"> <div style="color: #e040fb; font-size: 22px; font-weight: bold; text-align: center;">🔮 Xantria Galdenentri</div> </div> <</if>> <<if _questTarget === "xantria_glamour">> <<if $questData.active["xantria_glamour"]>> <<if $questData.active["xantria_glamour"].step === "training">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"Styled by hand. Good. Now you know what the craft asks for before you shortcut it. Practice with me here at the Coven and Glamour is yours."</div></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"My price is small and a little strange. Go to the beauty salon and have your hair styled by hand. Sit in the chair. Feel how long the mundane craft takes. Then come back, and I will teach you the shortcut."</div></div> <<set _glamourStyled = $appearance && $appearance.hairStyle === "styled">> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: #aaa; font-size: 14px; margin-bottom: 8px; font-weight: bold;">Required:</div> <div style="color: <<if _glamourStyled>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px; margin: 3px 0;"> <<if _glamourStyled>>✓<<else>>✗<</if>> Hair styled by hand (visit the Angelfish Beauty Salon) </div> </div> <</if>> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">Xantria looks you over, amused. "You carry the amulet well. Time you learned to shape more than yourself by moonlight. Glamour is the first spell I teach anyone. Hair, eyes, the small vanities. But magic only shortcuts a craft you respect. Go let the salon style your hair by hand first, and then we will begin."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("xantria_glamour")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<elseif _questTarget === "xantria_dreamdraught">> <<if $questData.active["xantria_dreamdraught"]>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">Sleep in your witch form with the draught on you. Any bed will do.</div></div> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">She sets a vial on the workbench before you have finished asking. "There is a place your amulet cannot take you. A dimension that borders every sleeping mind. Something lives there, and it has been alone a very long time. Keep the draught on you and sleep as a witch. It will knock politely."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("xantria_dreamdraught")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<elseif _questTarget === "xantria_tendril">> <<if $questData.active["xantria_tendril"]>> <<if $questData.active["xantria_tendril"].step === "training">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">She has agreed to teach you. Practice with Xantria here at the Coven to master the Tendril Conjury.</div></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">Grow closer to Xantria.</div></div> <<set _xr = $relationships ? $relationships["Xantria Galdenentri"] : null>> <<set _xlvl = _xr ? _xr.level : 0>> <<set _xname = "Stranger">> <<if _xlvl >= 4>><<set _xname = "Best Friend">><<elseif _xlvl >= 3>><<set _xname = "Close Friend">><<elseif _xlvl >= 2>><<set _xname = "Friend">><<elseif _xlvl >= 1>><<set _xname = "Acquaintance">><<elseif _xlvl < 0>><<set _xname = "Disliked">><</if>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: <<if _xlvl >= 3>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px;"> <<if _xlvl >= 3>>✓<<else>>✗<</if>> Relationship: <<= _xname>> (Close Friend required) </div> </div> <</if>> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"That trick I taught myself in this chamber. The tendrils. You have seen them." A slow smile. "I will not teach that to a stranger. Come back when we are closer, you and I, and I will show you how desire takes shape."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("xantria_tendril")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<elseif _questTarget === "xantria_beguile">> <<if $questData.active["xantria_beguile"]>> <<if $questData.active["xantria_beguile"].step === "training">> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">She is satisfied with your tongue. Practice with Xantria here at the Coven to master Beguile.</div></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">Show Xantria a practiced tongue. Three hundred charisma at least.</div></div> <<set _cha = $stats ? $stats.charisma : 0>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid #444;"> <div style="color: <<if _cha >= 300>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 14px;"> <<if _cha >= 300>>✓<<else>>✗<</if>> Charisma: <<= _cha>> of 300 </div> </div> <</if>> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #e040fb; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"Charm is a muscle. Magic can only pull on what is already there. Show me a practiced tongue, three hundred charisma at least, and I will teach you how to make an afternoon of someone's whole heart."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("xantria_beguile")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<elseif _questTarget === "clair_twinning">> <<if $questData.active["clair_twinning"]>> <<if $clairMemoryShared>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">She is still turning your memory over. Practice with her here to master the Twinning.</div></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"Bring the memory up where the dream can hold it," Clair says, nodding toward the still water. "Draw it from the Reflecting Pool and let it follow you to me."</div></div> <</if>> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">Clair circles you slowly, delighted. "You are the most solid thing I have ever had in here. I want to know what you feel like from the inside. Bring a memory with you when you sleep. Hold something that matters to you as you drift off. It will follow you down, and I will read it."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("clair_twinning")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<elseif _questTarget === "clair_lucidrest">> <<if $questData.active["clair_lucidrest"]>> <<if $clairNightmareSoothed>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">The corner of the dream is quiet now. Practice with Clair to master Lucid Rest.</div></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"It waits in the far corner, all mouths and tendrils," Clair says. "I cannot go near it. You will have to face it yourself, out there in the dream."</div></div> <</if>> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"Something snagged in the far corner of the dream. A nightmare, all sharp mouths and black tendrils. I cannot go near it. But you could, if you bear a fish blessed in holy light. Drive it off for me and I will teach you how to make sleep obey you."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("clair_lucidrest")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<elseif _questTarget === "clair_sandman">> <<if $questData.active["clair_sandman"]>> <<if $clairFlonaCharmGiven>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">She sleeps with the little fox under her cheek. Practice with her to master Entrancement.</div></div> <<elseif setup.witchSpells.hasQuestItem("flona_charm")>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">The carved charm sits warm in your pocket, even here.</div></div> <div style="text-align: center; margin-top: 15px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px rgba(167,139,250,0.45);'>Give Clair the carved charm</div>">><<if setup.witchSpells.canTap()>><<run setup.witchSpells.removeQuestItem("flona_charm")>><<set $clairFlonaCharmGiven = true>><<goto $questReturnPassage>><</if>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">Visit Flona Vulri in the Tundra of Aeternus and ask for a token.</div></div> <</if>> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #a78bfa; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">"There is a fox in the far snow of your world who has slept a hundred winters through and never once dreamed badly. I can taste it from here. Bring me something her hands have made and I will teach you what sleep knows about wanting."</div></div> <div style="display: flex; gap: 15px; justify-content: center;"><<link "<div style='display: inline-block; background: #51cf66; color: #1a1a1a; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 0 15px #51cf6644;'>Accept Quest</div>">><<if setup.witchSpells.canTap()>><<run setup.questSystem.startQuest("clair_sandman")>><<goto $questReturnPassage>><</if>><</link>><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 2px solid #666; color: #aaa; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px;'>Decline</div>">><<goto $questReturnPassage>><</link>></div> <</if>> <<else>> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border-left: 4px solid #666; margin-bottom: 15px;"><div style="color: #ccc; font-size: 16px; line-height: 1.6; font-style: italic;">...</div></div> <div style="text-align: center; margin-top: 10px;"><<link "<div style='display: inline-block; background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); border: 3px solid #667eea; color: white; padding: 12px 30px; border-radius: 10px; cursor: pointer; font-weight: bold; font-size: 14px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Back to Conversation</div>">><<goto $questReturnPassage>><</link>></div> <</if>> </div> <</nobr>>
<<nobr>> <<set $clairFirstMeetingDone = true>> <<set $clairDreamPending = false>> <<run (function(){ var v = State.variables; if (v.metNPCs && v.metNPCs.indexOf("Clair") === -1) v.metNPCs.push("Clair"); if (v.relationships && !v.relationships["Clair"]) v.relationships["Clair"] = {level: 1, points: 30}; })()>> <div class="dream-starfield" style="min-height: 100vh; padding: 40px 20px; display: flex; flex-direction: column; align-items: center; justify-content: center;"> <div style="max-width: 680px;"> <<timed 1s>> <p class="oni-fade" style="color: #9b8ac4; font-size: 16px; line-height: 1.8;">Sleep takes you the way it always does. Then it keeps going.</p> <<timed 3s>> <p class="oni-fade" style="color: #b5a5e0; font-size: 16px; line-height: 1.8;">The draught hums once in your blood, polite as a knock, and the dark opens onto violet. You are standing on light. It holds.</p> <<timed 4s>> <p class="oni-fade clair-voice" style="color: #cbb8ff; font-size: 16px; line-height: 1.8;">"Oh," says a voice, close and unhurried. "You brought a whole body. Nobody ever brings the body."</p> <div class="oni-fade" style="text-align: center; margin: 14px 0 18px 0;"><img src="Images/NPCs/StaticNPCs/Clair.webp" alt="Clair" style="max-width: 300px; max-height: 460px; border-radius: 12px; border: 2px solid #a78bfa; box-shadow: 0 0 26px rgba(167,140,250,0.5);" onerror="this.style.display='none';"></div> <p class="oni-fade clair-voice" style="color: #e6dcff; font-size: 16px; line-height: 1.8;">She condenses out of the drift the way frost forms, her hair a silvery lavender, barefoot, dressed in something between a nightgown and mist. Her eyes are pale opal and openly delighted. She walks a slow circle around you without any particular respect for which way is down.</p> <<timed 4s>> <p class="oni-fade clair-voice" style="color: #cbb8ff; font-size: 16px; line-height: 1.8;">"The potion smelled like Xantria's work. She knocked politely, so I let you in." She studies you a moment longer than a stranger would, and something like recognition softens her face. "Though I have seen you before tonight, Wanderer. Once, when you were formless and nameless, adrift in the dark between the stars, a presence leaned close and told you an island was waiting, a place where dreams could become real. You listened. You came. That was me, whispering into the very fabric of you." She smiles. "I am Clair. I have always been here, and I have watched you far longer than you know. You are the most interesting thing to fall into my dream in a few hundred years, so please, be in no hurry to wake."</p> <<timed 3s>> <div class="oni-fade" style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 13px 30px; border-radius: 10px; font-weight: bold; cursor: pointer;'>Look around the dream</div>">> <<goto "DreamDimension">> <</link>> </div> <</timed>> <</timed>> <</timed>> <</timed>> <</timed>> </div> </div> <</nobr>>
<<nobr>> <<if !setup.witchSpells.isSpellcaster() || !setup.witchSpells.knows("Glamour")>> <<goto "The Nest">> <<else>> <<set _back = (previous() && previous() !== "GlamourSpell") ? previous() : "Spellbook">> <<set _curLen = ($appearance.hairLength === "long") ? "long" : "short">> <<set _curStyle = $appearance.hairStyle ? $appearance.hairStyle : "messy">> <<set _curColor = $appearance.hairColor ? $appearance.hairColor : "Black">> <div style="background: radial-gradient(circle at 50% 20%, #1a0a2e 0%, #0d0518 100%); min-height: 100vh; padding: 20px;"> <h1 style="color: #e040fb; text-align: center; margin: 0 0 10px 0; text-shadow: 0 0 15px rgba(224,64,251,0.5);">💄 Glamour</h1> <p style="color: #bba8cc; text-align: center; font-size: 14px; max-width: 560px; margin: 0 auto 20px auto; line-height: 1.5;">You pass a hand in front of your face and the change follows it, light as makeup, real as anything. The spell holds until you change it again.</p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 15px; max-width: 800px; margin: 0 auto;"> <div style="border: 2px solid #e040fb; border-radius: 10px; padding: 14px; background: #1c1028;"> <h3 style="color: #e040fb; margin: 0 0 8px 0;">Hair Style</h3> <p style="color: #999; font-size: 12px; margin: 0 0 8px 0;">Currently: <<print _curStyle>></p> <<if _curStyle === "messy">> <<link "<div style='background: #7b1fa2; color: white; padding: 7px 12px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 4px;'>Styled</div>">> <<if setup.witchSpells.canTap()>> <<set $appearance.hairStyle = "styled">> <<goto "GlamourSpell">> <</if>> <</link>> <<else>> <<link "<div style='background: #7b1fa2; color: white; padding: 7px 12px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 4px;'>Artfully messy</div>">> <<if setup.witchSpells.canTap()>> <<set $appearance.hairStyle = "messy">> <<goto "GlamourSpell">> <</if>> <</link>> <</if>> </div> <div style="border: 2px solid #e040fb; border-radius: 10px; padding: 14px; background: #1c1028;"> <h3 style="color: #e040fb; margin: 0 0 8px 0;">Hair Length</h3> <p style="color: #999; font-size: 12px; margin: 0 0 8px 0;">Currently: <<print _curLen>></p> <<if _curLen === "long">> <<link "<div style='background: #7b1fa2; color: white; padding: 7px 12px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 4px;'>Short</div>">> <<if setup.witchSpells.canTap()>> <<set $appearance.hairLength = "short">> <<run $physicalTraits.delete("Long Hair")>> <<if !$physicalTraits.includes("Short Hair")>><<run $physicalTraits.push("Short Hair")>><</if>> <<goto "GlamourSpell">> <</if>> <</link>> <<else>> <<link "<div style='background: #7b1fa2; color: white; padding: 7px 12px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 4px;'>Long</div>">> <<if setup.witchSpells.canTap()>> <<set $appearance.hairLength = "long">> <<run $physicalTraits.delete("Short Hair")>> <<if !$physicalTraits.includes("Long Hair")>><<run $physicalTraits.push("Long Hair")>><</if>> <<goto "GlamourSpell">> <</if>> <</link>> <</if>> </div> <div style="border: 2px solid #e040fb; border-radius: 10px; padding: 14px; background: #1c1028;"> <h3 style="color: #e040fb; margin: 0 0 8px 0;">Hair Color</h3> <p style="color: #999; font-size: 12px; margin: 0 0 8px 0;">Currently: <<print _curColor>></p> <<for _gc range ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]>> <<capture _gc>> <<if _curColor !== _gc>> <<set _clabel = "<div style='background: #2d1a3d; color: #e0c8f0; padding: 6px 12px; border-radius: 8px; cursor: pointer; text-align: center; margin-top: 4px;'>" + _gc + "</div>">> <<link _clabel>> <<if setup.witchSpells.canTap()>> <<set $appearance.hairColor = _gc>> <<goto "GlamourSpell">> <</if>> <</link>> <</if>> <</capture>> <</for>> </div> </div> <div style="text-align: center; margin-top: 25px;"> <<link "<div style='display: inline-block; background: #333; color: white; padding: 10px 26px; border-radius: 8px; cursor: pointer;'>Done</div>">> <<goto _back>> <</link>> </div> </div> <</if>> <</nobr>>
<<nobr>> <div class="dream-starfield" style="min-height: 100vh; padding: 40px 20px;"> <div style="max-width: 680px; margin: 0 auto;"> <<timed 1s>> <p class="oni-fade" style="color: #9b8ac4; font-size: 16px; line-height: 1.8;">You speak the shape of the spell the way Clair taught you, less a word than an agreement, and the dream reaches back.</p> <<timed 3s>> <p class="oni-fade" style="color: #b5a5e0; font-size: 16px; line-height: 1.8;">Your edges go soft. Not painful, not even strange, just negotiable, the way a reflection is negotiable when the water moves. The witch body you know pales to moonlight from the fingertips inward.</p> <<timed 4s>> <p class="oni-fade" style="color: #cbb8ff; font-size: 16px; line-height: 1.8;">Then the light settles, and it settles as her. Silvery lavender hair pours down past your shoulders without weight. Your skin cools to something luminous and patient. The new body is taller, softer in some places and surer in others, and it fits like a borrowed coat that turns out to have been tailored for you all along.</p> <div class="oni-fade" style="text-align: center; margin: 16px 0 20px 0;"><img src="Images/Transformation/Clairtwinning.webp" alt="Clair" style="max-width: 320px; max-height: 480px; border-radius: 12px; border: 2px solid #a78bfa; box-shadow: 0 0 28px rgba(167,140,250,0.55);" onerror="this.style.display='none';"></div> <<timed 4s>> <p class="oni-fade" style="color: #e6dcff; font-size: 16px; line-height: 1.8;">Knowledge arrives with the shape. Languages you never learned sit quietly on your tongue. Old magic hums in your hands like a remembered song. When you say your name, the voice that answers is silk, and the name it says is Clair.</p> <p class="oni-fade" style="color: #cbb8ff; font-size: 16px; line-height: 1.8;">Somewhere, in a dream that borders every sleeping mind, the original laughs, delighted, and you feel it as a warmth behind your ribs. Two of her now. She has wanted this for centuries.</p> <<timed 3s>> <div class="oni-fade" style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 13px 30px; border-radius: 10px; font-weight: bold; cursor: pointer;'>Open your eyes as Clair</div>">> <<set _applied = setup.clairForm.apply()>> <<if _applied>><<set $clairFirstTransformDone = true>><</if>> <<goto "Spellbook">> <</link>> </div> <</timed>> <</timed>> <</timed>> <</timed>> <</timed>> </div> </div> <</nobr>>
<<nobr>> <<set $clairMemoryShared = true>> <div class="dream-starfield" style="min-height: 100vh; padding: 40px 20px;"> <div style="max-width: 680px; margin: 0 auto;"> <<timed 1s>> <p class="oni-fade" style="color: #9b8ac4; font-size: 16px; line-height: 1.8;">You kneel at the Reflecting Pool. The water does not show your face. It shows what you carried down here: something small and warm and yours, held the loose way you were holding it as you fell asleep.</p> <<timed 3s>> <p class="oni-fade" style="color: #b5a5e0; font-size: 16px; line-height: 1.8;">You reach in. The surface does not break. The memory rises to meet your fingers like a fish coming up for light, and you lift it out whole, dripping violet.</p> <<timed 4s>> <p class="oni-fade" style="color: #cbb8ff; font-size: 16px; line-height: 1.8;">Clair leans in, both hands cupped beneath yours, and reads it. Whatever it holds moves across her face like weather. "Oh," she breathes. "So that is what you are made of. Thank you. I will keep the shape of it."</p> <<timed 3s>> <div class="oni-fade" style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 13px 30px; border-radius: 10px; font-weight: bold; cursor: pointer;'>Open your eyes</div>">> <<goto "DreamDimension">> <</link>> </div> <</timed>> <</timed>> <</timed>> <</timed>> </div> </div> <</nobr>>
<<nobr>> <<set _divineFish = setup.playerHasTrait("Divine Sunfish")>> <<set $clairNightmareSoothed = true>> <div class="dream-starfield" style="min-height: 100vh; padding: 40px 20px;"> <div style="max-width: 680px; margin: 0 auto; position: relative; z-index: 2;"> <<if _divineFish>> <<timed 1s>> <p class="oni-fade" style="color: #e4c4cc; font-size: 16px; line-height: 1.8;">You walk toward the far corner. The light of the oasis altar still lives in you, sevenfold and holy, the blessing of the divine fish humming under your skin. You do not raise a hand. You do not need to.</p> <<timed 3s>> <div class="dream-holy-glow"></div> <div class="dream-holy-rays"></div> <div class="dream-holy-flash"></div> <p class="holy-text" style="color: #fff1c9; font-size: 17px; line-height: 1.8; font-weight: 500;">The array of mouths turns toward you all at once, and every one of them goes still. The black tendrils fall slack. Whatever it was feeding on, it cannot feed with a divine thing standing in the room. The nightmare comes apart like smoke off water, unmaking itself rather than touch the holy light you carry.</p> <<timed 4s>> <p class="oni-fade" style="color: #f0d8e0; font-size: 16px; line-height: 1.8;">Clair watches from a safe distance, wide eyed. "It ran," she says, half a laugh. "It looked at you and it simply gave up. I have never seen one do that." She shakes her head, delighted. "You did not even try."</p> <<timed 3s>> <div class="oni-fade" style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 13px 30px; border-radius: 10px; font-weight: bold; cursor: pointer;'>Return to the dream</div>">> <<goto "DreamDimension">> <</link>> </div> <</timed>> <</timed>> <</timed>> <</timed>> <<else>> <<timed 1s>> <p class="oni-fade" style="color: #d8b0bb; font-size: 16px; line-height: 1.8;">You cannot banish it yourself. But you carry a fish blessed in holy light, and a dream can borrow what you carry. "Give it to me," Clair says, holding out both hands. "The light, not the body. Let it pass through you into me."</p> <<timed 3s>> <div class="dream-borrow-glow"></div> <p class="holy-text" style="color: #f6e6cc; font-size: 16px; line-height: 1.8;">You open the place inside you where the blessing sits, and it flows out of your hands into hers, pale gold pouring into her silver. Clair blazes with it, brighter than you have ever seen her, a dreaming thing suddenly wearing daylight.</p> <<timed 4s>> <div class="dream-clair-rays"></div> <div class="dream-clair-flash"></div> <p class="clair-text" style="color: #e9ddff; font-size: 17px; line-height: 1.8; font-weight: 500;">She turns on the nightmare and speaks a word you feel in your teeth, and the borrowed light detonates out of her. It goes through the array of mouths like a tide through a net. The black tendrils burn away to nothing, the mouths close one by one, and the far corner is only violet quiet again. Clair sags, spent and grinning. "That," she pants, "is why I wanted you. Thank you for lending me the sun."</p> <!-- DREAMDEMON_SCENE_IMAGE_START --> <<if $imageSettings && $imageSettings.imagesEnabled>> <div class="oni-fade" style="text-align: center; margin: 16px 0 4px 0;"> <img src="Images/Scenes/dreamdemon.webp" alt="The nightmare" style="display: block; margin: 0 auto; max-width: min(100%, 720px); max-height: 640px; width: auto; height: auto; border-radius: 12px; border: 4px solid #a78bfa; box-shadow: 0 0 36px rgba(167, 139, 250, 0.55), 0 6px 20px rgba(0, 0, 0, 0.55);" onerror="this.style.display='none';"> </div> <</if>> <!-- DREAMDEMON_SCENE_IMAGE_END --> <<timed 3s>> <div class="oni-fade" style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: linear-gradient(135deg, #a78bfa 0%, #7c5cc4 100%); color: white; padding: 13px 30px; border-radius: 10px; font-weight: bold; cursor: pointer;'>Return to the dream</div>">> <<goto "DreamDimension">> <</link>> </div> <</timed>> <</timed>> <</timed>> <</timed>> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set _clairQuests = setup.getNPCQuests("Clair")>> <div class="dream-starfield" style="min-height: 100vh; padding: 40px 20px;"> <div style="max-width: 720px; margin: 0 auto;"> <div style="text-align: center; margin-bottom: 18px;"> <img src="Images/Faces/Laboratory/Clair_Portrait.webp" alt="Clair" style="max-width: 200px; border-radius: 14px; border: 2px solid #c084fc; box-shadow: 0 0 28px rgba(192,132,252,0.5);" onerror="this.style.display='none';"> <h1 style="color: #c084fc; margin: 12px 0 0 0; text-shadow: 0 0 16px rgba(192,132,252,0.6); letter-spacing: 1px;">🌙 Clair</h1> </div> <div style="background: rgba(20,16,42,0.72); border: 1px solid #6c5b8e; border-radius: 12px; padding: 16px 20px; margin-bottom: 18px;"> <p class="clair-voice" style="color: #d9c9ff; font-size: 15px; line-height: 1.7; margin: 0; font-style: italic;">Clair is sitting on nothing in particular, chin in her hands, watching you the way a cat watches a door open. "There you are," she says, pleased. "Ask me anything. I have had centuries to think, and almost no one to tell."</p> </div> <<for _cqi = 0; _cqi < _clairQuests.length; _cqi++>> <<set _cq = _clairQuests[_cqi]>> <<capture _cq>> <<if _cq.state === "available" && _cq.quest.dialoguePassage>> <div style="background: rgba(30,24,8,0.82); border: 2px solid #ffd700; border-radius: 10px; padding: 12px 16px; margin-bottom: 10px; box-shadow: 0 0 10px #ffd70033;"> <div style="color: #ffd700; font-weight: bold; margin-bottom: 4px;">✦ <<= _cq.quest.name>></div> <div style="color: #cbb8a0; font-size: 13px; line-height: 1.5; margin-bottom: 8px;"><<= _cq.quest.description>></div> <<link "<span style='color: #ffd700; cursor: pointer; font-weight: bold;'>Hear her out</span>">><<set $questDialogueTarget = _cq.id>><<goto _cq.quest.dialoguePassage>><</link>> </div> <<elseif _cq.state === "active" && _cq.quest.dialoguePassage>> <div style="background: rgba(12,22,38,0.82); border: 2px solid #4dabf7; border-radius: 10px; padding: 12px 16px; margin-bottom: 10px;"> <div style="color: #4dabf7; font-weight: bold; margin-bottom: 6px;">▶ <<= _cq.quest.name>></div> <<link "<span style='color: #4dabf7; cursor: pointer; font-weight: bold;'>Speak with her about it</span>">><<set $questDialogueTarget = _cq.id>><<goto _cq.quest.dialoguePassage>><</link>> </div> <</if>> <</capture>> <</for>> <div style="background: rgba(20,16,42,0.55); border: 1px solid #6c5b8e; border-radius: 12px; padding: 16px 20px; margin-bottom: 18px;"> <div style="color: #b9a8dd; font-size: 12px; letter-spacing: 1.5px; margin-bottom: 12px; text-transform: uppercase;">Speak with her</div> <div style="display: grid; gap: 12px;"> <div><<linkreplace '<span style="color:#c9b6ff;font-size:15px;">"What are you, exactly?"</span>'>><p class="clair-voice" style="color:#d9c9ff;font-size:15px;line-height:1.7;margin:8px 0 0 0;">"A habit the dream fell into, a very long time ago. Something dreamed so hard, so often, in one place, that the dreaming began to dream back. That waking was me. I have been here since before your island had a name."</p><</linkreplace>></div> <div><<linkreplace '<span style="color:#c9b6ff;font-size:15px;">"You said you have watched me before."</span>'>><p class="clair-voice" style="color:#d9c9ff;font-size:15px;line-height:1.7;margin:8px 0 0 0;">She tilts her head. "Since the first night you drifted formless into the dark. I am the quiet that speaks to sleepers, and almost none of them remember the voice after. You brought your whole self down here and looked me in the eye. I do not think you will forget me."</p><</linkreplace>></div> <div><<linkreplace '<span style="color:#c9b6ff;font-size:15px;">"Do you ever leave the dream?"</span>'>><p class="clair-voice" style="color:#d9c9ff;font-size:15px;line-height:1.7;margin:8px 0 0 0;">"Where would I go? Every sleeping mind opens onto this place, so I am already a little bit everywhere at once. I do not envy you your waking. It is so loud out there, and the things you love can end. Here, nothing has to."</p><</linkreplace>></div> <div><<linkreplace '<span style="color:#c9b6ff;font-size:15px;">"Tell me about this place."</span>'>><p class="clair-voice" style="color:#d9c9ff;font-size:15px;line-height:1.7;margin:8px 0 0 0;">"It is built from the pieces of the world no one could bear to let go. Favorite rooms. The faces of the dead. A song half remembered. They drift in on their own and I keep them company. You are the first visitor in centuries who is warm to the touch."</p><</linkreplace>></div> <div><<linkreplace '<span style="color:#c9b6ff;font-size:15px;">"I like you."</span>'>><p class="clair-voice" style="color:#d9c9ff;font-size:15px;line-height:1.7;margin:8px 0 0 0;">Her opal eyes brighten. "I know. You are terrible at hiding it, and I am very old and very good at reading the shape of a wanting. Stay as long as you like, Wanderer. The dream is patient. For you, so am I."</p><</linkreplace>></div> </div> </div> <<if setup.islandLore.isAskable("Clair")>> <div style="background:linear-gradient(135deg,#1a1430,#0e0a1c); border:2px solid #7a6aa8; border-radius:10px; padding:14px 16px; margin:0 auto 15px; max-width:620px;"> <p style="color:#cdbdf0; font-size:15px; line-height:1.6; margin:0 0 10px 0;">You steer the talk toward the island itself. How does this place work? How long has it stood?</p> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#7a6aa8,#4a3d70); color:white; padding:9px 22px; border-radius:9px; font-weight:bold; cursor:pointer;'>Ask about the island</div>">> <<if setup.canCombineTap()>> <<set $lastLocationBeforeAsk = "ClairDreamTalk">> <<run setup.islandLore.recordAsk("Clair")>> <<goto "IslandLoreAccount">> <</if>> <</link>> </div> <</if>> <div style="text-align: center;"> <<link "<div style='display:inline-block; background: linear-gradient(135deg, rgba(125,211,252,0.25), rgba(192,132,252,0.25)); border:2px solid #c084fc; color:#e6dcff; padding:12px 34px; border-radius:30px; font-weight:bold; cursor:pointer; text-shadow:0 0 10px #c084fc; box-shadow:0 0 16px rgba(192,132,252,0.3); letter-spacing:1px;'>Step back</div>">> <<goto "DreamDimension">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set _sp = $practiceSpell>> <<set _pd = setup.witchSpells.practiceData(_sp)>> <<if !_pd>> <<goto $practiceReturn>> <<else>> <<set _willMaster = setup.witchSpells.willMaster(_sp)>> <<set _bgClass = _pd.teacher === "Clair" ? "dream-starfield" : "">> <<set _bgStyle = _pd.teacher === "Clair" ? "min-height: 100vh; padding: 44px 20px;" : "background: radial-gradient(circle at 50% 22%, #241033 0%, #12081f 68%, #0a0512 100%); min-height: 100vh; padding: 44px 20px;">> <div @class="_bgClass" @style="_bgStyle"> <div style="max-width: 680px; margin: 0 auto;"> <<timed 1s>> <p class="oni-fade" style="color: #c9b6ff; font-size: 16px; line-height: 1.85;"><<= _pd.b0>></p> <<timed 3s>> <p class="oni-fade" style="color: #d9c9ff; font-size: 16px; line-height: 1.85;"><<= _pd.b1>></p> <<timed 4s>> <<if _willMaster>> <p class="oni-fade" style="color: #fff1c9; font-size: 17px; line-height: 1.85; font-weight: 500;"><<= _pd.mastery>></p> <<else>> <p class="oni-fade" style="color: #bcd6ff; font-size: 16px; line-height: 1.85; font-style: italic;">Not there yet, but closer than yesterday, humming just under your skin. <<= _pd.teacher>> tells you to rest, and come back to it.</p> <</if>> <<timed 2s>> <<set _btnHtml = "<div style='display:inline-block; background:linear-gradient(135deg, rgba(125,211,252,0.22), rgba(192,132,252,0.22)); border:2px solid #c084fc; color:#e6dcff; padding:12px 34px; border-radius:30px; font-weight:bold; cursor:pointer; letter-spacing:1px;'>" + (_willMaster ? "Master it" : "Rest for now") + "</div>">> <div class="oni-fade" style="text-align: center; margin-top: 30px;"> <<link _btnHtml>> <<if setup.witchSpells.canTap()>> <<set _r = setup.witchSpells.trainSpell(_sp)>> <<if _pd.teacher === "Clair">><<advancetime 60>><<else>><<advancetime 90>><</if>> <<run setup.questSystem.addNotification("updated", _r)>> <<goto $practiceReturn>> <</if>> <</link>> </div> <</timed>> <</timed>> <</timed>> <</timed>> </div> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoDragonAltar">> <<if $flawlessGemInventory === undefined>><<set $flawlessGemInventory = {}>><</if>> <<if $dragonAltarGems === undefined>><<set $dragonAltarGems = []>><</if>> <<if $dragonEntranceOpen === undefined>><<set $dragonEntranceOpen = false>><</if>> <<if setup.questSystem && !setup.questSystem.isQuestActive("dragon_queen_altar") && !setup.questSystem.isQuestCompleted("dragon_queen_altar") && !$dragonEntranceOpen>> <<run setup.questSystem.startQuest("dragon_queen_altar")>> <</if>> <style> @keyframes fgFilledPulse { 0%,100%{ filter: drop-shadow(0 0 2px var(--gem)); transform: scale(1); } 50%{ filter: drop-shadow(0 0 7px var(--gem)); transform: scale(1.04); } } @keyframes fgReadyPulse { 0%,100%{ filter: drop-shadow(0 0 1px var(--gem)); opacity:0.82; } 50%{ filter: drop-shadow(0 0 6px var(--gem)); opacity:1; } } .fg-basalt { background: linear-gradient(180deg,#2a2a2f 0%,#202024 55%,#161618 100%); min-height:100vh; padding:22px; } .fg-ring { position:relative; width:min(600px,92vw); aspect-ratio:1; margin:26px auto; } .fg-ring > a { display:contents; } .fg-cell { position:absolute; display:flex; align-items:center; justify-content:center; transition:z-index 0s linear 0.18s; } .fg-gem { width:clamp(56px,11vw,86px); height:clamp(56px,11vw,86px); line-height:0; } .fg-gem svg { display:block; } .fg-filled { animation: fgFilledPulse 2.6s ease-in-out infinite; } .fg-ready { animation: fgReadyPulse 3s ease-in-out infinite; cursor:pointer; } .fg-ready:hover { filter: drop-shadow(0 0 12px var(--gem)) !important; opacity:1 !important; } .fg-label { position:absolute; top:100%; left:50%; transform:translateX(-50%); margin-top:6px; font-size:12px; white-space:nowrap; opacity:0; transition:opacity .15s ease; pointer-events:none; background:rgba(12,12,15,0.9); padding:3px 9px; border-radius:7px; border:1px solid rgba(255,255,255,0.08); z-index:5; } .fg-cell:hover, .fg-cell:active { z-index:30; transition-delay:0s; } .fg-cell:hover .fg-label, .fg-cell:active .fg-label { opacity:1; } </style> <div class="fg-basalt"> <h1 style="color:#c9c9d2; text-align:center; text-shadow:0 2px 6px rgba(0,0,0,0.7); letter-spacing:1px;">The Ancient Altar</h1> <<if $dragonEntranceOpen>> <div style="padding:16px 18px; background:#2c2622; border:1px solid #c2622a; border-radius:12px; margin:16px auto 20px auto; max-width:760px; text-align:center;"> <p style="color:#e6b48a; font-size:15px; line-height:1.6; margin:0;">Every gem sits burning in its socket. The lava in the crater has drawn back, and a dark passage stands open below. Something waits within.</p> </div> <div style="text-align:center;"> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#ff5722 0%,#b03a17 100%); color:white; padding:14px 34px; border-radius:10px; font-weight:bold; cursor:pointer; margin:0 8px 10px 8px;'>Descend into the passage</div>">> <<goto "DragonQueenChamber">> <</link>> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#ff5722 0%,#b03a17 100%); color:white; padding:14px 34px; border-radius:10px; font-weight:bold; cursor:pointer;'>Return to the Peak</div>">> <<goto "VolcanoPeak">> <</link>> </div> <<else>> <div class="fg-ring"> <<set _n = setup.flawlessGems.TYPES.length>> <<for _gi = 0; _gi < _n; _gi++>> <<set _gk = setup.flawlessGems.TYPES[_gi]>> <<set _ang = _gi / _n * 2 * Math.PI - Math.PI / 2>> <<set _lx = (50 + 42 * Math.cos(_ang)).toFixed(2)>> <<set _ly = (50 + 42 * Math.sin(_ang)).toFixed(2)>> <<set _pos = "position:absolute; left:" + _lx + "%; top:" + _ly + "%; transform:translate(-50%,-50%);">> <<capture _gk, _pos>> <<if $dragonAltarGems.includes(_gk)>> <<set _cell = "<div class='fg-cell' style='" + _pos + "'>" + setup.flawlessGems.gemCell(_gk, "filled") + setup.flawlessGems.labelHTML(_gk, "filled") + "</div>">> <<print _cell>> <<elseif ($flawlessGemInventory[_gk] || 0) > 0>> <<set _cell = "<div class='fg-cell' style='" + _pos + "'>" + setup.flawlessGems.gemCell(_gk, "ready") + setup.flawlessGems.labelHTML(_gk, "ready") + "</div>">> <<link _cell>> /* Idempotency guard: also serves as the mobile double-tap guard. A re-fired tap re-runs this body, but the includes() check blocks a second deposit. Do not weaken it. */ <<if ($flawlessGemInventory[_gk] || 0) > 0 && !$dragonAltarGems.includes(_gk)>> <<set $flawlessGemInventory[_gk] = $flawlessGemInventory[_gk] - 1>> <<run $dragonAltarGems.push(_gk)>> <<if $dragonAltarGems.length >= 16 && !$dragonEntranceOpen>> <<set $dragonEntranceOpen = true>> <</if>> <</if>> <<if $dragonEntranceOpen>> <<goto "VolcanoAltarActivation">> <<else>> <<goto "VolcanoDragonAltar">> <</if>> <</link>> <<else>> <<set _cell = "<div class='fg-cell' style='" + _pos + "'>" + setup.flawlessGems.gemCell(_gk, "locked") + setup.flawlessGems.labelHTML(_gk, "locked") + "</div>">> <<print _cell>> <</if>> <</capture>> <</for>> </div> <div style="text-align:center; margin-top:14px;"> <<link "<div style='display:inline-block; background:#33333a; border:1px solid #55555e; color:#c9c9d2; padding:12px 30px; border-radius:10px; font-weight:bold; cursor:pointer;'>Step away from the altar</div>">> <<goto "VolcanoPeak">> <</link>> </div> <</if>> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DragonQueenChamber">> <<if $metDragonQueen === undefined>><<set $metDragonQueen = false>><</if>> /* Safety-net heat gate. Reaching here needed heat resistance; guard against losing it. */ <<set _hasHeatImmunity = setup.hasHeatResistance() || ($dragonDirectiveGiven && !$dragonFreed)>> <<if _hasHeatImmunity>> <<set $volcanoHeatSteps = 0>> <<else>> <<set $volcanoHeatSteps += 1>> <<if $volcanoHeatSteps >= 3>> <<set $volcanoHeatSteps = 0>> <<goto "VolcanoPassout">> <</if>> <</if>> <style> @keyframes dragonVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .dragon-voice { font-family:'Cinzel', serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:dragonVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } @keyframes prisonLavaPulse { 0%,100%{box-shadow:inset 0 0 60px rgba(255,120,40,0.35), 0 0 40px rgba(255,90,20,0.25);} 50%{box-shadow:inset 0 0 90px rgba(255,150,60,0.5), 0 0 70px rgba(255,110,30,0.4);} } .prison-pool { background:radial-gradient(ellipse at 50% 45%, #ffd9a0 0%, #ff8c1a 18%, #b23400 45%, #3a1000 80%); border-radius:50%; height:180px; max-width:420px; margin:0 auto 22px auto; animation:prisonLavaPulse 4s ease-in-out infinite; } </style> <div style="background:#0a0400; min-height:100vh; padding:30px 20px;"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <<if !_hasHeatImmunity && $volcanoHeatSteps === 1>> <div style="background:#4a1a00; padding:12px; border-radius:8px; border:2px solid #ff5722; margin-bottom:15px; text-align:center;"> <p style="color:#ff8a65; font-size:15px; font-weight:bold; margin:0;">🌡️ The searing heat of this place presses against your skin. You cannot linger much longer.</p> </div> <<elseif !_hasHeatImmunity && $volcanoHeatSteps === 2>> <div style="background:#5a0a00; padding:12px; border-radius:8px; border:2px solid #ff0000; margin-bottom:15px; text-align:center;"> <p style="color:#ff4444; font-size:16px; font-weight:bold; margin:0;">🔥 Your vision swims. One more moment in this heat and you will not walk out.</p> </div> <</if>> <<if !$metDragonQueen>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The passage opens into a low chamber, and at its heart lies a pool of lava unlike any you have seen. Its light is pale and wrong, the color of a candle behind bone. The heat that rolls off it makes even your fireproof body flinch. Nothing moves within it. Then it speaks.</p> <p class="dragon-voice">"Who treads upon my silence? Some small warm thing, come crawling to the edge of my grave. Nearer. Let me taste the shape of thee."</p> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">You have no answer worth giving. The voice does not wait for one.</p> <p class="dragon-voice">"Flesh that doth not blacken in my heat. Curious. The centuries send me at last a visitor who doth not burn to ash upon the threshold. Look upon the pale fire that holds me. It was kindled by those who feared what I am, and it drinks the very heat that should be my throne. I who ruled the burning heart of this world am bound in a cup of light no wider than a grave."</p> <p class="dragon-voice">"Free me, little ember, and I shall not forget it. I am a queen. A queen pays her debts in kind that mortals do not dream of. Loose these pale chains and I will set upon thee a gift worthy of the one who dared."</p> <p class="dragon-voice">"But thou canst not simply reach in and pluck me free. The binding must be unmade as it was made. Seek the ones who wrought it. Bring me what I bid, and step by step we shall drown this cold light. Go now. I am patient. I have had no choice but to learn it."</p> <p class="dragon-voice">"Before thou canst free me, thou must know where thou standest. This island is not what it seems, and I would learn what its people still remember of it. Go among them. Ask how this place lives and holds together. But speak not one word of me. Not my voice, not this pool, not that I wait beneath the mountain. If they ask who sent thee, thou sent thyself. Return when thou hast the shape of it."</p> </div> <<set $metDragonQueen = true>> <<if setup.questSystem && !setup.questSystem.isQuestActive("dragon_queen_free") && !setup.questSystem.isQuestCompleted("dragon_queen_free")>> <<run setup.questSystem.startQuest("dragon_queen_free")>> <</if>> <<if setup.questSystem && !setup.questSystem.isQuestActive("mikla_island_lore") && !setup.questSystem.isQuestCompleted("mikla_island_lore")>> <<run setup.questSystem.startQuest("mikla_island_lore")>> <</if>> <<else>> <<if setup.questSystem && setup.questSystem.isQuestActive("mikla_island_lore") && $questData.active["mikla_island_lore"].step === "report">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return, and the voice rises out of it, expectant.</p> <p class="dragon-voice">"Thou art returned. Tell me, then. What didst thou learn of this island of yours?"</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Tell them what you learned</div>">> <<if setup.canCombineTap()>> <<set $islandLoreReported = true>> <<if !$ownedArtifacts>><<set $ownedArtifacts = []>><</if>> <<if $ownedArtifacts.indexOf("Hammer of the Fire Giants") === -1>><<run $ownedArtifacts.push("Hammer of the Fire Giants")>><</if>> <<set $hasClawToothNecklace = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "MiklaIslandReport">> <</if>> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("mikla_island_lore") && !setup.questSystem.isQuestActive("mikla_investigate_city") && !setup.questSystem.isQuestCompleted("mikla_investigate_city")>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs, and this time the voice has more to say. There is a weight to it, as though it has been waiting for you to be ready.</p> <p class="dragon-voice">"Thou art returned, and thou hast eyes now. Come closer. There is more I would have thee see."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Approach the pool</div>">> <<goto "MiklaCityIntro">> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("mikla_investigate_city") && $questData.active["mikla_investigate_city"].step === "investigate">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice settles, patient, waiting on your errands.</p> <p class="dragon-voice">"Thou hast thy tasks. The hollow hall, and the search for a child. Go, and look closely. I am not going anywhere."</p> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("mikla_investigate_city") && $questData.active["mikla_investigate_city"].step === "report">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice rises to meet you, keen and waiting.</p> <p class="dragon-voice">"Thou hast the look of one who found what she sought. Tell me. Tell me all of it."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Tell her what you found</div>">> <<if setup.canCombineTap()>> <<set $miklaCityReported = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "MiklaCityReport">> <</if>> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("mikla_investigate_city") && !setup.questSystem.isQuestActive("island_supply_lines") && !setup.questSystem.isQuestCompleted("island_supply_lines")>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs, and the voice comes up with that patient weight it wears when it means to set thee walking again.</p> <p class="dragon-voice">"Thou art returned, and there is more of this island I would have thee uncover. Come closer. Let me set thee thy next errand."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Approach the pool</div>">> <<goto "MiklaSupplyIntro">> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("island_supply_lines") && $questData.active["island_supply_lines"].step === "investigate">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice settles, in no hurry at all.</p> <p class="dragon-voice">"Thou hast thy errand. Walk down to the water and watch what the island does not wish thee to notice. Slowly, and across days. Come back when thou hast the shape of it."</p> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("island_supply_lines") && $questData.active["island_supply_lines"].step === "report_docks">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice rises to meet you, keen for the telling.</p> <p class="dragon-voice">"Well? What did the water and its sheds give up to thee?"</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Tell her what the docks are hiding</div>">> <<if setup.canCombineTap()>> <<set $supplyDocksReported = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "MiklaSupplyMidReport">> <</if>> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("island_supply_lines") && $questData.active["island_supply_lines"].step === "voyage">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice waits, expectant.</p> <p class="dragon-voice">"Thou hast a sea to cross, and a thing to learn from the crossing. Get thyself out on the water, as far as it will bear thee. Go."</p> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("island_supply_lines") && $questData.active["island_supply_lines"].step === "report_voyage">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice reaches for you, hungry for the last of it.</p> <p class="dragon-voice">"Thou hast the look of one the sea gave back. Tell me. Tell me what lies beyond the shore."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Tell her what lies beyond the shore</div>">> <<if setup.canCombineTap()>> <<set $supplyReported = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "MiklaSupplyReveal">> <</if>> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("island_supply_lines") && !setup.questSystem.isQuestActive("island_one_sky") && !setup.questSystem.isQuestCompleted("island_one_sky")>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs, and the voice comes up wearing that patient weight it takes on when it means to set you walking again.</p> <p class="dragon-voice">"Thou art returned, and there is a thing over thy head I would have thee truly see. Come closer."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Approach the pool</div>">> <<goto "MiklaSkyIntro">> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("island_one_sky") && $questData.active["island_one_sky"].step === "observe">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice settles, in no hurry.</p> <p class="dragon-voice">"Thou hast a sky to read. Three far corners in a day, the turn of the dawn, and the desert's little lie. Go, and look with thine own eyes."</p> </div> <<elseif setup.questSystem && setup.questSystem.isQuestActive("island_one_sky") && $questData.active["island_one_sky"].step === "report_sky">> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice rises to meet you, keen for the telling.</p> <p class="dragon-voice">"Well? What is the sky of this island, now that thou hast truly looked at it?"</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Tell her what the sky is</div>">> <<if setup.canCombineTap()>> <<set $skyReported = true>> <<set $skyRiteUnlocked = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "MiklaSkyReport">> <</if>> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("island_one_sky") && $dragonFreed>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The pool is dark and cool now, the pale fire gone out of it for good. The place where she was bound holds only cooling stone. She is loose in the world somewhere, and the mountain feels emptier for it.</p> <p class="dragon-voice">"Thou didst not turn back. I do not forget such things. Go and become what I gave thee."</p> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("island_one_sky") && !$dragonFreed && $dragonDirectiveGiven>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The pale fire coils in its pool, and her voice comes low and steady out of it, waiting on your shapes.</p> <p class="dragon-voice">"The bindings will not answer to one face. Come to them wearing the shapes that made them, one after the next, and we shall put this cold light out together."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Approach the bindings</div>">> <<goto "DragonBindings">> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("island_one_sky") && !$dragonFreed && !$dragonDirectiveGiven>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs, and this time the voice has the weight of a thing long promised and at last at hand.</p> <p class="dragon-voice">"Thou hast seen the whole shape of this cage now, road and water and sky. Good. Then it is time. Look upon the pale fire that holds me. It was not wrought by one hand, and it will not be unwrought by one shape. Thou art a thing of many faces, ember. Bring me each face it needs, and step by step we shall drown this cold light. Wilt thou?"</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn mikla-btn-primary'>I will unmake it</div>">> <<if setup.canCombineTap()>><<set $dragonDirectiveGiven = true>><<goto "DragonQueenChamber">><</if>> <</link>> </div> </div> <<elseif setup.questSystem && setup.questSystem.isQuestCompleted("island_supply_lines")>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice greets you, and holds its counsel a while longer.</p> <p class="dragon-voice">"Thou hast done well by me, little ember, and better than well. Rest. What comes next is heavier still, and not for tonight."</p> <p style="color:#9a8a70; font-size:14px; line-height:1.6; font-style:italic;">There is nothing more she asks of you yet. Whatever she means to do with what you have learned, she is not ready to say it.</p> </div> <<else>> <div style="max-width:640px; margin:0 auto;"> <p style="color:#c9b79a; font-size:16px; line-height:1.7;">The searing lava stirs as you return. The voice rises out of it once more.</p> <p class="dragon-voice">"Thou art returned. Good. I had begun to wonder if the ember had gone cold. Tell me thou hast not come with empty hands."</p> <p style="color:#9a8a70; font-size:14px; line-height:1.6; font-style:italic;">There is nothing more you can do for her yet. The way to unmake her prison has not yet shown itself.</p> </div> <</if>> <</if>> <<if $skyRiteUnlocked>> <div style="max-width:640px; margin:22px auto 0 auto; border:2px solid #b06a2c; border-radius:12px; padding:16px; background:linear-gradient(180deg,#1c130b,#0d0906);"> <p style="color:#f0cf95; font-size:15px; line-height:1.6; margin:0 0 12px 0;">The fire will turn the sky for you, if you bring it what it asks.</p> <div style="text-align:center;"><<link "<div class='mikla-btn'>Perform the Rite of the Sky</div>">><<goto "RiteOfTheSky">><</link>></div> </div> <</if>> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">> <<goto "VolcanoPeak">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VolcanoAltarActivation">> <<if $dragonEntranceOpen === undefined>><<set $dragonEntranceOpen = false>><</if>> <<run try { if (typeof navigator !== "undefined" && navigator.vibrate) navigator.vibrate([180,70,260,70,430,90,660]); } catch (e) {}>> <style> @keyframes fgQuake { 0%,100%{transform:translate(0,0);} 12%{transform:translate(-4px,3px);} 24%{transform:translate(5px,-3px);} 36%{transform:translate(-5px,-2px);} 48%{transform:translate(4px,4px);} 60%{transform:translate(-3px,3px);} 72%{transform:translate(4px,-3px);} 84%{transform:translate(-3px,-3px);} } @keyframes fgFlare { 0%,100%{ filter: drop-shadow(0 0 4px var(--gem)); transform:scale(1); } 50%{ filter: drop-shadow(0 0 20px var(--gem)) drop-shadow(0 0 36px var(--gem)); transform:scale(1.12); } } @keyframes fgFadeIn { from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:translateY(0); } } @keyframes fgRainbow { 0%{ text-shadow:0 0 10px hsl(0,90%,62%); } 17%{ text-shadow:0 0 10px hsl(52,90%,62%); } 34%{ text-shadow:0 0 10px hsl(130,80%,58%); } 50%{ text-shadow:0 0 10px hsl(190,90%,62%); } 67%{ text-shadow:0 0 10px hsl(255,90%,68%); } 84%{ text-shadow:0 0 10px hsl(315,90%,66%); } 100%{ text-shadow:0 0 10px hsl(360,90%,62%); } } .fg-basalt { background: linear-gradient(180deg,#2a2a2f 0%,#202024 55%,#161618 100%); min-height:100vh; padding:22px; } .fg-quake { animation: fgQuake 0.3s linear infinite; } .fg-ring { position:relative; width:min(600px,92vw); aspect-ratio:1; margin:26px auto; } .fg-cell { position:absolute; display:flex; align-items:center; justify-content:center; } .fg-gem { width:clamp(56px,11vw,86px); height:clamp(56px,11vw,86px); line-height:0; } .fg-gem svg { display:block; } .fg-activate .fg-filled { animation: fgFlare 3.6s ease-in-out infinite; } .fg-act-text { color:#efe9dd; font-size:16px; line-height:1.7; max-width:640px; margin:14px auto 0 auto; text-align:center; animation: fgFadeIn 1.6s ease both, fgRainbow 7s linear infinite; } </style> <div id="fg-activate-scene" class="fg-basalt fg-activate fg-quake"> <h1 style="color:#c9c9d2; text-align:center; text-shadow:0 2px 6px rgba(0,0,0,0.7); letter-spacing:1px;">The Ancient Altar</h1> <div class="fg-ring"> <<set _n = setup.flawlessGems.TYPES.length>> <<for _gi = 0; _gi < _n; _gi++>> <<set _gk = setup.flawlessGems.TYPES[_gi]>> <<set _ang = _gi / _n * 2 * Math.PI - Math.PI / 2>> <<set _lx = (50 + 42 * Math.cos(_ang)).toFixed(2)>> <<set _ly = (50 + 42 * Math.sin(_ang)).toFixed(2)>> <<set _pos = "position:absolute; left:" + _lx + "%; top:" + _ly + "%; transform:translate(-50%,-50%);">> <<print "<div class='fg-cell' style='" + _pos + "'>" + setup.flawlessGems.gemCell(_gk, "filled") + "</div>">> <</for>> </div> <div style="min-height:150px;"> <<timed 0.3s>> <p class="fg-act-text">The final gem sinks into its socket. For a breath, nothing. Then the stone remembers what it was made to do.</p> <</timed>> <<timed 2.6s>> <p class="fg-act-text">A rumble climbs up through your feet. The sixteen gems blaze awake all at once, each throwing its own color across the black basalt, and the whole peak shudders around you.</p> <</timed>> <<timed 5.4s>> <<run try { $("#fg-activate-scene").removeClass("fg-quake"); } catch (e) {}>> <p class="fg-act-text">Deep below, something gives. The lava in the crater draws back with a long groan of moving rock, and where there was only black stone a dark passage now yawns open, breathing heat.</p> <div style="text-align:center; margin-top:18px;"> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#ff5722 0%,#b03a17 100%); color:white; padding:15px 38px; border-radius:10px; font-weight:bold; font-size:16px; cursor:pointer; box-shadow:0 0 18px rgba(255,87,34,0.4);'>Descend into the passage</div>">> <<goto "DragonQueenChamber">> <</link>> </div> <</timed>> </div> </div> <</nobr>>
<<nobr>> <<set _firstMeet = !$veradinMet>> <<set $lastLocation = "VeradinTalk">> <<set $veradinMet = true>> <style> .vt-scene { background: radial-gradient(120% 80% at 50% 6%, #2a1a0e 0%, #160e09 50%, #0b0806 100%); min-height:100vh; padding:24px 16px 42px; } .vt-name { text-align:center; color:#f2b869; font-size:30px; font-family:'MedievalSharp','Papyrus',cursive; text-shadow:0 0 16px rgba(255,140,45,.45); margin:6px 0 0; letter-spacing:1px; } .vt-div { width:130px; height:3px; margin:9px auto 18px; border-radius:3px; background:linear-gradient(90deg,transparent,#d98a3d,transparent); } .vt-panel { max-width:620px; margin:0 auto; background:linear-gradient(180deg,#221708,#180f07); border:1px solid #5a3f20; border-radius:14px; padding:20px 22px; box-shadow:0 6px 22px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,180,90,.06); } .vt-narr { color:#b7a58c; font-family:Georgia,serif; font-style:italic; line-height:1.65; margin:0 0 14px; } .vt-say { color:#f0cf95; font-family:Georgia,serif; line-height:1.6; margin:0 0 14px; padding-left:14px; border-left:3px solid #b06a1e; } .vt-panel p:last-child { margin-bottom:0; } .vt-banner { margin-top:6px; background:linear-gradient(135deg,#3a2a12,#2a1d10); border:1px solid #d98a3d; border-radius:10px; padding:12px 14px; text-align:center; color:#ffd98a; font-weight:bold; font-family:Georgia,serif; box-shadow:0 0 16px rgba(217,138,61,.25); } .vt-back { text-align:center; margin-top:20px; } .vt-backbtn { display:inline-block; background:linear-gradient(135deg,#7a4a1e,#ad6c2b); color:#fff; padding:11px 28px; border-radius:8px; cursor:pointer; font-family:'MedievalSharp',cursive; box-shadow:0 3px 10px rgba(0,0,0,.4); } </style> <div class="vt-scene"> <h1 class="vt-name">Veradin Loyldxier</h1> <div class="vt-div"></div> <<if $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <div style="text-align:center; margin:0 auto 16px;"><img src="Images/NPCs/StaticNPCs/Veradin.webp" alt="Veradin Loyldxier" style="max-width:280px; max-height:460px; border-radius:12px; border:2px solid #d98a3d; box-shadow:0 0 22px rgba(217,138,61,0.4);" onerror="this.style.display='none';"></div> <</if>> <div class="vt-panel"> <<if !$veradinTrust and $foundVeradinHeirloom>> <<if _firstMeet>> <p class="vt-narr">The dwarf looks up from his anvil ready to bark at another gawker, and then he sees what you are cradling. The hammer stops mid swing. For a stranger to walk in off the cold mountain holding this, of all things, he has no words for a breath or two.</p> <p class="vt-narr">Then he takes the vase from your hands as if it were made of spun glass, and something in his hard face cracks open.</p> <<else>> <p class="vt-narr">You draw out the vase. The dwarf goes utterly still, the hammer frozen mid arc. For a long moment he only stares, then takes it from your hands as if it were made of spun glass, and something in his hard face cracks open.</p> <</if>> <p class="vt-say">"Ya have no idea what ya carried out of that sand. This is three hundred years of my kin, and I thought it gone forever." He clears his throat roughly, embarrassed by his own feeling. "A dwarf pays his debts. Ya want flawless stones, I can pull them from raw ore where a jeweler only sees rubble. Bring me yer rough gems and I will work them. It is a gamble every time, mind. The stone decides."</p> <<set $veradinTrust = true>> <div class="vt-banner">Veradin trusts you. His refining service is now open at the forge.</div> <<elseif !$veradinTrust and !$foundVeradinHeirloom>> <p class="vt-narr">The dwarf does not look up from his anvil at first. Sparks jump with every hammer fall. When he finally fixes you with a flat stare, his eyes are the grey of cooled iron.</p> <p class="vt-say">"Ya walked a long way to gawk at a workin smith. Speak or shift, I have no patience for either standin about."</p> <p class="vt-narr">You ask what he is doing so far from any hold. His jaw tightens.</p> <p class="vt-say">"That is my business. But since ya ask, and since ya found this place, I will trade ya honest. I lost somethin. An heirloom of my line, an old inscribed vase, taken from me on the crossin and carried off into those cursed ruins out in the sand. Bring it back and I will owe ya a smith's debt. And a dwarf pays his debts."</p> <p class="vt-say">"Til then, keep yer hands off my tools."</p> <<else>> <p class="vt-say">"Back again," the dwarf grunts, not unkindly. "Ya have gems for the fire, or are ya just here to watch an honest dwarf sweat?"</p> <</if>> </div> <div class="vt-back"> <<link "<div class='vt-backbtn'>Back to the forge</div>">><<goto "VeradinForge">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "VeradinForge">> <<set _hasF = Object.keys($flawlessGemInventory || {}).some(function(k){ return ($flawlessGemInventory[k]||0) > 0; })>> <<set _hasC = Object.keys($cutGemInventory || {}).some(function(k){ return ($cutGemInventory[k]||0) > 0 && setup.mining.CUT_GEM_BASE_PRICES[k] !== undefined; })>> <<set _hasR = $relicInventory && $relicInventory.length > 0>> <style> .vf-scene { background: radial-gradient(120% 80% at 50% 8%, #2c1b0f 0%, #180f0a 48%, #0b0806 100%); min-height:100vh; padding:22px 16px 44px; } .vf-title { text-align:center; color:#f2b869; font-size:32px; margin:4px 0 2px; font-family:'MedievalSharp','Papyrus',cursive; text-shadow:0 0 18px rgba(255,140,45,0.5); letter-spacing:1px; } .vf-embers { width:130px; height:4px; margin:4px auto 0; border-radius:3px; background:linear-gradient(90deg,transparent,#ff7a1a,#ffcf6b,#ff7a1a,transparent); box-shadow:0 0 12px #ff7a1a; } .vf-intro { color:#c39a6b; max-width:540px; margin:14px auto 22px; text-align:center; font-size:15px; line-height:1.6; font-family:Georgia,serif; } .vf-actions { max-width:520px; margin:0 auto; display:flex; flex-direction:column; gap:13px; } .vf-card { display:flex; align-items:center; gap:15px; padding:16px 18px; border-radius:12px; cursor:pointer; border:1px solid #6a4420; background:linear-gradient(135deg,#241708,#180f07); box-shadow:0 4px 14px rgba(0,0,0,.45), inset 0 1px 0 rgba(255,180,90,.08); transition:transform .12s, border-color .12s, box-shadow .12s; } .vf-card:hover { transform:translateY(-2px); border-color:#d98a3d; box-shadow:0 6px 20px rgba(0,0,0,.5), 0 0 16px rgba(217,138,61,.25); } .vf-ico { font-size:26px; width:38px; text-align:center; } .vf-cname { color:#f0c98a; font-size:18px; font-weight:bold; font-family:'MedievalSharp','Papyrus',cursive; } .vf-cdesc { color:#a8906f; font-size:13.5px; font-family:Georgia,serif; margin-top:1px; } .vf-wares { max-width:520px; margin:22px auto 0; padding:14px 16px; border-radius:12px; border:1px solid #4a3a22; background:rgba(20,13,7,0.6); } .vf-wares-h { text-align:center; color:#d98a3d; font-size:20px; margin:0 0 4px; font-family:'MedievalSharp','Papyrus',cursive; } .vf-leave { text-align:center; margin-top:24px; } .vf-leavebtn { display:inline-block; background:#2a211a; color:#c8b294; padding:10px 26px; border-radius:8px; cursor:pointer; font-family:Georgia,serif; border:1px solid #4a3a2a; } .vf-leavebtn:hover { background:#3a2d20; color:#e8d5b5; } </style> <div class="vf-scene"> <h1 class="vf-title">⚒️ Veradin's Forge</h1> <div class="vf-embers"></div> <<if $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <div style="text-align:center; margin:8px auto 2px;"><img src="Images/NPCs/StaticNPCs/Veradin.webp" alt="Veradin Loyldxier" style="max-width:240px; max-height:400px; border-radius:12px; border:2px solid #d98a3d; box-shadow:0 0 22px rgba(217,138,61,0.4);" onerror="this.style.display='none';"></div> <</if>> <p class="vf-intro">A squat stone forge wedged into the mountainside, roaring with heat. Ingots, half finished blades, and a barrel of rough stones crowd every surface.</p> <div class="vf-actions"> <<link "<div class='vf-card'><div class='vf-ico'>💬</div><div><div class='vf-cname'>Speak with Veradin</div><div class='vf-cdesc'>Trade words with the gruff old smith.</div></div></div>">><<goto "VeradinTalk">><</link>> <<if $hasClawToothNecklace && !$veradinHasClawTooth>> <<link "<div class='vf-card'><div class='vf-ico'>🔨</div><div><div class='vf-cname'>Give the Hammer of the Fire Giants</div><div class='vf-cdesc'>Hand the mighty hammer to the smith.</div></div></div>">> <<if setup.canCombineTap()>> <<set $veradinHasClawTooth = true>> <<set $hasClawToothNecklace = false>> <<if $ownedArtifacts>><<set _ci = $ownedArtifacts.indexOf("Hammer of the Fire Giants")>><<if _ci !== -1>><<run $ownedArtifacts.splice(_ci, 1)>><</if>><</if>> <<goto "VeradinClawTooth">> <</if>> <</link>> <</if>> <<if $veradinTrust>> <<link "<div class='vf-card'><div class='vf-ico'>⚒️</div><div><div class='vf-cname'>The Refining Fire</div><div class='vf-cdesc'>Feed rough stones to the anvil and gamble for flawless gems.</div></div></div>">><<goto "VeradinRefine">><</link>> <</if>> </div> <<if _hasF or _hasC or _hasR>> <div class="vf-wares"> <div class="vf-wares-h">Sell to Veradin</div> <<include "_GemRelicSell">> </div> <</if>> <<if setup.islandLore.isAskable("Veradin")>> <div style="background:linear-gradient(135deg,#1a1430,#0e0a1c); border:2px solid #7a6aa8; border-radius:10px; padding:14px 16px; margin:0 auto 15px; max-width:620px;"> <p style="color:#cdbdf0; font-size:15px; line-height:1.6; margin:0 0 10px 0;">You steer the talk toward the island itself. How does this place work? How long has it stood?</p> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#7a6aa8,#4a3d70); color:white; padding:9px 22px; border-radius:9px; font-weight:bold; cursor:pointer;'>Ask about the island</div>">> <<if setup.canCombineTap()>> <<set $lastLocationBeforeAsk = $lastLocation>> <<run setup.islandLore.recordAsk("Veradin")>> <<goto "IslandLoreAccount">> <</if>> <</link>> </div> <</if>> <div class="vf-leave"> <<link "<div class='vf-leavebtn'>Leave the forge</div>">><<goto "Mountains">><</link>> </div> </div> <</nobr>>
<<nobr>> <style> .grs { font-family:Helmet,Freesans,sans-serif; } .grs-h { font-family:'MedievalSharp','Papyrus',cursive; font-size:16px; margin:12px 0 6px; letter-spacing:.5px; border-bottom:1px solid rgba(255,180,90,.15); padding-bottom:4px; } .grs-hf{color:#ffd98a;} .grs-hc{color:#cdd4de;} .grs-hr{color:#d6a94f;} .grs-row { display:flex; justify-content:space-between; align-items:center; gap:10px; padding:7px 10px; border-radius:8px; margin-bottom:5px; background:rgba(255,255,255,0.025); } .grs-l { color:#e8dcc6; font-size:14px; display:flex; align-items:center; gap:9px; flex-wrap:wrap; } .grs-dot { width:12px; height:12px; border-radius:50%; box-shadow:0 0 6px currentColor; flex:none; } .grs-q { color:#fff; font-weight:bold; } .grs-p { color:#7ddf9a; font-size:12.5px; } .grs-b { font-size:13px; white-space:nowrap; } .grs-empty { color:#8a7a68; text-align:center; padding:12px; font-family:Helmet,Freesans,sans-serif; } </style> <div id="gem-relic-sell" class="grs"> <<set _sb = setup.mining.getActiveTfBuffs()>> <<set _pm = (_sb.gemSalePriceMult && _sb.gemSalePriceMult > 0) ? _sb.gemSalePriceMult : 1>> <<set _hp = ($currentArtifact === "The Pearl of Abundance") || ($physicalTraits && $physicalTraits.indexOf("Naiad") !== -1)>> <<set _pearl = _hp ? 1.5 : 1>> <<set _mult = _pm * _pearl>> <<set _hasF = Object.keys($flawlessGemInventory || {}).some(function(k){ return ($flawlessGemInventory[k]||0) > 0; })>> <<set _hasC = Object.keys($cutGemInventory || {}).some(function(k){ return ($cutGemInventory[k]||0) > 0 && setup.mining.CUT_GEM_BASE_PRICES[k] !== undefined; })>> <<set _hasR = $relicInventory && $relicInventory.length > 0>> <<if !_hasF and !_hasC and !_hasR>> <div class="grs-empty">Nothing to sell right now.</div> <</if>> <<if _hasF>> <div class="grs-h grs-hf">Flawless Gems</div> <<for _fid range setup.jewelers.CUTTABLE_GEMS>><<capture _fid>> <<set _fq = ($flawlessGemInventory[_fid] || 0)>> <<if _fq > 0>> <<set _fp = Math.floor(setup.mining.flawlessGemPrice(_fid) * _mult)>> <div class="grs-row"><span class="grs-l"><span class="grs-dot" style="color:<<= setup.flawlessGems.color(_fid)>>; background:<<= setup.flawlessGems.color(_fid)>>;"></span><<= setup.mining._prettyName(_fid)>> <span class="grs-q">x<<= _fq>></span> <span class="grs-p">$<<= _fp>> ea</span></span><span class="grs-b"><<link "Sell 1">><<if setup.canCombineTap()>><<run setup.mining.sellFlawlessGem(_fid,1)>><<replace "#gem-relic-sell">><<include "_GemRelicSell">><</replace>><</if>><</link>> · <<link "All">><<if setup.canCombineTap()>><<run setup.mining.sellFlawlessGem(_fid, ($flawlessGemInventory[_fid] || 0))>><<replace "#gem-relic-sell">><<include "_GemRelicSell">><</replace>><</if>><</link>></span></div> <</if>> <</capture>><</for>> <</if>> <<if _hasC>> <div class="grs-h grs-hc">Cut Gems</div> <<for _cid range setup.jewelers.CUTTABLE_GEMS>><<capture _cid>> <<set _cq = ($cutGemInventory[_cid] || 0)>> <<if _cq > 0>> <<set _cp = Math.floor(setup.mining.CUT_GEM_BASE_PRICES[_cid] * _mult)>> <div class="grs-row"><span class="grs-l"><span class="grs-dot" style="color:<<= setup.flawlessGems.color(_cid)>>; background:<<= setup.flawlessGems.color(_cid)>>; opacity:.75;"></span><<= setup.mining._prettyName(_cid)>> <span class="grs-q">x<<= _cq>></span> <span class="grs-p">$<<= _cp>> ea</span></span><span class="grs-b"><<link "Sell 1">><<if setup.canCombineTap()>><<run setup.mining.sellCutGem(_cid,1)>><<replace "#gem-relic-sell">><<include "_GemRelicSell">><</replace>><</if>><</link>> · <<link "All">><<if setup.canCombineTap()>><<run setup.mining.sellCutGem(_cid, ($cutGemInventory[_cid] || 0))>><<replace "#gem-relic-sell">><<include "_GemRelicSell">><</replace>><</if>><</link>></span></div> <</if>> <</capture>><</for>> <</if>> <<if _hasR>> <div class="grs-h grs-hr">Relics</div> <<for _ri = 0; _ri < $relicInventory.length; _ri++>><<capture _ri>> <<set _rel = $relicInventory[_ri]>> <div class="grs-row"><span class="grs-l"><span class="grs-dot" style="color:#c2953a; background:#c2953a;"></span><<print _rel.name>> <span class="grs-p">$<<print Math.floor(_rel.value * _mult)>></span></span><span class="grs-b"><<link "Sell">><<if setup.canCombineTap()>><<run $money = ($money || 0) + Math.floor($relicInventory[_ri].value * _mult)>><<run $relicInventory.splice(_ri, 1)>><<run try { SugarCube.UIBar.update(); } catch (e) {}>><<replace "#gem-relic-sell">><<include "_GemRelicSell">><</replace>><</if>><</link>></span></div> <</capture>><</for>> <</if>> </div> <</nobr>>
<<set $lastLocation = "VeradinRefine">> <<if !$veradinTrust>><<goto "VeradinForge">><</if>> <style> .fr-scene { background: radial-gradient(120% 85% at 50% 6%, #2c1b0f 0%, #180f0a 46%, #0b0806 100%); min-height:100vh; padding:18px 14px 44px; } .fr-title { text-align:center; color:#f2b869; font-size:30px; margin:6px 0 2px; letter-spacing:1px; font-family:'MedievalSharp','Papyrus',cursive; text-shadow:0 0 18px rgba(255,140,45,0.5); } .fr-sub { text-align:center; color:#c39a6b; max-width:560px; margin:0 auto 28px; font-size:15px; line-height:1.55; font-family:Georgia,serif; } .fr-stage { position:relative; width:min(560px,94vw); height:200px; margin:12px auto 8px; } .fr-bed { position:absolute; left:50%; top:152px; transform:translateX(-50%); width:82%; height:32px; border-radius:50%; background:radial-gradient(ellipse at 50% 50%, rgba(255,150,45,0.55), rgba(255,88,20,0.22) 50%, transparent 78%); filter:blur(3px); animation:frBed 2.6s ease-in-out infinite; } @keyframes frBed { 0%,100%{opacity:.7; transform:translateX(-50%) scale(1);} 50%{opacity:1; transform:translateX(-50%) scale(1.05);} } .fr-anvil { position:absolute; left:50%; bottom:12px; transform:translateX(-50%); width:min(196px,52%); height:118px; z-index:2; cursor:pointer; transition:transform .12s, filter .12s; } .fr-anvil.fr-over { transform:translateX(-50%) scale(1.06); filter:drop-shadow(0 0 15px rgba(255,175,65,.85)); } .fr-anvil.fr-hit { animation:frHit .22s ease; } @keyframes frHit { 0%{transform:translateX(-50%);} 30%{transform:translateX(-50%) translateY(5px) scale(.985);} 100%{transform:translateX(-50%);} } .fr-hint { position:absolute; left:50%; top:6px; transform:translateX(-50%); color:#e9b26a; font-size:13.5px; opacity:.78; letter-spacing:.4px; white-space:nowrap; font-family:Georgia,serif; } .fr-sparks, .fr-reveal { position:absolute; inset:0; pointer-events:none; z-index:9; } .fr-spark { position:absolute; border-radius:50%; box-shadow:0 0 6px currentColor; transition:transform .68s cubic-bezier(.15,.7,.3,1), opacity .68s ease-in; } .fr-reveal { display:flex; align-items:center; justify-content:center; z-index:12; } .fr-result { display:flex; flex-direction:column; align-items:center; gap:6px; animation:frPop .42s cubic-bezier(.2,1.5,.4,1); transition:opacity .55s, transform .55s; } .fr-result.fr-fade { opacity:0; transform:translateY(-14px); } @keyframes frPop { 0%{transform:scale(.3) translateY(24px); opacity:0;} 100%{transform:scale(1) translateY(0); opacity:1;} } .fr-gem { width:96px; height:96px; } .fr-gem.fr-flawless { animation:frGlow 1.6s ease-in-out infinite; } @keyframes frGlow { 0%,100%{filter:drop-shadow(0 0 8px var(--gem)) drop-shadow(0 0 16px var(--gem));} 50%{filter:drop-shadow(0 0 15px var(--gem)) drop-shadow(0 0 33px var(--gem));} } .fr-gem.fr-cut { filter:saturate(.82) brightness(.9); opacity:.94; } .fr-rlabel { font-size:18px; font-weight:bold; font-family:'MedievalSharp','Papyrus',cursive; } .fr-flaw { color:#ffe9a8; text-shadow:0 0 11px #ffae3a; } .fr-cutl { color:#ccd3dd; } .fr-lostl { color:#8a7a68; } .fr-dust { width:74px; height:74px; border-radius:50%; background:radial-gradient(circle,#6b5b48,transparent 70%); animation:frDust .8s ease-out forwards; } @keyframes frDust { 0%{transform:scale(.4); opacity:.85;} 100%{transform:scale(1.7); opacity:0;} } .fr-tally { display:flex; gap:18px; justify-content:center; margin:4px 0 14px; font-family:Georgia,serif; font-size:14px; } .fr-tf{color:#ffd98a;} .fr-tc{color:#b9c2cf;} .fr-tl{color:#7d6f5e;} .fr-rack { display:flex; flex-wrap:wrap; gap:12px; justify-content:center; max-width:600px; margin:0 auto; position:relative; z-index:20; } .fr-stone { position:relative; width:74px; cursor:pointer; text-align:center; user-select:none; -webkit-user-select:none; -webkit-touch-callout:none; transition:transform .12s; } .fr-stone:hover { transform:translateY(-3px); } .fr-stone:active { transform:scale(0.95); } .fr-stone-gem { width:54px; height:54px; margin:0 auto; filter:drop-shadow(0 3px 4px rgba(0,0,0,.55)); } .fr-stone-badge { position:absolute; top:-3px; right:7px; background:#7a4a1e; color:#fff; font-size:12px; font-weight:bold; border-radius:10px; padding:1px 7px; box-shadow:0 1px 3px rgba(0,0,0,.5); font-family:Georgia,serif; } .fr-stone-name { font-size:11.5px; color:#c9a06c; margin-top:2px; font-family:Georgia,serif; } .fr-empty { color:#8a7a68; text-align:center; padding:22px 12px; font-family:Georgia,serif; } .fr-ghost { position:fixed; width:54px; height:54px; margin-left:-27px; margin-top:-27px; pointer-events:none; z-index:9999; filter:drop-shadow(0 0 10px rgba(255,165,65,.75)); } .fr-back { text-align:center; margin-top:20px; } .fr-flash { position:absolute; inset:0; opacity:0.9; transition:opacity .5s ease-out; pointer-events:none; z-index:5; background:radial-gradient(circle at 50% 42%, rgba(255,242,200,0.9), rgba(255,180,60,0.3) 40%, transparent 68%); } .fr-ring { position:absolute; left:50%; top:46px; width:16px; height:16px; margin:-8px 0 0 -8px; border:3px solid #fff; border-radius:50%; opacity:0.9; animation:frRing .72s ease-out forwards; pointer-events:none; } @keyframes frRing { to { width:200px; height:200px; margin:-100px 0 0 -100px; opacity:0; border-width:1px; } } .fr-debris { position:absolute; box-shadow:0 0 2px rgba(0,0,0,0.4); transition:transform .95s cubic-bezier(.2,.6,.4,1), opacity .95s ease-in; z-index:6; } .fr-gem.fr-big { width:112px; height:112px; } .fr-gem.fr-big.fr-flawless { animation:frGlowBig 1.3s ease-in-out infinite; } @keyframes frGlowBig { 0%,100%{filter:drop-shadow(0 0 12px var(--gem)) drop-shadow(0 0 24px var(--gem));} 50%{filter:drop-shadow(0 0 24px var(--gem)) drop-shadow(0 0 46px var(--gem));} } .fr-result { position:relative; } </style> <div class="fr-scene"> <h1 class="fr-title">The Refining Fire</h1> <p class="fr-sub">Veradin waits at his anvil, hammer resting on one shoulder. "Feed a rough stone to the fire. Some come out flawless, some settle for a clean cut, and some the fire simply keeps. That is the bargain."</p> <div id="fr-root"></div> <div class="fr-back"> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#7a4a1e,#ad6c2b); color:#fff; padding:12px 30px; border-radius:8px; font-weight:bold; cursor:pointer; font-family:MedievalSharp,cursive; box-shadow:0 3px 10px rgba(0,0,0,.5);'>Back to the forge</div>">> <<goto "VeradinForge">> <</link>> </div> </div>
<<if $lastRefine and $lastRefine.refined>> <div style="background:#2a1d10; border:1px solid #d98a3d; border-radius:8px; padding:12px; margin:10px auto; max-width:520px; text-align:center; color:#ffd27f;"> Refined <<print $lastRefine.refined>> raw <<print setup.mining._prettyName($lastRefine.gemId)>>: <strong><<print $lastRefine.flawless>></strong> flawless, <strong><<print $lastRefine.cut>></strong> cut, <strong><<print $lastRefine.lost>></strong> lost to the fire. </div> <</if>> <<set _hasRaw = Object.keys($gemInventory || {}).some(function(k){ return ($gemInventory[k]||0) > 0 && setup.jewelers.CUTTABLE_GEMS.indexOf(k) !== -1; })>> <<if !_hasRaw>> <p style="color:#999; text-align:center;">You have no raw gems to refine.</p> <<else>> <div style="max-width:520px; margin:0 auto; background:#2a1d10; border:1px solid #7a4a1e; border-radius:10px; padding:12px;"> <<for _gid range setup.jewelers.CUTTABLE_GEMS>> <<capture _gid>> <<set _gq = ($gemInventory[_gid] || 0)>> <<if _gq > 0>> <div style="display:flex; justify-content:space-between; align-items:center; padding:5px 8px; border-bottom:1px solid #3a2a1a;"> <span style="color:#e8d5b5;"><<= setup.mining._prettyName(_gid)>>: <strong><<= _gq>></strong></span> <span style="font-size:13px;"><<link "Refine 1">><<set $lastRefine = setup.mining.refineGem(_gid, 1)>><<replace "#refine-dynamic">><<include "_VeradinRefineList">><</replace>><</link>><<if _gq >= 5>> | <<link "Refine 5">><<set $lastRefine = setup.mining.refineGem(_gid, 5)>><<replace "#refine-dynamic">><<include "_VeradinRefineList">><</replace>><</link>><</if>> | <<link "Refine all">><<set $lastRefine = setup.mining.refineGem(_gid, ($gemInventory[_gid] || 0))>><<replace "#refine-dynamic">><<include "_VeradinRefineList">><</replace>><</link>></span> </div> <</if>> <</capture>> <</for>> </div> <</if>>
<<nobr>> <<set _v = $islandLoreViewing>> <div style="background:#0d0b14; min-height:100vh; padding:34px 20px;"> <div style="max-width:640px; margin:0 auto; background:rgba(18,15,28,0.85); border:1px solid #4a3d63; border-radius:14px; padding:24px 26px;"> <<if _v === "Clair">> <p style="color:#d9c9ff; font-size:16px; line-height:1.75; font-style:italic;">Clair tips her head, delighted you asked. "This island? It is not only what your feet find. It sits where a great many places lean against one another, and the wall between them is thin here, thin as a held breath. I have watched things slip through when no one was looking." She smiles, and says no more of it, though you feel there is a great deal more she could. "You live on the skin of something far larger, Wanderer. Most never feel it. You will."</p> <<elseif _v === "Flona Vulri">> <p style="color:#cfe8f5; font-size:16px; line-height:1.75;">Flona is quiet a while before she answers, the way she always is with things that matter. <span style="color:#e8c98a;">"This is an old place, little traveler. Older than the maps, older than the hands that drew them. I have been here longer than I can rightly say, and even I do not know where its edges truly lie."</span> She watches the far white distance. <span style="color:#e8c98a;">"There are places out past the cold where the world feels thin, like a curtain you could push a hand through. I have never tried. Some doors are kinder left shut."</span> She says nothing more on that one.</p> <<elseif _v === "Xantria Galdenentri">> <p style="color:#e6d3ff; font-size:16px; line-height:1.75;">Xantria's eyes sharpen the moment you ask, as if you touched something live. "The island. Yes. You feel it too, good, good. It is not plain ground under us. It hums. It remembers." Her fingers trace a shape in the air you do not recognise. "There are old wards here. Seams in the world. A wall you cannot see but could walk straight into, if you were unlucky, or looking for it. I have looked." Then she blinks, and waves it all away. "But that is a long tale, and walls have ears. Another time."</p> <<elseif _v === "Quesha Epo">> <p style="color:#ddeef5; font-size:16px; line-height:1.75;">Quesha trails her fingers through the water and thinks about it. "The island? It is quiet, if you let it be. The tides keep their own time here, and the water is always talking to anyone who slows down enough to listen." She smiles at some old memory. "My grandmother knew every current off these shores. She used to say the sea raised this place and the sea will take it back one day, in no hurry at all. I like that. No hurry."</p> <<elseif _v === "Roisin Sullivan">> <p style="color:#e8dcff; font-size:16px; line-height:1.75;">"The island?" Roisin snorts, but not unkindly. "Aye, it is a good rock. Small enough that everyone knows your business, big enough you can lose them when you want to." She nods out at the water. "Tides are honest, the surf is better than it has any right to be, and the coffee in town is worse than it should be. Right then. That is the island. You want poetry, go ask someone who has been here longer than me." She grins.</p> <<elseif _v === "Veradin">> <p style="color:#f0cf95; font-size:16px; line-height:1.75;">Veradin grunts, not looking up from the anvil. "Ya want to know about this island? Ask the sea, not me. I came in on the crossin like anyone with sense would, cold water and colder nights, and I have not strayed far from this forge since." He turns a glowing bar. "It is decent stone country, I will grant it that. The mountains have good bones. Past that, it is not my island to explain. A dwarf tends his own fire."</p> <<elseif _v === "Revna McKraken">> <p style="color:#e0c8ff; font-size:16px; line-height:1.75;">Revna does not look up from the ledger for a long moment. "The island." She says it flatly, as if weighing whether the question earns an answer. "People come. People go. The shop stays. That is most of what there is to know." She marks a line in the book. "The rest is in the tomes, if you have the coin and the patience for them. I do not give lectures." The subject, plainly, is closed.</p> <<else>> <p style="color:#bbb; font-size:16px; line-height:1.75;">You turn the conversation elsewhere.</p> <</if>> <div style="text-align:center; margin-top:24px;"> <<link "<div style='display:inline-block; background:linear-gradient(135deg,#5a4a7a,#3a2f52); color:#efe7ff; padding:12px 30px; border-radius:10px; font-weight:bold; cursor:pointer;'>Step back</div>">> <<goto $lastLocationBeforeAsk || $preNPCLocation || "The Nest">> <</link>> </div> </div> </div> <</nobr>>
<<nobr>> <style> .vct-scene { background: radial-gradient(120% 80% at 50% 6%, #2a1a0e 0%, #160e09 50%, #0b0806 100%); min-height:100vh; padding:24px 16px 42px; } .vct-name { text-align:center; color:#f2b869; font-size:30px; font-family:'MedievalSharp','Papyrus',cursive; text-shadow:0 0 16px rgba(255,140,45,.45); margin:6px 0 0; letter-spacing:1px; } .vct-div { width:130px; height:3px; margin:9px auto 18px; border-radius:3px; background:linear-gradient(90deg,transparent,#d98a3d,transparent); } .vct-panel { max-width:620px; margin:0 auto; background:linear-gradient(180deg,#221708,#180f07); border:1px solid #5a3f20; border-radius:14px; padding:20px 22px; box-shadow:0 6px 22px rgba(0,0,0,.45); } .vct-narr { color:#b7a58c; font-family:Georgia,serif; font-style:italic; line-height:1.65; margin:0 0 14px; } .vct-say { color:#f0cf95; font-family:Georgia,serif; line-height:1.6; margin:0 0 14px; padding-left:14px; border-left:3px solid #b06a1e; } .vct-back { text-align:center; margin-top:20px; } .vct-backbtn { display:inline-block; background:linear-gradient(135deg,#7a4a1e,#ad6c2b); color:#fff; padding:11px 28px; border-radius:8px; cursor:pointer; font-family:'MedievalSharp',cursive; } </style> <div class="vct-scene"> <h1 class="vct-name">Veradin Loyldxier</h1> <div class="vct-div"></div> <div class="vct-panel"> <p class="vct-narr">Veradin's knees dip as the great hammer settles into his hands, heavier than its size has any right to be. He runs a thumb along the black iron head, mutters somethin low under his breath in a tongue you do not know, the words rough and old as a keel dragged over stone. For a moment he is somewhere else entirely.</p> <p class="vct-say">"This is giant work. Fire giant, if I know my marks, and I know my marks. Where ya came by it is yer own business, and I will not ask." He sets it by the anvil, near reverent, and nods gruff to cover the shine in his eye. "My thanks. The fire will run truer with this at the forge. Bring me yer rough stones and ya will see."</p> </div> <div class="vct-back"> <<link "<div class='vct-backbtn'>Back to the forge</div>">><<goto "VeradinForge">><</link>> </div> </div> <</nobr>>
<<nobr>> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mir-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mir-wrap { max-width:640px; margin:0 auto; } .mir-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mir-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } .mir-banner { margin-top:14px; background:linear-gradient(135deg,#3a2a12,#2a1d10); border:1px solid #d98a3d; border-radius:10px; padding:12px 14px; text-align:center; color:#ffd98a; font-weight:bold; } </style> <div class="mir-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mir-wrap"> <p class="mir-p">The pale light shifts as you speak, listening. You tell them what the island's people gave you. The tides and the seasons, the small strange quiet of the place, and the old thin edges some of them spoke of and would not explain.</p> <p class="mir-voice">"So. Thou hast eyes after all, and the wit to use them. Good. Now thou beginnest to see the cage as I do."</p> <p class="mir-p">The pale fire gutters, and something heaves up out of the pool to land at your feet with a weight that cracks the stone. A great smith's hammer, its head black iron veined with slow cooling gold, the haft wrapped in scorched leather. The heat rolling off it is fierce, and somehow not unkind.</p> <p class="mir-voice">"Take it. It was wrought by the fire giants, in an age when I owned a great many things. Carry it to the one who works stone and fire on the mountain. Tell them nothing of me. They will know its worth, or their blood will."</p> <div class="mir-banner">Received: Hammer of the Fire Giants (minor artifact).</div> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">> <<goto "VolcanoPeak">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaCityIntro">> <<if !$miklaArrivalAnswer>><<set $miklaArrivalAnswer = "">><</if>> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mci-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mci-wrap { max-width:640px; margin:0 auto; } .mci-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mci-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mci-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mci-wrap"> <<if $miklaArrivalAnswer === "">> <p class="mci-p">The searing lava turns over on itself, and the voice settles, unhurried, as though it has all the centuries in the world to spend on you.</p> <p class="mci-voice">"Before I set thee to thy task, tell me true. How didst thou come to this island? Cast thy mind back to the first of it."</p> <div style="text-align:center; margin-top:20px;"> <<link "<div class='mikla-btn'>I woke in an alley with nothing to my name. I do not remember arriving.</div>">> <<if setup.canCombineTap()>><<set $miklaArrivalAnswer = "alley">><<goto "MiklaCityIntro">><</if>> <</link>> <br><br> <<link "<div class='mikla-btn'>There was a dark place, and a voice, and then I simply was here.</div>">> <<if setup.canCombineTap()>><<set $miklaArrivalAnswer = "dark">><<goto "MiklaCityIntro">><</if>> <</link>> <br><br> <<link "<div class='mikla-btn'>I dreamed, I think. And when the dream let go, the island had me.</div>">> <<if setup.canCombineTap()>><<set $miklaArrivalAnswer = "dream">><<goto "MiklaCityIntro">><</if>> <</link>> <<if $clairFirstMeetingDone>> <br><br> <<link "<div class='mikla-btn'>It was like a dream. And I have since met one who dwells inside such places.</div>">> <<if setup.canCombineTap()>><<set $miklaArrivalAnswer = "clair">><<goto "MiklaCityIntro">><</if>> <</link>> <</if>> </div> <<else>> <p class="mci-voice">"Aye. As I thought. Not one soul on this rock can tell me how they came, only that they woke. No ship. No shore. Only the waking. Hold that. It matters."</p> <<if $miklaArrivalAnswer === "clair">> <p class="mci-voice">"A dweller in dreams. So. Then the way in and the way out may be the same door, and someone keeps it. Remember that, when the time comes."</p> <</if>> <p class="mci-p">The lava dims, gathering itself, and when the voice returns it is edged with purpose.</p> <p class="mci-voice">"Now. I would have thee look at this island the way I have been made to look at it. Two things. Go to the seat of its power, the hall where its rulers are said to sit, and search it. Tell me what governs here, if aught governs at all."</p> <p class="mci-voice">"And this. Walk among its people and find me a child. A babe in arms, a girl with scabs on her knees, a mother heavy with one yet to come. Look everywhere thou canst. Then come back and tell me true what thou didst find."</p> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Set out</div>">> <<if setup.canCombineTap()>> <<if setup.questSystem && !setup.questSystem.isQuestActive("mikla_investigate_city") && !setup.questSystem.isQuestCompleted("mikla_investigate_city")>> <<run setup.questSystem.startQuest("mikla_investigate_city")>> <</if>> <<goto "VolcanoPeak">> <</if>> <</link>> </div> <</if>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "TownHallInvestigate">> <style> .thi-scene { background:#141018; min-height:100vh; padding:30px 20px; } .thi-wrap { max-width:660px; margin:0 auto; } .thi-p { color:#cfc3d6; font-size:16px; line-height:1.75; } .thi-sun { color:#ffd27a; font-weight:bold; } .thi-magic { margin-top:14px; background:linear-gradient(135deg,#241636,#160f24); border:1px solid #7a4fd0; border-radius:10px; padding:14px; color:#d7c3ff; font-style:italic; line-height:1.7; } </style> <div class="thi-scene"> <h1 style="color:#b19cd9; text-align:center;">The Offices Behind the Offices</h1> <div class="thi-wrap"> <p class="thi-p">You let yourself into the rooms the public never sees, and you begin to read the place the way you would read a person you did not trust.</p> <p class="thi-p">It does not hold together. The drawers are full of forms, and every form is blank. There is a ledger for the city budget, ruled into neat columns, and not one column holds a number. There are laws bound in leather, and the laws name offices that name other offices that circle back and name no one at all. A great seal sits on the desk. When you press it into wax it leaves a clean, meaningless ring. Nothing here governs anything. The mayor is a coat that someone puts on. It is not an office. It is a costume, and the city wears it so it need not admit that no one holds the wheel.</p> <p class="thi-p">And there is the other thing. Once you see it you cannot stop seeing it. Worked into the cornice, pressed into the wax, cut small at the foot of every doorframe, is the <span class="thi-sun">sunfish</span>. The same mark the island is named for. Not a flourish. A signature, laid down again and again by a hand that wanted this building to belong to it.</p> <<if setup.mikla && setup.mikla.hasMythicalPerception && setup.mikla.hasMythicalPerception()>> <div class="thi-magic">There is more, and only the changed can feel it. Where your eye finds a sunfish, something answers. A low warmth, a pressure behind the eyes, the sense of a breath held for a very long time. The marks are not idle. They are working, quietly, the way a lock works whether or not anyone watches the door. Whatever truly governs this island, it is not in the ledgers. It is in these.</div> <</if>> <p class="thi-p" style="margin-top:18px; color:#9a8fa6; font-style:italic;">You have what you came for. She will want to hear of this.</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Back to the Town Hall</div>">> <<goto "TownHall">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaChildCheck">> <<if !Array.isArray($miklaChildCheckLocations)>><<set $miklaChildCheckLocations = []>><</if>> <<set _checked = $miklaChildCheckLocations.length>> <<set _place = $miklaChildCheckLast || "Downtown">> <style> .mcc-scene { background:#0a0d12; min-height:100vh; padding:30px 20px; } .mcc-wrap { max-width:640px; margin:0 auto; } .mcc-p { color:#bcc6d2; font-size:16px; line-height:1.75; } .mcc-count { margin-top:16px; text-align:center; color:#8aa0b8; font-size:14px; font-style:italic; } </style> <div class="mcc-scene"> <h1 style="color:#7fb0d8; text-align:center;">No Small Shoes</h1> <div class="mcc-wrap"> <p class="mcc-p">You look, and you keep looking, the way she asked. And the more carefully you look, the stranger the quiet becomes.</p> <p class="mcc-p">There are no children here. Not one. There is a bench worn smooth where a swing set never squeaks, a shop of clothes with nothing cut small, a clinic with no mother waiting and no cradle in the corner. No one is heavy with child. No one carries a babe on a hip. The people go about their day and none of them seem to notice the absence, as though the thought slides off them before it can catch. It catches on you. You cannot make it let go.</p> <div class="mcc-count"> <<if _checked >= 5>> You have looked in <<print _checked>> places now. It is the same everywhere. That is answer enough. <<else>> Places searched: <<print _checked>> of 5. <</if>> </div> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Keep looking</div>">> <<goto _place>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaCityReport">> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mcr-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mcr-wrap { max-width:640px; margin:0 auto; } .mcr-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mcr-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mcr-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mcr-wrap"> <p class="mcr-p">You tell her what you found. The hollow hall, the blank ledgers, the mark of the sunfish pressed into every quiet corner of the place that pretends to rule. And then the other thing. The bench with no child on it. The shops with nothing small. A whole island, and not one babe in it.</p> <p class="mcr-voice">"So. Thou hast seen it, and thou hast not looked away. Good. Most do. Most cannot bear to hold the thought, and so the island lets them set it down."</p> <p class="mcr-voice">"Hear me, then, for this is the shape of thy prison and mine both. No cradle has ever rocked on this rock, and none ever shall. It is not chance, little ember. It is not misfortune. This place does not permit it. Whatever walks here, walks here childless, however it was made and whomever it lies with. The island sees to that. It suffers no beginning it did not author."</p> <p class="mcr-p">The lava turns, slow and thick, and for a moment the voice is quieter than you have heard it.</p> <p class="mcr-voice">"There is more. There is a why to it, and a hand behind the why, and I know the shape of that hand better than I would wish. But not yet. Thou art not ready to carry it, and I am not ready to say it aloud, even here, even to thee. Go. Rest. Thou hast done what I asked, and more. When next thou climbest to me, we shall speak of who built this cage, and what it is truly for."</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">> <<goto "VolcanoPeak">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaSupplyIntro">> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mv-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mv-wrap { max-width:640px; margin:0 auto; } .mv-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mv-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mv-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mv-wrap"> <p class="mv-p">The lava lifts and folds, and the voice comes up warm and unhurried, the way it does when it has already decided a thing and only waits for you to catch up.</p> <p class="mv-voice">"Thou hast seen the hollow hall, and the island with no children in it. Good. Here is the next thread to pull. Every mouth on this rock is fed, and not one of them asks how. I would have thee ask it."</p> <p class="mv-voice">"Go down to the water, where the great ships come in. Watch what they carry. Find the sheds where it is kept, and get thyself inside if thou canst, by honest work or by stealth or by whatever slippery shape thou wearest. But do it slow. Come and go across some days, and mark whether anything truly changes. I think thou wilt find it does not."</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn mikla-btn-primary'>Set out</div>">> <<if setup.canCombineTap()>> <<if setup.questSystem && !setup.questSystem.isQuestActive("island_supply_lines") && !setup.questSystem.isQuestCompleted("island_supply_lines")>> <<run setup.questSystem.startQuest("island_supply_lines")>> <</if>> <<goto "VolcanoPeak">> <</if>> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DockWarehouse">> <<if !Array.isArray($supplyWarehouseDays)>><<set $supplyWarehouseDays = []>><</if>> <<set _whDays = $supplyWarehouseDays.length>> <style> .dw-scene { background:#0e1216; min-height:100vh; padding:30px 20px; } .dw-wrap { max-width:660px; margin:0 auto; } .dw-p { color:#c3ccd4; font-size:16px; line-height:1.75; } </style> <div class="dw-scene"> <h1 style="color:#8fb3c8; text-align:center;">The Warehouse</h1> <div class="dw-wrap"> <<if _whDays <= 1>> <p class="dw-p">You get yourself inside, and the door swings shut on the noise of the harbour. It is a cathedral of crates. Rows and stacks and towers of them, sailcloth and sacking and banded wood, climbing into the dark near the roof. Everything the island eats and burns and wears must pass through here.</p> <p class="dw-p">You walk the aisles slowly and fix the shape of the place in your mind. A leaning stack by the north door. A gap like a missing tooth in the third row. A crate near the front with a long pale scar down its side. You will know this room again when you come back. For now it is only full, impossibly full, and quiet.</p> <<else>> <p class="dw-p">You come back on another day, and the room has changed, and it has not. The leaning stack by the north door is gone, but there is one exactly like it against the south wall now. The gap in the third row has closed, and a new one has opened two rows over. You find the crate with the long pale scar, and it sits where it never sat before.</p> <p class="dw-p">And that is the thing that stops you cold. It is the same crate. The same scar. You count what you can reach, and nothing is missing, and nothing is new. Not one box has been broken open, not one carried out to feed anybody. It has all simply moved, the way a bored hand shuffles the same deck over and over so the eye believes something happened. Nothing happened. Nothing here ever leaves.</p> <</if>> <p class="dw-p" style="margin-top:14px; color:#8a94a0; font-style:italic;"><<if _whDays <= 1>>You should come back another day and see whether any of it has truly moved.<<else>>She will want to hear of this.<</if>></p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Back to the docks</div>">> <<goto "Docks">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SupplyHarborWatch">> <style> .hw-scene { background:#0b0f16; min-height:100vh; padding:30px 20px; } .hw-wrap { max-width:640px; margin:0 auto; } .hw-p { color:#bcc6d2; font-size:16px; line-height:1.75; } </style> <div class="hw-scene"> <h1 style="color:#6fa8c8; text-align:center;">The Harbour</h1> <div class="hw-wrap"> <<if $supplyShipReturned>> <p class="hw-p">The ship is back. You watch it come in low and heavy, riding the swell the way a full hull rides, and you know it before it is close enough to name. It is the same ship. And stacked on its deck, roped down under the same weathered canvas, is the same cargo you watched it carry out to nothing. Not restocked. Not replaced. The same. It went to the edge of the world and it brought back exactly what it took.</p> <<elseif $supplyShipDepartDay === $dayNumber>> <p class="hw-p">A cargo ship is making ready, and you stay to watch it go. It stands out from the pier, catches the wind, and shrinks toward the flat line where the sky sits on the sea. You wait for it to slip over that line and out of sight the way ships do. It does not. At the horizon it is simply gone, all at once, like a candle pinched out. Not sunk. Not sailed past. Gone.</p> <p class="hw-p" style="margin-top:12px; color:#8a94a0; font-style:italic;">Come back in a day or two and watch for its return.</p> <<else>> <p class="hw-p">The stretch of water where you watched the ship vanish lies empty and calm. Whatever is out there, it has not come back yet. You will have to be patient and look again in a day or two.</p> <</if>> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Back to the docks</div>">> <<goto "Docks">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SupplyVoyage">> <<set _voyages = $supplyVoyageCount>> <style> .sv-scene { background:#071019; min-height:100vh; padding:30px 20px; } .sv-wrap { max-width:640px; margin:0 auto; } .sv-p { color:#bcd0dc; font-size:16px; line-height:1.75; } </style> <div class="sv-scene"> <h1 style="color:#66b0d0; text-align:center;">The Open Water</h1> <div class="sv-wrap"> <<if _voyages <= 1>> <p class="sv-p">You point yourself at the empty horizon and go. The dock falls away behind you, then the harbour, then the whole ragged line of the shore, until you look back and there is nothing there at all, only water meeting sky in a flat grey ring that holds you at its centre. You keep on. You do not turn. You hold your line the way you would swear an oath, hour after hour, into a distance that never once becomes anything.</p> <p class="sv-p">And then there is a shape ahead of you, low on the water, growing. For a moment your heart lifts. Land. Another shore. Somewhere. Then you see the mountain standing on it, and the harbour, and the dock, and you understand. It is the island. Dead ahead of you, precisely where you left it at your back. You did not turn. You never turned. And it is in front of you again, patient, waiting, and there is nothing to do but come in to the same pier you left from.</p> <<else>> <p class="sv-p">You go out again, because a thing this wrong deserves to be made sure of. The same heading. The same held line, hour on hour, the island gone from behind you and no land anywhere ahead. And the same ending: the mountain rising up in front of you where nothing should be, the harbour, the dock. You come in tired and certain this time, the disbelief burned off. There is no out. The line you draw away from this place is a circle, and it always was.</p> <</if>> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Come in to the dock</div>">> <<goto "Docks">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaSupplyMidReport">> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mv-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mv-wrap { max-width:640px; margin:0 auto; } .mv-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mv-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mv-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mv-wrap"> <p class="mv-p">You tell her what the docks are hiding. The warehouse that shuffles the same crates and feeds no one. The ship that sails out full, vanishes at the horizon, and comes back days later carrying the very cargo it left with. She listens, and she is not surprised, not even a little.</p> <p class="mv-voice">"Aye. It goes out full and it comes back full, and the ledger never moves a hair. An island that eats and eats and never empties, and never grows. Thou art seeing the machinery of it now, the turning of the one wheel dressed up as trade."</p> <p class="mv-voice">"But thou hast learned it from the shore, and the shore will tell thee only so much. Here is the next of it, and the hardest. Get thyself a hull, or trust thine own limbs if the sea answers to thy kind, and go out. As far as the water will bear thee. Do not stop at the edge of thy nerve. Go past it. Then come and tell me what the far edge of the world did when thou reached for it."</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">> <<goto "VolcanoPeak">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaSupplyReveal">> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mv-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mv-wrap { max-width:640px; margin:0 auto; } .mv-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mv-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mv-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mv-wrap"> <p class="mv-p">You tell her the last of it. That you rowed and swam and sailed at the edge of the world with everything in you, and the world simply handed you back. That the island stood ahead of you no matter which way you faced. You expected her to be shaken. She is not.</p> <p class="mv-voice">"So. Thou hast reached for the far edge, and the far edge folded thee home. Good. Now hear a thing I never hid from thee, and never once spoke aloud."</p> <p class="mv-voice">"I knew. I have always known. No crate leaves. No keel escapes. No soul walks off this rock, though it march straight at the horizon until its legs give out. I did not send thee down to that water to be taught what I have carried in me longer than thy people have had names."</p> <p class="mv-voice">"I sent thee so thou wouldst stand in it and know it in thy bones. For a thing thou art merely told, thou canst set down and walk away from. A thing thou hast seen with thine own eyes, thou carriest for the rest of thy days. And I have need of one who carries it, little ember. Not one who was told."</p> <p class="mv-voice">"Who built this cage, and what it is truly for, is a heavier telling, and I will not spend it tonight on a body worn out from rowing at the sea. Rest. Thou hast earned the quiet, and thou hast earned my trust, which is the rarer coin. We are not finished, thou and I. But we are further along than we were."</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">> <<goto "VolcanoPeak">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "SupplyCaptainTalk">> <style> .sc-scene { background:#0d1014; min-height:100vh; padding:30px 20px; } .sc-wrap { max-width:640px; margin:0 auto; } .sc-p { color:#c3c9d0; font-size:16px; line-height:1.75; } .sc-said { color:#e2d3b0; } </style> <div class="sc-scene"> <h1 style="color:#9ab0c0; text-align:center;">A Cargo Captain</h1> <div class="sc-wrap"> <p class="sc-p">You find a captain leaning on a bollard with a mug of something hot, watching his crew work. He is weathered and easy and glad enough to talk. You ask him about the far water, the edge of it, what lies past the horizon where his ships go.</p> <p class="sc-p"><span class="sc-said">"Past the horizon? More water, friend. Then a port, then more water, then home. Been sailing this run thirty years. Never once lost my bearings."</span> He says it warm and certain, and he means every word.</p> <p class="sc-p">You press him. Has he never noticed the crossing take too long, or too short? Never watched the island sit exactly where it should not? Never felt the sea quietly hand him back? He laughs, kindly, the way you laugh at a child who has asked whether the sun is afraid of the dark.</p> <p class="sc-p"><span class="sc-said">"You want to lay off the strong stuff before noon, is all. Nothing out there but honest water and an honest day's haul."</span> And that is the whole of it. Whatever is being done to this island, it is not being done to him. He cannot see it. You get the strange, cold sense that he is not able to.</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Back to the docks</div>">> <<goto "Docks">> <</link>> </div> </div> <</nobr>>
<<nobr>> <<set _isNew = setup.questSystem && !setup.questSystem.isQuestActive("island_one_sky") && !setup.questSystem.isQuestCompleted("island_one_sky")>> <<if _isNew>><<run setup.questSystem.startQuest("island_one_sky")>><</if>> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mv-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mv-wrap { max-width:640px; margin:0 auto; } .mv-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mv-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mv-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mv-wrap"> <p class="mv-p">The lava turns, and she comes up in it, and this time there is something almost like humour in the heat of her voice.</p> <p class="mv-voice">"Thou hast walked the roads and the water for me, little ember, and thou hast a doubting eye now. Good. Turn it upward. Look at the sky."</p> <p class="mv-voice">"A true sky is a quarrelsome thing. It rains on one shore and shines on the next. It cannot agree with itself from one hill to the next. Watch thine own, and tell me if it behaves so. Read it from three far corners in a single day. Stand still through the dawn and watch what it does. And go stand in the desert, where the little board on thy hip swears the sun is always out, and see for thyself whether it speaks true. Then come to me."</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">><<goto "VolcanoPeak">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set _region = $skyObserveReturn>> <<set _return = $skyLastRealLocation || "The Nest">> <style> .so-scene { background:#0a1420; min-height:100vh; padding:30px 20px; } .so-wrap { max-width:640px; margin:0 auto; } .so-p { color:#bcd0dc; font-size:16px; line-height:1.75; } .so-note { color:#8aa0b0; font-size:14px; line-height:1.6; font-style:italic; } </style> <div class="so-scene"> <h1 style="color:#66b0d0; text-align:center;">You Read the Sky</h1> <div class="so-wrap"> <p class="so-p">You stop where you are and give the sky your whole attention, the way she asked. <<print setup.getWeatherIcon($currentWeather)>> Whatever it is doing, it is doing it edge to edge, the same grey or the same glare pulled taut over the whole bowl of the island at once, with no seam, no front, no far corner where it softens into something else.</p> <<if $skyLastRealLocation === "Desert" && $currentWeather !== "Clear">> <<set $skyDesertLie = true>> <p class="so-p">Here is the strangest of it. The little readout on your hip insists, as it always does in the desert, that the sky is Clear. You lift your eyes off it and there is no clearness anywhere, only the same weather the rest of the island is wearing today, laid over the dunes like a lie told with a straight face.</p> <<elseif $skyLastRealLocation === "Desert">> <p class="so-note">The desert readout says Clear, and today, by chance, the sky agrees with it. Come back when the sky is doing something and see whether the readout still tells the truth.</p> <</if>> <<if $skyObserveDay !== $dayNumber>><<set $skyObserveDay = $dayNumber>><<set $skyObservedRegions = []>><</if>> <<if _region && $skyObservedRegions.indexOf(_region) === -1>><<run $skyObservedRegions.push(_region)>><</if>> <p class="so-note">Corners read today: <<print ($skyObserveDay === $dayNumber ? $skyObservedRegions.length : 0)>> / 3<<if $skyWatchedFlip>> • the dawn's turn seen<</if>><<if $skyDesertLie>> • the desert's lie seen<</if>></p> <<if !$skyWatchedFlip>> <div style="margin-top:18px;"> <<link "<div class='mikla-btn'>Stay still and watch the sky turn over</div>">> <<set _minsToDawn = (($timeInMinutes < 480) ? (480 - $timeInMinutes) : (1440 - $timeInMinutes + 480)) + 5>> <<run advanceTime(_minsToDawn)>> <<set $skyWatchedFlip = true>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <<goto "SkyFlipWatch">> <</link>> </div> <</if>> </div> <div style="text-align:center; margin-top:22px;"> <<link "<div class='mikla-btn'>Back</div>">><<run setup.questSystem && setup.questSystem.checkProgress()>><<goto _return>><</link>> </div> </div> <</nobr>>
<<nobr>> <style> .so-scene { background:#0a1420; min-height:100vh; padding:30px 20px; } .so-wrap { max-width:640px; margin:0 auto; } .so-p { color:#bcd0dc; font-size:16px; line-height:1.75; } </style> <div class="so-scene"> <h1 style="color:#66b0d0; text-align:center;">The Turn of the Sky</h1> <div class="so-wrap"> <p class="so-p">You hold still and keep your eyes up as the dark thins toward dawn. There is no gathering, no wind that shoulders the clouds along, no slow bruising of the light. There is only a moment, sharp as a thrown switch, where the sky was one thing and then is another. <<print setup.getWeatherIcon($currentWeather)>> The whole island's weather changes in that single blink, everywhere, together, and then it simply holds, as if a hand somewhere had turned a wheel one notch and walked away.</p> </div> <div style="text-align:center; margin-top:22px;"> <<link "<div class='mikla-btn'>Back</div>">><<set _d = $skyLastRealLocation || "The Nest">><<goto _d>><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaSkyReport">> <style> @keyframes miklaVoiceShake { 0%,100%{transform:translate(0,0);} 25%{transform:translate(0.6px,-0.5px);} 50%{transform:translate(-0.5px,0.5px);} 75%{transform:translate(0.4px,0.4px);} } .mv-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .mv-wrap { max-width:640px; margin:0 auto; } .mv-p { color:#c9b79a; font-size:16px; line-height:1.7; } .mv-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); animation:miklaVoiceShake 0.28s ease-in-out infinite; font-size:19px; line-height:1.7; letter-spacing:0.5px; } </style> <div class="mv-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Searing Pool of Lava</h1> <div class="mv-wrap"> <p class="mv-p">You tell her all of it. One sky for the whole island, thrown on like a bedsheet. The dawn that changes nothing gently and everything at once. The desert readout lying with a straight face. She is quiet a moment, and the lava breathes.</p> <p class="mv-voice">"So. Even the sky is one wheel, turned once a day by a hand that does not trouble to hide itself from a doubting eye. Weather that is told, not weathered. Thou hast felt it now, in thy own bones, and that is worth more than a hundred of my sayings."</p> <p class="mv-voice">"Here is thy wage for the seeing. That wheel has a spoke a body can reach, if she comes to the fire with the right things in her hands: a stone the earth kept, and two fish that will rise only under the sky thou meanst to call. Bring them, and I will show thee how to set thine own weather over this rock for a few days together. It will cost thee, and it will not come often. But the sky will be thine to choose, and not merely thine to suffer."</p> <p class="mv-p">She does not tell you who turns the wheel the rest of the time. Not tonight. You get the sense she is saving it, the way one saves the heaviest stone for last.</p> </div> <div style="text-align:center; margin-top:26px;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">><<goto "VolcanoPeak">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RiteOfTheSky">> <style> .rt-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .rt-wrap { max-width:680px; margin:0 auto; } .rt-p { color:#c9b79a; font-size:16px; line-height:1.7; } .rt-card { border:2px solid #b06a2c; border-radius:12px; padding:16px; margin:14px 0; background:linear-gradient(180deg,#1c130b,#0d0906); } .rt-off { color:#f0cf95; font-size:14px; line-height:1.6; } .rt-miss { color:#c76b5a; font-size:13px; line-height:1.5; } </style> <div class="rt-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Rite of the Sky</h1> <div class="rt-wrap"> <p class="rt-p">The fire waits. Lay the offerings at its edge and name the sky you want, and it will hold over the island from tomorrow's dawn for three days together.</p> <<if setup.skyRite.onCooldown()>> <div class="rt-card"><p class="rt-off">The wheel will not be turned again so soon. Come back in <<print setup.skyRite.cooldownDaysLeft()>> days.</p></div> <<else>> <<for _w range ["Clear", "Cloudy", "Rainy", "Stormy"]>> <<capture _w>> <<set _o = setup.skyRite.OFFERINGS[_w]>> <<set _miss = setup.skyRite.missingParts(_w)>> <div class="rt-card"> <p class="rt-off"><<print _o.icon>> <strong><<print _w>></strong>: needs <<print _o.gemLabel>>, <<print _o.mythLabel>>, <<print _o.legLabel>></p> <<if _miss.length === 0>> <<set _lbl = "<div class='mikla-btn'>Call the " + _w + " sky</div>">> <<link _lbl>> <<if setup.canCombineTap()>> <<if setup.skyRite.cast(_w)>><<goto "RiteResult">><<else>><<goto "RiteOfTheSky">><</if>> <</if>> <</link>> <<else>> <p class="rt-miss">You are missing: <<print _miss.join(", ")>></p> <</if>> </div> <</capture>> <</for>> <</if>> <div style="text-align:center; margin-top:22px;"> <<link "<div class='mikla-btn'>Step back from the fire</div>">><<goto "DragonQueenChamber">><</link>> </div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "RiteResult">> <<set _type = $forcedWeather ? $forcedWeather.type : "Clear">> <style> .rt-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .rt-wrap { max-width:640px; margin:0 auto; } .rt-p { color:#c9b79a; font-size:16px; line-height:1.7; } </style> <div class="rt-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Wheel Turns</h1> <div class="rt-wrap"> <p class="rt-p">The stone cracks to powder in the heat and the two fish go to smoke that smells of the sea, and something vast and patient shifts, one notch, under your hand. <<print setup.getWeatherIcon(_type)>> Tomorrow the island will wake to the sky you named, and wear it for three days before the wheel is left to turn on its own again.</p> </div> <div style="text-align:center; margin-top:22px;"> <<link "<div class='mikla-btn'>Let it settle</div>">><<goto "DragonQueenChamber">><</link>> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DragonBindings">> <<set _step = $dragonReleaseStep>> <<set _inForm = setup.dragonRelease.isInForm(_step)>> <style> .db-scene { background:#0a0400; min-height:100vh; padding:30px 20px; } .db-wrap { max-width:640px; margin:0 auto; } .db-p { color:#c9b79a; font-size:16px; line-height:1.7; } .db-seal { border:2px solid #5a3a1a; border-radius:10px; padding:12px 14px; margin:10px 0; background:linear-gradient(180deg,#1c130b,#0d0906); color:#c9a06a; font-size:14px; } .db-seal.done { border-color:#b06a2c; color:#f0cf95; } .db-seal.cur { border-color:#ff8a50; box-shadow:0 0 12px rgba(255,110,30,0.4); } .dragon-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85); font-size:18px; line-height:1.7; } </style> <div class="db-scene"> <h1 style="color:#ff8a50; text-align:center; text-shadow:0 0 16px rgba(255,80,0,0.5);">The Pale Bindings</h1> <div class="db-wrap"> <p class="db-p">Six threads of cold light hold her in the pool, and each answers only to a shape that helped make it. <<print $dragonReleaseStep>> of 6 are undone.</p> <<for _i = 0; _i lt setup.dragonRelease.TOTAL; _i++>> <<capture _i>> <<set _r = setup.dragonRelease.RELEASES[_i]>> <<if _i lt $dragonReleaseStep>> <div class="db-seal done">✓ The <<print _r.forms.join(" / ")>> binding is unmade.</div> <<elseif _i eq $dragonReleaseStep>> <div class="db-seal cur">◆ This binding answers to <strong><<print _r.forms.join(" or ")>></strong> (<<print _r.name>>).</div> <<else>> <div class="db-seal">□ A binding still sealed. Its shape is not yet revealed.</div> <</if>> <</capture>> <</for>> <<if $dragonReleaseStep gte setup.dragonRelease.TOTAL>> <p class="db-p">Every thread is cut. The pool waits.</p> <div style="text-align:center; margin-top:20px;"><<link "<div class='mikla-btn'>Speak the last word</div>">><<goto "DragonFreed">><</link>></div> <<elseif _inForm>> <p class="dragon-voice">"Aye. Thou hast come wearing the right shape at last. Reach in. Do not flinch."</p> <div style="text-align:center; margin-top:16px;"> <<link "<div class='mikla-btn'>Unmake this binding</div>">> <<if setup.canCombineTap()>> <<if setup.dragonRelease.isInForm($dragonReleaseStep)>> <<set $dragonReleaseStep = $dragonReleaseStep + 1>> <<if $dragonReleaseStep gte setup.dragonRelease.TOTAL>> <<goto "DragonFreed">> <<else>> <<goto "DragonBindings">> <</if>> <</if>> <</if>> <</link>> </div> <<else>> <p class="db-p">You are not wearing the shape this binding demands. It wants <strong><<print setup.dragonRelease.formHint($dragonReleaseStep)>></strong>. Return in that form.</p> <</if>> <div style="text-align:center; margin-top:22px;"><<link "<div class='mikla-btn'>Step back</div>">><<goto "DragonQueenChamber">><</link>></div> </div> </div> <</nobr>>
<<nobr>> <<set $lastLocation = "DragonFreed">> <<if !$dragonFreed>> <<set $dragonFreed = true>> /* Release shockwave strips the Automaton form the player wore to unbind the final seal and banks it into trait storage (storeTraitToStorage reverts the full transformation to human as a side effect). */ <<if $physicalTraits.includes("Automaton")>> <<set _autoStored = setup.fishing.storeTraitToStorage("physical", "Automaton")>> <<if !_autoStored && $physicalTraits.includes("Automaton")>> <<run setup.revertFullTransformation("Automaton")>> <<set _autoIdx = $physicalTraits.indexOf("Automaton")>> <<if _autoIdx !== -1>><<run $physicalTraits.splice(_autoIdx, 1)>><</if>> <</if>> <</if>> <<if !$physicalTraits.includes("Dragon")>><<run $physicalTraits.push("Dragon")>><</if>> <<run setup.questSystem && setup.questSystem.checkProgress()>> <</if>> <style> @keyframes dfFade { 0%{opacity:0; transform:translateY(20px);} 100%{opacity:1; transform:translateY(0);} } @keyframes dfBorder { 0%,100%{border-color:rgba(255,90,20,0.4); box-shadow:0 0 15px rgba(255,90,20,0.2);} 50%{border-color:rgba(255,140,60,0.65); box-shadow:0 0 25px rgba(255,90,20,0.45), 0 0 40px rgba(255,140,60,0.15);} } @keyframes dfEmberRise { 0%{transform:translateY(0); opacity:0;} 15%{opacity:0.85;} 100%{transform:translateY(-220px); opacity:0;} } .df-scene { background:linear-gradient(135deg,#150200 0%,#3a0d00 50%,#150200 100%); min-height:100vh; padding:30px 20px; position:relative; overflow:hidden; } .df-scene::before { content:''; position:absolute; top:0; left:0; right:0; bottom:0; background-image: radial-gradient(2px 2px at 30px 260px, rgba(255,150,60,0.7), transparent), radial-gradient(2px 2px at 130px 300px, rgba(255,90,20,0.6), transparent), radial-gradient(1px 1px at 210px 240px, rgba(255,190,100,0.6), transparent), radial-gradient(2px 2px at 90px 330px, rgba(255,110,30,0.5), transparent), radial-gradient(1px 1px at 270px 290px, rgba(255,150,60,0.6), transparent); background-repeat:repeat; background-size:300px 340px; animation:dfEmberRise 6s linear infinite; pointer-events:none; } .df-sec { background:rgba(20,4,0,0.85); border:2px solid rgba(255,90,20,0.4); border-radius:15px; padding:25px; margin:20px auto; max-width:720px; opacity:0; animation:dfFade 1s ease-out forwards, dfBorder 4s ease-in-out infinite; animation-delay:0s, 0s; position:relative; } .df-p { color:#f0d8c8; font-size:16px; line-height:1.8; margin:0 0 14px 0; } .df-p:last-child { margin-bottom:0; } .dragon-voice { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.85), 0 0 18px rgba(255,60,0,0.45); font-size:19px; line-height:1.7; letter-spacing:0.5px; margin:0 0 14px 0; } .df-divider { height:2px; background:linear-gradient(90deg,transparent,#c0392b,#ff8a50,#c0392b,transparent); margin:25px auto; max-width:720px; opacity:0.6; } .df-img { text-align:center; margin:18px 0; } .df-img img { max-width:360px; width:100%; border-radius:12px; border:3px solid #ff6b3a; box-shadow:0 0 30px rgba(255,90,20,0.5); } .mikla-name { font-family:'Cinzel',serif; color:#fff2d0; font-size:26px; text-align:center; text-shadow:0 0 12px rgba(255,140,40,0.9), 0 0 28px rgba(255,70,0,0.5); letter-spacing:1px; margin:6px 0 14px 0; } </style> <div class="df-scene"> <div class="df-sec"> <p class="df-p">The last cold thread parts under your hand, and the pale fire that held her for longer than your people have had names simply goes out. The pool drains of its wrong light. Then the freed heat comes off it all at once, a soundless wave that rolls through you and keeps going.</p> <p class="df-p">It takes the shape you wore to reach this place with it. The automaton shell you built yourself into to touch the binding shears loose, plating and porcelain sloughing away like frost off a kettle, and the cold clockwork heart of it is pulled out of you clean. You stand in your own skin again, human and ringing, the taste of hot metal on your tongue. What you were is not lost. You can feel it folded away small and patient, yours to put back on another day.</p> </div> <<timed 5s>> <div class="df-divider"></div> <div class="df-sec"> <p class="df-p">The lava heaves. Something vast comes up out of it and does not stop coming: white scales sheeting the light, wings of red fire and beaten gold snapping wide until they scrape both walls, a crown of horns, a long tail that ends in a living flame. She does not fold herself small this time. She lets you see the whole of what you have loosed, and the chamber is far too little to hold it.</p> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <div class="df-img"><img src="Images/NPCs/StaticNPCs/Mikla_Dragon.webp"></div> <</if>> </div> <</timed>> <<timed 11s>> <div class="df-divider"></div> <div class="df-sec"> <p class="dragon-voice">"Look, then, and remember it. In the tongue I was named in, before thy kind had letters to spell fire, I am"</p> <p class="mikla-name">þann mikla rauða</p> <p class="df-p">The word lands in your chest more than your ears, all iron and burning, and you know your mouth was never made to hold it.</p> <p class="dragon-voice">"It sits ill on a mortal jaw. Call me Mikla Roytha. It is close enough, and kinder to thy teeth."</p> </div> <</timed>> <<timed 17s>> <div class="df-divider"></div> <div class="df-sec"> <p class="df-p">She lowers her great head until one banked coal of an eye fills your whole sky, and sets something into you rather than into your palm: a seed of her own fire, old and patient. It is not yet a shape you can wear. It is the promise of one.</p> <p class="dragon-voice">"That is the Dragon in thee now, raw and unshaped. Take it to the green ruin where thou minglest thy natures. Fold it together with thine own bright, brash self and a soul to anchor it, and thou shalt wear a piece of what I am. This debt is paid."</p> <p class="df-p" style="color:#9a8a70; font-style:italic;">You have gained the Dragon trait. Combine Dragon + Gyaru + Soul at the Overgrown Lab to become a Half-Dragon.</p> </div> <</timed>> <<timed 24s>> <div class="df-divider"></div> <div class="df-sec"> <p class="df-p">Then she draws the fire back into herself. The wings fold, and the vast body folds after them, all that molten majesty pouring down and inward like a candle burning in reverse, until what stands on the cooling stone is near your own height. A woman, near enough: her horns still curling back off pale hair that falls to the floor, her eyes two red coals gone gentle, wrapped in white and gold. She looks you over with open, unhurried interest.</p> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <div class="df-img"><img src="Images/NPCs/StaticNPCs/Mikla_Humanoid.webp"></div> <</if>> <p class="dragon-voice">"There. Better, for talk. A shape need not fill a mountain to make its point." She almost smiles, and it is almost warm. "We are not finished, thou and I. But go and be a dragon a while first. Thou hast earned the wearing of it."</p> </div> <</timed>> <<timed 30s>> <div class="df-sec" style="text-align:center; border:none; background:none; box-shadow:none; animation:dfFade 1s ease-out forwards;"> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">><<goto "VolcanoPeak">><</link>> </div> <</timed>> </div> <</nobr>>
<<nobr>> <<set $dgReturn = ($lastLocation && $lastLocation !== "DragonGyaruTransformation") ? $lastLocation : "The Nest">> <<set $lastLocation = "DragonGyaruTransformation">> <<if $possessionActive>> <div style="max-width:640px; margin:30px auto; padding:22px; background:#1a0a0a; border:2px solid #ff6b3a; border-radius:12px; text-align:center;"> <p style="color:#ffb090; font-size:16px; line-height:1.6;">The dragon fire will not take root in a body that is not your own. Return to your own skin first.</p> <<link "<div style='background:#c0392b; color:white; padding:10px 24px; border-radius:6px; font-weight:bold; display:inline-block; cursor:pointer;'>Step back</div>">><<goto $dgReturn>><</link>> </div> <<else>> <<set _wasMale = ($gender === "male")>> <<set _chestOrder = ["flat masculine", "flat", "small", "medium", "large", "huge", "giant", "gigantic"]>> <<set _preChest = ($bodyParts && $bodyParts.chest) ? $bodyParts.chest : "medium">> <<set _willGrowChest = (_chestOrder.indexOf(_preChest) lt _chestOrder.indexOf("huge"))>> <<set _hdgApplied = setup.applyFullTransformation("Half-Dragon Gyaru")>> <<if _hdgApplied && !$physicalTraits.includes("Half-Dragon Gyaru")>><<run $physicalTraits.push("Half-Dragon Gyaru")>><</if>> <style> @keyframes dgFade { 0%{opacity:0; transform:translateY(20px);} 100%{opacity:1; transform:translateY(0);} } @keyframes dgBorder { 0%,100%{border-color:rgba(255,90,20,0.4); box-shadow:0 0 15px rgba(255,90,20,0.2);} 50%{border-color:rgba(255,140,60,0.65); box-shadow:0 0 25px rgba(255,90,20,0.45), 0 0 40px rgba(255,140,60,0.15);} } @keyframes dgEmberRise { 0%{transform:translateY(0); opacity:0;} 15%{opacity:0.85;} 100%{transform:translateY(-220px); opacity:0;} } .dg-container { background:linear-gradient(135deg,#150200 0%,#3a0d00 50%,#150200 100%); min-height:100vh; padding:30px 20px; position:relative; overflow:hidden; } .dg-container::before { content:''; position:absolute; top:0; left:0; right:0; bottom:0; background-image: radial-gradient(2px 2px at 30px 260px, rgba(255,150,60,0.7), transparent), radial-gradient(2px 2px at 130px 300px, rgba(255,90,20,0.6), transparent), radial-gradient(1px 1px at 210px 240px, rgba(255,190,100,0.6), transparent), radial-gradient(2px 2px at 90px 330px, rgba(255,110,30,0.5), transparent), radial-gradient(1px 1px at 270px 290px, rgba(255,150,60,0.6), transparent); background-repeat:repeat; background-size:300px 340px; animation:dgEmberRise 6s linear infinite; pointer-events:none; } .dg-title { color:#ff8a50; font-size:32px; text-align:center; text-shadow:0 0 20px #ff6b3a, 0 0 40px #c0392b; margin-bottom:30px; letter-spacing:3px; position:relative; } .dg-section { background:rgba(20,4,0,0.85); border:2px solid rgba(255,90,20,0.4); border-radius:15px; padding:25px; margin:20px auto; max-width:800px; opacity:0; animation:dgFade 1s ease-out forwards, dgBorder 4s ease-in-out infinite; animation-delay:var(--delay,0s), var(--delay,0s); position:relative; } .dg-section p { color:#f0d8c8; font-size:16px; line-height:1.8; margin:0; } .dg-section-title { color:#ff8a50; font-size:20px; font-weight:bold; margin:0 0 15px 0; text-shadow:0 0 10px rgba(255,140,60,0.5); } .dg-divider { height:2px; background:linear-gradient(90deg,transparent,#c0392b,#ff8a50,#c0392b,transparent); margin:25px auto; max-width:800px; opacity:0.6; } .dg-section-image { text-align:center; margin:18px 0 0 0; } .dg-section-image img { max-width:340px; width:100%; border-radius:12px; border:3px solid #ff6b3a; box-shadow:0 0 30px rgba(255,90,20,0.5); } </style> <div class="dg-container"> <div class="dg-section" style="--delay:0s;"> <p>It starts as heat, deep in your belly, like you swallowed a coal and it liked it there. It spreads. Your blood goes thick and hot and loud in your ears, and something old and enormous turns over inside you and decides it is awake now.</p> </div> <<timed 5s>> <div class="dg-divider"></div> <div class="dg-section" style="--delay:0s;"> <p>Your scalp splits with a bright ache and you feel them come, two horns curling back off your skull, heavy and hot and yours. Your hair drinks the fire and goes bone white, a bleached platinum falling messy over one eye.</p> </div> <div class="dg-section" style="--delay:0.8s;"> <p>You blink and the world sharpens, too sharp, and you know without a mirror that your pupils have narrowed to hard yellow slits. Your grin pulls wide. The teeth behind it are fangs now, and you like how they feel against your tongue.</p> </div> <</timed>> <<timed 11s>> <div class="dg-divider"></div> <div class="dg-section" style="--delay:0s;"> <p>Red scales chase up your forearms and bloom across your thighs, warm as sunbaked stone. Your spine arches on its own, a groan tearing out of you, and your back splits open in two long lines of pressure that resolve into wings, huge and ragged and red, snapping wide to a span that fills the room.</p> </div> <div class="dg-section" style="--delay:0.8s;"> <p>A tail follows, thick and heavy and scaled, uncoiling from the base of your spine to lash the floor. Your feet crack and lengthen into clawed dragon feet that dig into the ground like they own it.</p> </div> <</timed>> <<timed 17s>> <div class="dg-divider"></div> <div class="dg-section" style="--delay:0s;"> <<if _wasMale>> <p>The heat pours down between your legs and takes what was there with it, your cock softening and drawing up and folding away into you. What blooms in its place is slick and swollen and desperately, gorgeously sensitive, and the first throb of it buckles your knees. You brace on your own thick thigh and pant.</p> <<else>> <p>The heat pools low and deep, and your sex throbs with it, swelling slick and greedy and achingly sensitive as the fire rewrites every nerve down there.</p> <</if>> </div> <div class="dg-section" style="--delay:0.8s;"> <p>Muscle piles onto you in slabs, shoulders and back and a stomach that ridges into hard cut abs under your hands. Your thighs thicken until they could crack stone.<<if _willGrowChest>> Your chest swells at the same time, breasts growing full and heavy and then heavier, spilling forward, nipples hard and aching as the weight settles.<</if>> You are enormous now, all power and curve, and every inch of it is throbbing.</p> </div> <</timed>> <<timed 24s>> <div class="dg-divider"></div> <div class="dg-section" style="--delay:0s;"> <p>The heat has nowhere left to go but up, and it crests. You drop into a crouch, wings mantling, thighs spread wide because your body demands the room, and your clawed hand drags down your ridged stomach and lower. You are so wet you are dripping. The first touch is lightning. You throw your head back and rut against your own fingers, tail thrashing, a low growl building in your chest that is not remotely human, and you chase it hard and greedy and shameless until it breaks over you in a long roaring wave of heat that leaves you shuddering and grinning and drunk on how good it is to be this.</p> </div> <</timed>> <<timed 31s>> <div class="dg-divider"></div> <div class="dg-section" style="--delay:0s;"> <p>When it fades you are still smiling, fangs and all. You flex, and the whole magnificent stacked shape of you moves like it was always meant to. Let them stare.</p> </div> <div class="dg-section" style="--delay:0.8s;"> <p style="color:#ff8a50; font-size:20px; font-weight:bold; text-align:center;">You are a Half-Dragon Gyaru.</p> <<if $imageSettings && $imageSettings.imagesEnabled>> <div class="dg-section-image"><img src="Images/Transformation/Dragon_Gyaru.webp"></div> <</if>> </div> <</timed>> <<timed 37s>> <div class="dg-section" style="--delay:0s; text-align:center;"> <<link "<div style='background:#c0392b; color:white; padding:12px 30px; border-radius:8px; font-weight:bold; display:inline-block; cursor:pointer;'>Take it all in</div>">><<goto $dgReturn>><</link>> </div> <</timed>> </div> <</if>> <</nobr>>
<<nobr>> <<set $lastLocation = "MiklaLair">> <<set _tf = $activeTransformation || "none">> <<set _pool = (setup.miklaLines && setup.miklaLines[_tf]) ? setup.miklaLines[_tf] : (setup.miklaLines ? setup.miklaLines["none"] : ["The great dragon regards you in warm and easy silence."])>> <<set _miklaLine = _pool[random(0, _pool.length - 1)]>> <style> @keyframes mlFade { 0%{opacity:0; transform:translateY(14px);} 100%{opacity:1; transform:translateY(0);} } .ml-scene { background:linear-gradient(160deg,#180400 0%,#2e0a02 55%,#180400 100%); min-height:100vh; padding:34px 20px; } .ml-wrap { max-width:680px; margin:0 auto; animation:mlFade 0.9s ease-out forwards; } .ml-img { text-align:center; margin:0 0 22px 0; } .ml-img img { max-width:300px; width:100%; border-radius:14px; border:3px solid #ff9d4a; box-shadow:0 0 34px rgba(255,120,30,0.45); } .ml-frame { color:#e8cdb4; font-size:16px; line-height:1.7; text-align:center; margin-bottom:18px; } .ml-line { font-family:'Cinzel',serif; color:#ffd27a; text-shadow:0 0 8px rgba(255,120,20,0.8), 0 0 18px rgba(255,60,0,0.4); font-size:20px; line-height:1.7; text-align:center; padding:0 6px; } </style> <div class="ml-scene"> <div class="ml-wrap"> <<if $imageSettings && $imageSettings.imagesEnabled && $imageSettings.npcImagesEnabled>> <div class="ml-img"><img src="Images/NPCs/StaticNPCs/Mikla_Humanoid.webp"></div> <</if>> <p class="ml-frame">Mikla Roytha reclines in the cooled heart of the mountain, wings folded, gold catching the low red light. She lifts her gaze to you as you enter, and something in it warms.</p> <p class="ml-line"><<print _miklaLine>></p> <div style="text-align:center; margin-top:28px;"> <<link "<div class='mikla-btn'>Speak with her again</div>">><<goto "MiklaLair">><</link>> <div style="height:12px;"></div> <<link "<div class='mikla-btn'>Climb back to the Peak</div>">><<goto "VolcanoPeak">><</link>> </div> </div> </div> <</nobr>>