Browser lacks capabilities required to play.

Upgrade or switch to another browser.

Loading…
<<nobr>> <<set $maxTraits = 1>> /* Initialize default name values if not already set */ <<if $firstName === undefined or $firstName === "">> <<set $firstName = "Water">> <</if>> <<if $lastName === undefined or $lastName === "">> <<set $lastName = "Bottle">> <</if>> /* Initialize appearance object if it doesn't exist */ <<if !$appearance>> <<set $appearance = { skinTone: "pale", hairColor: "Black", hairStyle: "messy", physique: "average", age: "Adult" }>> <</if>> /* Initialize bodyParts if not set */ <<if !$bodyParts>> <<set $bodyParts = { gender: "male", chest: "flat masculine", butt: "flat masculine" }>> <</if>> /* Initialize playerPronouns if not set */ <<if !$playerPronouns>> <<set $playerPronouns = "he/him">> <</if>> /* Clear the returning flag after loading */ <<if $returningFromSummary>> <<set $returningFromSummary = false>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">🎨 Character Creation</h1> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> Create your character for Sunfish City. Customize your appearance and select starting traits. </p> </div> <!-- Basic Information --> <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: 0 0 20px 0; font-size: 24px; border-bottom: 3px solid #667eea; padding-bottom: 10px;">👤 Basic Information</h2> <div style="margin-bottom: 20px;"> <label style="color: #aaa; font-size: 16px; display: block; margin-bottom: 8px; font-weight: bold;">First Name:</label> <<textbox "$firstName" $firstName autofocus>> </div> <div style="margin-bottom: 0;"> <label style="color: #aaa; font-size: 16px; display: block; margin-bottom: 8px; font-weight: bold;">Last Name:</label> <<textbox "$lastName" $lastName>> </div> </div> <!-- Pronouns --> <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 20px 0; font-size: 24px; border-bottom: 3px solid #9b59b6; padding-bottom: 10px;">💬 Pronouns</h2> <div style="display: flex; gap: 20px; align-items: center; flex-wrap: wrap;"> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $playerPronouns === "he/him">> <<radiobutton "$playerPronouns" "he/him" checked>> <<else>> <<radiobutton "$playerPronouns" "he/him">> <</if>> He/Him </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $playerPronouns === "she/her">> <<radiobutton "$playerPronouns" "she/her" checked>> <<else>> <<radiobutton "$playerPronouns" "she/her">> <</if>> She/Her </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $playerPronouns === "they/them">> <<radiobutton "$playerPronouns" "they/them" checked>> <<else>> <<radiobutton "$playerPronouns" "they/them">> <</if>> They/Them </label> <<link "<span style='color: #9b59b6; font-weight: bold; font-size: 16px;'>Customize</span>">> <<pronouns>> <</link>> </div> </div> <!-- Gender --> <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 20px 0; font-size: 24px; border-bottom: 3px solid #ff6b6b; padding-bottom: 10px;">⚧ Gender</h2> <div style="display: flex; gap: 20px; flex-wrap: wrap;"> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $bodyParts.gender === "male">> <<radiobutton "$bodyParts.gender" "male" checked>> <<else>> <<radiobutton "$bodyParts.gender" "male">> <</if>> Male </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $bodyParts.gender === "female">> <<radiobutton "$bodyParts.gender" "female" checked>> <<else>> <<radiobutton "$bodyParts.gender" "female">> <</if>> Female </label> </div> </div> <!-- Appearance --> <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 20px 0; font-size: 24px; border-bottom: 3px solid #17a2b8; padding-bottom: 10px;">✨ Appearance</h2> <div style="margin-bottom: 20px;"> <h3 style="color: #aaa; margin: 0 0 10px 0; font-size: 18px;">Skin Tone:</h3> <div style="display: flex; gap: 20px; flex-wrap: wrap;"> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.skinTone === "pale">> <<radiobutton "$appearance.skinTone" "pale" checked>> <<else>> <<radiobutton "$appearance.skinTone" "pale">> <</if>> Pale </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.skinTone === "tan">> <<radiobutton "$appearance.skinTone" "tan" checked>> <<else>> <<radiobutton "$appearance.skinTone" "tan">> <</if>> Tan </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.skinTone === "dark">> <<radiobutton "$appearance.skinTone" "dark" checked>> <<else>> <<radiobutton "$appearance.skinTone" "dark">> <</if>> Dark </label> </div> </div> <div style="margin-bottom: 20px;"> <h3 style="color: #aaa; margin: 0 0 10px 0; font-size: 18px;">Hair Color:</h3> <div style="display: flex; gap: 20px; flex-wrap: wrap;"> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.hairColor === "Black" || !$appearance.hairColor>> <<radiobutton "$appearance.hairColor" "Black" checked>> <<else>> <<radiobutton "$appearance.hairColor" "Black">> <</if>> Black </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.hairColor === "Brown">> <<radiobutton "$appearance.hairColor" "Brown" checked>> <<else>> <<radiobutton "$appearance.hairColor" "Brown">> <</if>> Brown </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.hairColor === "Blonde">> <<radiobutton "$appearance.hairColor" "Blonde" checked>> <<else>> <<radiobutton "$appearance.hairColor" "Blonde">> <</if>> Blonde </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.hairColor === "Red">> <<radiobutton "$appearance.hairColor" "Red" checked>> <<else>> <<radiobutton "$appearance.hairColor" "Red">> <</if>> Red </label> </div> </div> <div style="margin-bottom: 0;"> <h3 style="color: #aaa; margin: 0 0 10px 0; font-size: 18px;">Age:</h3> <div style="display: flex; gap: 20px; flex-wrap: wrap;"> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.age === "Adult">> <<radiobutton "$appearance.age" "Adult" checked>> <<else>> <<radiobutton "$appearance.age" "Adult">> <</if>> Adult </label> <label style="color: #ccc; font-size: 16px; cursor: pointer;"> <<if $appearance.age === "Mature Adult">> <<radiobutton "$appearance.age" "Mature Adult" checked>> <<else>> <<radiobutton "$appearance.age" "Mature Adult">> <</if>> Mature Adult </label> </div> </div> </div> <!-- Trait Selection --> <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 20px 0; font-size: 24px; border-bottom: 3px solid #51cf66; padding-bottom: 10px;">🎯 Starting Traits</h2> <p style="color: #aaa; font-size: 16px; margin: 0 0 15px 0;"> <strong>Optional:</strong> You may select 1 trait (or none). </p> <span id="trait-counter"> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #51cf66;"> <p style="color: #51cf66; margin: 0; font-size: 16px; font-weight: bold;"> You have currently chosen <span style="color: #ffc107;"><<print $selectedTraits.length>></span> out of 1 trait. </p> </div> </span> <span id="trait-list"> <<include "TraitListDisplay">> </span> </div> <!-- Continue Button --> <div style="text-align: center; margin-top: 30px;"> <<link "<div style='display: inline-block; background: #51cf66; color: white; padding: 18px 50px; border-radius: 12px; font-weight: bold; font-size: 20px; box-shadow: 0 4px 8px rgba(0,0,0,0.4);'>Continue to Summary →</div>">> /* Auto-set chest and butt based on gender */ <<if $bodyParts.gender === "male">> <<set $bodyParts.chest = "flat masculine">> <<set $bodyParts.butt = "flat masculine">> <<else>> <<set $bodyParts.chest = "flat">> <<set $bodyParts.butt = "flat">> <</if>> /* Ensure hair style is set to messy */ <<set $appearance.hairStyle = "messy">> /* Initialize hair length as short by default and add to physical traits */ <<set $appearance.hairLength = "short">> <<if !$physicalTraits.includes("Short Hair")>> <<run $physicalTraits.push("Short Hair")>> <</if>> /* Set all stats to 5 */ <<set $stats = { charisma: 5, dexterity: 5, strength: 5, intelligence: 5 }>> /* Set max stat caps to 100 */ <<set $statMaxCaps = { charisma: 999, dexterity: 999, strength: 999, intelligence: 999 }>> /* Set pronouns based on selection */ <<if $playerPronouns === "she/her">> <<run setup.gender.setPronouns("female")>> <<elseif $playerPronouns === "he/him">> <<run setup.gender.setPronouns("male")>> <<elseif $playerPronouns === "they/them">> <<run setup.gender.setPronouns("they")>> <</if>> /* Store character creation trait separately (bonuses applied dynamically via setup.getTotalStat) */ <<if $selectedTraits.length > 0>> <<set $characterCreationTrait = $selectedTraits[0]>> <<else>> <<set $characterCreationTrait = null>> <</if>> <<set $maxTraits = 100>> <<goto "Summary">> <</link>> </div> </div> <</nobr>><<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>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">📋 Character Summary</h1> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; margin-bottom: 25px; border: 2px solid #667eea; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: white; font-size: 18px; margin: 0; text-align: center;"> Are you ready to begin your journey? </p> </div> <!-- Name --> <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: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #667eea; padding-bottom: 10px;">👤 Name</h2> <p style="color: #ccc; font-size: 20px; margin: 0; font-weight: bold;">$firstName $lastName</p> </div> <!-- Appearance --> <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;">✨ Appearance</h2> <ul style="list-style-type: none; padding-left: 0; margin: 0;"> <li style="color: #ccc; font-size: 16px; margin-bottom: 10px;"> <strong style="color: #17a2b8;">Hair:</strong> <<set _summaryHairStyle = $appearance.hairStyle === "messy" ? "Messy " : "">> <<set _summaryHairLength = $appearance.hairLength ? $appearance.hairLength.toUpperFirst() : "Short">> <<print _summaryHairStyle + _summaryHairLength>> $appearance.hairColor </li> <li style="color: #ccc; font-size: 16px; margin-bottom: 10px;"> <strong style="color: #17a2b8;">Skin Tone:</strong> <<print $appearance.skinTone.toUpperFirst()>> </li> <li style="color: #ccc; font-size: 16px; margin-bottom: 10px;"> <strong style="color: #17a2b8;">Age:</strong> $appearance.age </li> <li style="color: #ccc; font-size: 16px; margin: 0;"> <strong style="color: #17a2b8;">Gender:</strong> <<print $bodyParts.gender.toUpperFirst()>> </li> </ul> </div> <!-- Body Parts --> <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> <ul style="list-style-type: none; padding-left: 0; margin: 0;"> <li style="color: #ccc; font-size: 16px; margin-bottom: 10px;"> <strong style="color: #ff6b6b;">Chest:</strong> <<print $bodyParts.chest.toUpperFirst()>> </li> <li style="color: #ccc; font-size: 16px; margin: 0;"> <strong style="color: #ff6b6b;">Butt:</strong> <<print $bodyParts.butt.toUpperFirst()>> </li> </ul> </div> <!-- Physical Traits --> <<if $physicalTraits.length > 0>> <<set _displaySummaryPhysicalTraits = $physicalTraits.filter(function(trait) { return trait !== "Short Hair" && trait !== "Long Hair"; })>> <<if _displaySummaryPhysicalTraits.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> <ul style="list-style-type: none; padding-left: 0; margin: 0;"> <<for _i to 0; _i < _displaySummaryPhysicalTraits.length; _i++>> <li style="color: #ccc; font-size: 16px; margin-bottom: 8px;">• <<print _displaySummaryPhysicalTraits[_i]>></li> <</for>> </ul> </div> <</if>> <</if>> <!-- Mental Traits --> <<if $mentalTraits.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> <ul style="list-style-type: none; padding-left: 0; margin: 0;"> <<for _i to 0; _i < $mentalTraits.length; _i++>> <li style="color: #ccc; font-size: 16px; margin-bottom: 8px;">• <<print $mentalTraits[_i]>></li> <</for>> </ul> </div> <</if>> <!-- Skills --> <<if $skills.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> <ul style="list-style-type: none; padding-left: 0; margin: 0;"> <<for _i to 0; _i < $skills.length; _i++>> <li style="color: #ccc; font-size: 16px; margin-bottom: 8px;">• <<print $skills[_i]>></li> <</for>> </ul> </div> <</if>> <!-- Character Creation Traits --> <<if $selectedTraits.length > 0>> <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);"> <h2 style="color: #e91e63; margin: 0 0 15px 0; font-size: 24px; border-bottom: 3px solid #e91e63; padding-bottom: 10px;">⭐ Character Creation Traits</h2> <ul style="list-style-type: none; padding-left: 0; margin: 0;"> <<for _i to 0; _i < $selectedTraits.length; _i++>> <li style="color: #ccc; font-size: 16px; margin-bottom: 8px;">• <<print $selectedTraits[_i]>></li> <</for>> </ul> </div> <</if>> <!-- Action Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 30px;"> <<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 4px 8px rgba(0,0,0,0.4);'>✅ Begin Game</div>">> <<set $skipTimeAdvancement = true>> <<goto "Alleyway">> <</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 4px 8px rgba(0,0,0,0.4);'>← Back to Character Creation</div>">> <<set $returningFromSummary = true>> <<goto "CharacterCreation">> <</link>> </div> </div> <</nobr>><<nobr>> <!-- Time and Date Display --> <<set _currentTime = getTimeOfDay()>> <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> </div> <!-- Player Name --> <div style="text-align: center; margin-bottom: 10px;"> <<if $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> <!-- 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>> <<set $lastLocation = "Alleyway">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #666; text-align: center;">🌆 Dark Alleyway</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 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> </div> <!-- Unemployed NPCs Section --> <<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>> <<run _unemployedNPCs.push(_npc)>> <</if>> <</for>> <<if _unemployedNPCs.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 #666; 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;"> Some people who have fallen on hard times have gathered in the alley... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _unemployedNPCs>> <<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 5px 0;"> <em>Unemployed</em> </p> <p style="font-size: 13px; color: #aaa; font-style: italic; margin: 0 0 10px 0;"> Lost their job and ended up here in the alley. </p> <<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> <</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>> <<run advanceTime(_sleepHours * 60)>> <<run Dialog.close()>> <<if _wasRobbed>> <<goto "AlleySleepRobbed">> <<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 $hasApartment>>#51cf66<<else>>#ff6b6b<</if>>;"> <<if $hasApartment>>Housed<<else>>Homeless<</if>> </span> </div> <div> <strong style="color: #aaa;">Age:</strong> <span style="color: #ccc;">$appearance.age</span> </div> </div> </div> <!-- PRONOUNS SECTION --> <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 20px 0; font-size: 24px; border-bottom: 3px solid #9b59b6; padding-bottom: 10px;">💬 Pronouns</h2> <div style="margin-bottom: 15px;"> <strong style="color: #aaa;">Current Pronouns:</strong> <span style="color: #9b59b6; font-size: 18px; font-weight: bold;"> <<if $playerPronouns === "he/him">>He/Him <<elseif $playerPronouns === "she/her">>She/Her <<elseif $playerPronouns === "they/them">>They/Them <<else>>Custom <</if>> </span> </div> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 15px;"> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; color: #ccc; padding: 12px; border-radius: 8px; cursor: pointer; font-weight: bold; text-align: center; transition: all 0.3s;'>He/Him</div>">> <<set $playerPronouns = "he/him">> <<run setup.gender.setPronouns("male")>> <<goto "Body">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; color: #ccc; padding: 12px; border-radius: 8px; cursor: pointer; font-weight: bold; text-align: center; transition: all 0.3s;'>She/Her</div>">> <<set $playerPronouns = "she/her">> <<run setup.gender.setPronouns("female")>> <<goto "Body">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; color: #ccc; padding: 12px; border-radius: 8px; cursor: pointer; font-weight: bold; text-align: center; transition: all 0.3s;'>They/Them</div>">> <<set $playerPronouns = "they/them">> <<run setup.gender.setPronouns("they")>> <<goto "Body">> <</link>> <<link "<div style='background: #1a1a1a; border: 2px solid #9b59b6; color: #ccc; padding: 12px; border-radius: 8px; cursor: pointer; font-weight: bold; text-align: center; transition: all 0.3s;'>Customize</div>">> <<pronouns>> <</link>> </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;">Physique:</strong> <span style="color: #ccc;"><<print $appearance.physique.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> </div> </div> <!-- 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 style="color: #51cf66; margin-top: 0;">💪 Physical Traits</h2> <<if $physicalTraits && $physicalTraits.length > 0>> <<set _displayPhysicalTraits = $physicalTraits.filter(function(trait) { return trait !== "Short Hair" && trait !== "Long Hair"; })>> <<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">> <<set _bgColor = "#1a1a1a">> <div style="background: _bgColor; 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> </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> <!-- 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 style="color: #9b59b6; margin-top: 0;">🧠 Mental Traits</h2> <<if $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 _bgColor = "#1a1a1a">> <div style="background: _bgColor; 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> </div> <</for>> </div> <<else>> <p style="color: #666; font-style: italic; margin: 0;">No mental traits acquired yet.</p> <</if>> </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 style="color: #ffc107; margin-top: 0;">🎯 Skills</h2> <<if $skills && $skills.length > 0>> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _skill range $skills>> <<set _skillValue = setup.getTraitValue("skill", _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> </div> <</for>> </div> <<else>> <p style="color: #666; font-style: italic; margin: 0;">No skills acquired yet.</p> <</if>> </div> <!-- CHARACTER CREATION TRAITS --> <<if $selectedTraits && $selectedTraits.length > 0>> <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 style="color: #e91e63; margin-top: 0;">⭐ Character Creation Traits</h2> <div style="display: flex; flex-wrap: wrap; gap: 10px;"> <<for _trait range $selectedTraits>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <div style="background: #1a1a1a; border: 2px solid #e91e63; border-radius: 8px; padding: 10px 15px;"> <strong style="color: #ccc;">_trait</strong> <span style="color: #e91e63; font-size: 13px; margin-left: 5px;"> (+_traitValue) </span> </div> <</for>> </div> </div> <</if>> <!-- CURRENT JOBS --> <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;">💼 Current Employment</h2> <<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> <!-- 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">> <<goto $lastLocation>> <<elseif _prev !== "Body" && _prev !== "Debug">> <<goto _prev>> <<else>> <<goto "Summary">> <</if>> <</link>> </div> </div> <</nobr>>:: StoryMenu <<nobr>> [[Body]] [[Relationships]] [[Cheat Menu|Debug]] [[Image Settings|ImageSettings]] [[Patreon|https://www.patreon.com/Grankor]] [[Discord|https://discord.gg/z9eDdQC6zA]] <</nobr>><<nobr>> <<set $lastLocation = "Downtown">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #667eea; text-align: center;">🏙️ Downtown</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;"> 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;">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;"> <h3 style="color: #ffc107; margin-top: 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; 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> <!-- 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;">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;"> <h3 style="color: #ff1493; margin-top: 0;">🔴 Red Light District</h3> <p style="font-size: 14px; color: #aaa; 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 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-top: 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; 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;'>Travel to Alleyway</div>">> <<goto "Alleyway">> <</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-top: 0;">🏢 Sunfish Apartments</h3> <p style="font-size: 14px; color: #aaa; 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-top: 0;">🏛️ Town Hall</h3> <p style="font-size: 14px; color: #aaa; 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-top: 0;">🐠 Sunfish City Aquarium</h3> <p style="font-size: 14px; color: #aaa; 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> </div> <</nobr>><<nobr>> <<set $lastLocation = "BusinessDistrict">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #17a2b8; text-align: center;">💼 Business District</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;"> 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;">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;">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 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; min-height: 180px;"> <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;">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;'>Travel 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; min-height: 180px;"> <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;">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 Alleyway</div>">> <<goto "Alleyway">> <</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 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; min-height: 180px;"> <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;">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; min-height: 180px;"> <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;">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; min-height: 180px;"> <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;">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; min-height: 180px;"> <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;">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; 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;">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;'>Travel to Mall</div>">> <<goto "Mall">> <</link>> </div> </div> </div> <</nobr>><<nobr>> <<set $lastLocation = "RedLightDistrict">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff1493; text-align: center;">🔴 Red Light District</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;"> 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> <h2 style="color: #ff1493;">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;"> <h3 style="color: #ffc107; margin-top: 0;">🚌 Bus Stop</h3> <p style="font-size: 14px; color: #aaa; 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> <!-- 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;">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 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-top: 0;">💼 Business District</h3> <p style="font-size: 14px; color: #aaa; 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 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-top: 0;">⚓ Docks</h3> <p style="font-size: 14px; color: #aaa; 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;'>Travel 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-top: 0;">🌆 Alleyway</h3> <p style="font-size: 14px; color: #aaa; 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 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; 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;">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;'>Travel to Outskirts</div>">> <<goto "Outskirts">> <</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-top: 0;">💋 Azure Angelfish Lounge</h3> <p style="font-size: 14px; color: #aaa; 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-top: 0;">🪼 Electric Jelly Revue</h3> <p style="font-size: 14px; color: #aaa; 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-top: 0;">🎰 The Silver Marlin</h3> <p style="font-size: 14px; color: #aaa; 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> <</nobr>><<nobr>> <<set $lastLocation = "Docks">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #3498db; text-align: center;">⚓ Docks</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;"> 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> <!-- 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;">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> <!-- 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> </div> <!-- NPCs Section --> <<set _npcsHere = setup.getNPCsByJob("Dock Worker")>> <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);"> <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 #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: #999; margin: 0 0 10px 0;"><<print _npc.jobs.join(", ")>></p> <<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>> <</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="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>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffc107; text-align: center;">🚌 Bus Stop</h1> <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>> <<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> <<if $busPassDaysRemaining && $busPassDaysRemaining > 0>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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> <!-- 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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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>> <<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> </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>">> <<travel>> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>><<nobr>> <<if !setup.isMallOpen()>> <<goto "MallClosed">> <</if>> <<set $lastLocation = "Mall">> <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="font-size: 14px; color: #aaa; 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: 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> </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=State.variables.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}`;State.variables.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}`;State.variables.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=`<<set $bodyPartImages = ${JSON.stringify(State.variables.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><<endnobr>><<nobr>> <<set $lastLocation = "FitnessShop">> <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;">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.getNPCsByJob("Fitness Shop Clerk")>> <<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>> <<if setup.isNPCAvailable(_npc.name)>> <<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>> <</if>> <</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">> <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, #e91e63 0%, #c2185b 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> <!-- 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">> <<if _stylingCost > 0 && $money < _stylingCost>> <!-- 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: 13px; color: #aaa; margin-bottom: 10px;">Duration: 7 days</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> <p style="font-size: 13px; color: #aaa; margin-bottom: 10px;">Duration: 7 days</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 $money -= _stylingCost>> <</if>> <<set $appearance.hairStyle = "styled">> <<set $hairStyleExpiry = $dayNumber + 7>> <<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> <<set _daysRemaining = $hairStyleExpiry - $dayNumber>> <<if _daysRemaining > 0>> <p style="font-size: 13px; color: #51cf66; margin-bottom: 15px;">Expires in _daysRemaining day<<if _daysRemaining !== 1>>s<</if>></p> <<else>> <p style="font-size: 13px; color: #ffc107; margin-bottom: 15px;">Styling wearing off...</p> <</if>> <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>> <<if _haircutCost > 0 && $money < _haircutCost>> <!-- 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 $money -= _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>> <!-- 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>> <<if setup.isNPCAvailable(_npc.name)>> <<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>> <</if>> <</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">> <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;">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.getNPCsByJob("Ecentric Shop Worker")>> <<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>> <<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> <<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>> <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">> <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> <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.getNPCsByJob("Adult Store Clerk")>> <<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>> <<if setup.isNPCAvailable(_npc.name)>> <<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>> <</if>> <</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">> <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> <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.getNPCsByJob("Baker")>> <<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>> <<if setup.isNPCAvailable(_npc.name)>> <<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>> <</if>> <</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">> <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> <h2 style="color: #17a2b8;">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] === "Tech 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.getNPCsByJob("Tech Store Clerk")>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="margin-top: 30px; color: #17a2b8;">People Here</h2> <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>> <<if setup.isNPCAvailable(_npc.name)>> <<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>> <</if>> <</for>> </div> </div> <<else>> <h2 style="margin-top: 30px; color: #17a2b8;">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>><<silently>> <<nobr>> /* Set current and previous passage variables */ <<set _currentPassage = passage()>> <<set _previousPassage = previous()>> <<if $tradingWithNPC && _currentPassage === "NPCInteraction">> <<run setup.meetNPC($tradingWithNPC)>> <</if>> /* List of passages that should NOT be saved as lastLocation */ <<set _excludedPassages = [ "Relationships", "RelationshipDetail", "Debug", "Body", "StoryInit", "PassageHeader", "StoryCaption", "TradeInterface", "TradeSelectItems", "TradeResult", "NPCInteraction", "NPCTalk", "NPCTalkResponse", "FenRisTraining", "GymNPCs", "GymLockerRoom", "ImageSettings", "BusStop" ]>> /* Only update lastLocation if this is a real game location */ <<if !_excludedPassages.includes(_currentPassage) && _currentPassage !== "">> <<set $lastLocation = _currentPassage>> <</if>> /* Rest of your existing PassageHeader code goes here */ /* Check if we should skip time advancement */ <<if $skipTimeAdvancement>> <<set $skipTimeAdvancement = false>> <<else>> <<if !setup.timePassages>> <<set setup.timePassages = { main: ["BusinessDistrict", "Downtown", "ResidentialArea", "Park", "Beach", "University", "Hospital", "Library", "Gym", "Alleyway", "RedLightDistrict", "Docks", "BusStop", "Outskirts", "SeabassPark"], sublocations: ["Gym", "DanceStudio", "Cafe", "TrainingCenter", "Apartments", "TownHall", "ShadyShop", "Brothel", "StripClub", "Casino","LampreyTomes"], mall: ["Mall", "FitnessShop", "EcentricShop", "BeautySalon", "TechStore", "AdultStore", "Bakery", "FoodCourt", "MallAtrium"], noTime: ["Start", "CharacterCreation", "StoryInit", "Summary", "NPCFirstMeeting", "NPCEncounter", "NPCChat", "NPCSkillTalk", "NPCInterestTalk", "TradingInterface", "ProcessTrade", "TradeSuccess", "TradeFailure", "Body", "Debug"] }>> <</if>> <<if !setup.timePassages.noTime.includes(_currentPassage) && _previousPassage !== _currentPassage && _previousPassage !== "">> <<if setup.timePassages.main.includes(_currentPassage)>> <<set $timeInMinutes += 15>> <<if $timeInMinutes >= 1440>> <<set $timeInMinutes -= 1440>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<if _currentDayIndex < $dayOrder.length - 1>> <<set $dayOfWeek = $dayOrder[_currentDayIndex + 1]>> <<else>> <<set $dayOfWeek = $dayOrder[0]>> <<set $weekNumber += 1>> <</if>> <<set $dayNumber += 1>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> <</if>> <<elseif setup.timePassages.sublocations.includes(_currentPassage)>> <<set $timeInMinutes += 5>> <<if $timeInMinutes >= 1440>> <<set $timeInMinutes -= 1440>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<if _currentDayIndex < $dayOrder.length - 1>> <<set $dayOfWeek = $dayOrder[_currentDayIndex + 1]>> <<else>> <<set $dayOfWeek = $dayOrder[0]>> <<set $weekNumber += 1>> <</if>> <<set $dayNumber += 1>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> <</if>> <<elseif setup.timePassages.mall.includes(_currentPassage)>> <<if _previousPassage === "Mall">> <<set $timeInMinutes += 2>> <<else>> <<set $timeInMinutes += 5>> <</if>> <<if $timeInMinutes >= 1440>> <<set $timeInMinutes -= 1440>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<if _currentDayIndex < $dayOrder.length - 1>> <<set $dayOfWeek = $dayOrder[_currentDayIndex + 1]>> <<else>> <<set $dayOfWeek = $dayOrder[0]>> <<set $weekNumber += 1>> <</if>> <<set $dayNumber += 1>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> <</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: 300, dexterity: 300, strength: 300, intelligence: 300 }>> /* ---------------------------------- */ /* --- 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 physique exists */ <<if !$appearance.physique>> <<set $appearance.physique = "average">> <</if>> /* Make sure hairStyle is messy */ <<if !$appearance.hairStyle>> <<set $appearance.hairStyle = "messy">> <</if>> /* ---------------------------------- */ /* --- PLAYER BODY PARTS --- */ /* ---------------------------------- */ <<set $bodyParts = { gender: "male", chest: "flat masculine", butt: "flat masculine" }>> /* ---------------------------------- */ /* --- PLAYER TRAITS & SKILLS --- */ /* ---------------------------------- */ <<set $physicalTraits = []>> <<set $mentalTraits = []>> <<set $selectedTraits = []>> <<set $skills = []>> /* Trait definitions for character creation */ <<set $availableTraits = { "Quick Learner": "Gain skills faster", "Swift": "Increased dexterity", "Silver-Tongued": "Increased charisma", "Pensive": "Increased intelligence", "Jock": "Increased strength", "Naturally Gifted": "All stats increased" }>> /* Available physical traits */ <<set $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", "Broad-shouldered": "Wide shoulders", "Quick": "Fast movements", "Sturdy": "Solid build", "Fashionable": "Stylish appearance", "Quick Reflexes": "Fast reactions", "Fast": "High speed", "Slow": "Low speed" }>> /* Available voice traits */ <<set $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 $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", "Immature": "Childish behavior", "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", "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", "Tech Savvy": "Good with technology" }>> /* Stereotype traits */ <<set $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 $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" }>> /* ---------------------------------- */ /* --- PLAYER STATUS --- */ /* ---------------------------------- */ <<set $homeless = true>> <<set $jobs = []>> <<set $money = 0>> <</silently>> /* ---------------------------------- */ /* --- SHADY SHOP TRACKING --- */ /* ---------------------------------- */ <<set $shadyDealsToday = 0>> <<set $lastFenRisTrainingDay = -1>> /* ---------------------------------- */ /* --- RELATIONSHIP SYSTEM --- */ /* ---------------------------------- */ <<set setup.relationshipLevels = [ {level: 1, name: "Stranger", minXp: 0, maxXp: 20, color: "#666666"}, {level: 2, name: "Acquaintance", minXp: 20, maxXp: 70, color: "#51cf66"}, {level: 3, name: "Friend", minXp: 70, maxXp: 170, color: "#4dabf7"}, {level: 4, name: "Close Friend", minXp: 170, maxXp: 420, color: "#9b59b6"}, {level: 5, name: "Lover", minXp: 420, maxXp: 920, color: "#ff6b9d"} ]>> /* 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: 1, xp: 0, maxXp: 20, levelName: "Stranger", loverUnlocked: false }>> <</for>> /* Function to add relationship XP */ <<set setup.addRelationshipXP = function(npcName, xpAmount) { var v = State.variables; if (!v.npcRelationships[npcName]) { v.npcRelationships[npcName] = { level: 1, xp: 0, maxXp: 20, levelName: "Stranger", loverUnlocked: false }; } var rel = v.npcRelationships[npcName]; rel.xp += xpAmount; // Level up logic while (rel.xp >= rel.maxXp && rel.level < 5) { rel.level++; var levelData = setup.relationshipLevels[rel.level - 1]; rel.levelName = levelData.name; rel.maxXp = levelData.maxXp - levelData.minXp; rel.xp = rel.xp - (setup.relationshipLevels[rel.level - 2].maxXp - setup.relationshipLevels[rel.level - 2].minXp); } // Cap at max XP for level 5 if not unlocked if (rel.level === 5 && !rel.loverUnlocked && rel.xp >= rel.maxXp) { rel.xp = rel.maxXp; } }>> /* Function to unlock lover status */ <<set setup.unlockLoverStatus = function(npcName) { var v = State.variables; if (v.npcRelationships[npcName] && v.npcRelationships[npcName].level === 5) { v.npcRelationships[npcName].loverUnlocked = true; v.npcRelationships[npcName].levelName = "Lover"; } }>> /* Function to get relationship color */ <<set setup.getRelationshipColor = function(level) { return setup.relationshipLevels[level - 1].color; }>> /* 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>>test:: InitTimeSystem <<silently>> /* ---------------------------------- */ /* --- TIME & DAY TRACKING --- */ /* ---------------------------------- */ <<set $timeInMinutes = 480>> /* Start at 8:00 AM */ <<set $dayOfWeek = "Monday">> <<set $dayNumber = 1>> <<set $weekNumber = 1>> <<set $dayOrder = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]>> /* ---------------------------------- */ /* --- TRADE LIMITS --- */ /* ---------------------------------- */ <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> /* ---------------------------------- */ /* --- WORK TRACKING --- */ /* ---------------------------------- */ <<set $hoursWorkedToday = 0>> <<set $lastWorkDay = 0>> <</silently>> /* Check if hair styling has expired */ <<if $hairStyleExpiry && $dayNumber >= $hairStyleExpiry>> <<set $appearance.hairStyle = "messy">> <<set $hairStyleExpiry = null>> <</if>> /* 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> 9:00 AM - 5:00 PM<br> <strong>Current Time:</strong> <<= getTimeString()>> </p> <p style="color: #aaaaaa; margin-top: 20px;"> The mall opens at 9:00 AM and closes at 5:00 PM. Come back during business hours! </p> </div> <br> <div style="text-align: center;"> [[Leave|BusinessDistrict]] </div> <</nobr>><<nobr>> <<set _relColor = "#667eea">> <!-- Password Check --> <<if !$cheatMenuUnlocked>> <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;"> <<textbox "_cheatPassword" "" "autofocus">> </div> <span id="passwordError" style="color: #ff6b6b; font-size: 14px; display: none; margin-bottom: 15px;">❌ Incorrect password. Please try again.</span> <<link "<div 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>">> <<set _correctPassword = "Krakendeeznutzgottem">> /* Are you realling using inspect element to find the password? smh. */ <<if _cheatPassword === _correctPassword>> <<set $cheatMenuUnlocked = true>> <<goto "Debug">> <<else>> <<run $("#passwordError").show()>> <</if>> <</link>> <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> <<else>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- 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);'>← Return to game</div>">> <<goto $lastLocation>> <</link>> </div> <!-- 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);">⚙️ Cheat Menu</h1> </div> <span id="cheatMenuContent"> <!-- Time & Date Section --> <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;">⏰ Time & Date</h2> <!-- Current Time Display --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; color: #e0e0e0; font-size: 15px;"> <div> <strong style="color: #4dabf7;">Current Time:</strong><br> <span id="currentTime" style="color: #51cf66; font-size: 18px; font-weight: bold;"><<= getTimeString()>></span> </div> <div> <strong style="color: #4dabf7;">Date:</strong><br> <span id="currentDate" style="color: #ffd43b; font-size: 18px; font-weight: bold;">$dayOfWeek, Day $dayNumber</span> </div> </div> </div> <!-- Quick Time Adjustments --> <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;">Quick Time Adjustments</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>+30 Minutes</div>">> <<run advanceTime(30)>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> <<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>+1 Hour</div>">> <<run advanceTime(60)>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> </div> </div> <!-- Set Specific Time --> <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;">Set Specific Time</h3> <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;"> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>6 AM</div>">> <<set $timeInMinutes = 360>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>9 AM</div>">> <<set $timeInMinutes = 540>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>12 PM</div>">> <<set $timeInMinutes = 720>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff8787 0%, #ff6b6b 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>3 PM</div>">> <<set $timeInMinutes = 900>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff8787 0%, #ff6b6b 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>6 PM</div>">> <<set $timeInMinutes = 1080>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>10 PM</div>">> <<set $timeInMinutes = 1320>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <</link>> </div> </div> <!-- Day Controls --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Day Controls</h3> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 12px; border-radius: 8px; text-align: center; cursor: pointer; font-weight: bold; margin-bottom: 10px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Next Day (8 AM)</div>">> <<set $dayNumber += 1>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<set _nextDayIndex = (_currentDayIndex + 1) % 7>> <<set $dayOfWeek = $dayOrder[_nextDayIndex]>> <<if $dayOfWeek === "Monday">> <<set $weekNumber += 1>> <</if>> <<set $timeInMinutes = 480>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <<replace "#currentDate">>$dayOfWeek, Day $dayNumber<</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #da77f2 0%, #cc5de8 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);'>Next Week (Monday 8 AM)</div>">> <<set $weekNumber += 1>> <<set $dayOfWeek = "Monday">> <<set $dayNumber += 7>> <<set $timeInMinutes = 480>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> <<replace "#currentTime">><<= getTimeString()>><</replace>> <<replace "#currentDate">>$dayOfWeek, Day $dayNumber<</replace>> <</link>> </div> </div> <!-- Money Section --> <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;">💰 Money</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <p style="color: #e0e0e0; font-size: 18px; margin: 0 0 15px 0;"> <strong>Current Money:</strong> <span id="currentMoney" style="color: #51cf66;">$<<= $money.toLocaleString()>></span> </p> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px;"> <<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);'>+$50,000</div>">> <<set $money += 50000>> <<replace "#currentMoney">>$<<= $money.toLocaleString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 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);'>Set to $100,000</div>">> <<set $money = 100000>> <<replace "#currentMoney">>$<<= $money.toLocaleString()>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 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);'>Reset to $0</div>">> <<set $money = 0>> <<replace "#currentMoney">>$<<= $money.toLocaleString()>><</replace>> <</link>> </div> </div> </div> <!-- Stats Section --> <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;">📊 Stats</h2> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px;"> <!-- Strength --> <div> <p style="color: #ff6b6b; margin: 0 0 8px 0; font-weight: bold;">■ Strength: <span id="statStrength"><<= setup.getTotalStat("strength")>></span></p> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 14px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Set to 99</div>">> <<set $stats.strength = 99>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <</link>> </div> <!-- Dexterity --> <div> <p style="color: #51cf66; margin: 0 0 8px 0; font-weight: bold;">■ Dexterity: <span id="statDexterity"><<= setup.getTotalStat("dexterity")>></span></p> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 14px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Set to 99</div>">> <<set $stats.dexterity = 99>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <</link>> </div> <!-- Charisma --> <div> <p style="color: #ffd43b; margin: 0 0 8px 0; font-weight: bold;">■ Charisma: <span id="statCharisma"><<= setup.getTotalStat("charisma")>></span></p> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 14px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Set to 99</div>">> <<set $stats.charisma = 99>> <<replace "#statCharisma">><<= setup.getTotalStat("charisma")>><</replace>> <</link>> </div> <!-- Intelligence --> <div> <p style="color: #4dabf7; margin: 0 0 8px 0; font-weight: bold;">■ Intelligence: <span id="statIntelligence"><<= setup.getTotalStat("intelligence")>></span></p> <<link "<div style='background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 14px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Set to 99</div>">> <<set $stats.intelligence = 99>> <<replace "#statIntelligence">><<= setup.getTotalStat("intelligence")>><</replace>> <</link>> </div> </div> </div> </div> <!-- Body Parts Section --> <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;">👤 Body & Appearance</h2> <!-- Gender --> <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;">Gender: <span id="currentGender" style="color: #e0e0e0;"><<= $bodyParts.gender.charAt(0).toUpperCase() + $bodyParts.gender.slice(1)>></span></h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #ff6b9d 0%, #c92a2a 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Female</div>">> <<set $bodyParts.gender = "female">> <<replace "#currentGender">><<= $bodyParts.gender.charAt(0).toUpperCase() + $bodyParts.gender.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #4dabf7 0%, #1971c2 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Male</div>">> <<set $bodyParts.gender = "male">> <<replace "#currentGender">><<= $bodyParts.gender.charAt(0).toUpperCase() + $bodyParts.gender.slice(1)>><</replace>> <</link>> </div> </div> <!-- Chest Size --> <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;">Chest Size: <span id="currentChest" style="color: #e0e0e0;"><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>></span></h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px;"> <<link "<div style='background: linear-gradient(135deg, #868e96 0%, #495057 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Flat Masculine</div>">> <<set $bodyParts.chest = "flat masculine">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #868e96 0%, #495057 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Flat</div>">> <<set $bodyParts.chest = "flat">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #a9d5de 0%, #74c0fc 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Small</div>">> <<set $bodyParts.chest = "small">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #91a7ff 0%, #748ffc 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Medium</div>">> <<set $bodyParts.chest = "medium">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #da77f2 0%, #cc5de8 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Large</div>">> <<set $bodyParts.chest = "large">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b9d 0%, #f06595 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Huge</div>">> <<set $bodyParts.chest = "huge">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff8787 0%, #ff6b6b 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Giant</div>">> <<set $bodyParts.chest = "giant">> <<replace "#currentChest">><<= $bodyParts.chest.charAt(0).toUpperCase() + $bodyParts.chest.slice(1)>><</replace>> <</link>> </div> </div> <!-- Butt Size --> <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;">Butt Size: <span id="currentButt" style="color: #e0e0e0;"><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>></span></h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px;"> <<link "<div style='background: linear-gradient(135deg, #868e96 0%, #495057 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Flat Masculine</div>">> <<set $bodyParts.butt = "flat masculine">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #868e96 0%, #495057 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Flat</div>">> <<set $bodyParts.butt = "flat">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #a9d5de 0%, #74c0fc 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Small</div>">> <<set $bodyParts.butt = "small">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #91a7ff 0%, #748ffc 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Medium</div>">> <<set $bodyParts.butt = "medium">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #da77f2 0%, #cc5de8 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Large</div>">> <<set $bodyParts.butt = "large">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b9d 0%, #f06595 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Huge</div>">> <<set $bodyParts.butt = "huge">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff8787 0%, #ff6b6b 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 13px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Giant</div>">> <<set $bodyParts.butt = "giant">> <<replace "#currentButt">><<= $bodyParts.butt.charAt(0).toUpperCase() + $bodyParts.butt.slice(1)>><</replace>> <</link>> </div> </div> <!-- Skin Tone --> <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;">Skin Tone: <span id="currentSkinTone" style="color: #e0e0e0;"><<= $appearance.skinTone.charAt(0).toUpperCase() + $appearance.skinTone.slice(1)>></span></h3> <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #ffe8cc 0%, #ffd8a8 100%); color: #333; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Pale</div>">> <<set $appearance.skinTone = "pale">> <<replace "#currentSkinTone">><<= $appearance.skinTone.charAt(0).toUpperCase() + $appearance.skinTone.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #d9b99b 0%, #b7856a 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Tan</div>">> <<set $appearance.skinTone = "tan">> <<replace "#currentSkinTone">><<= $appearance.skinTone.charAt(0).toUpperCase() + $appearance.skinTone.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #8d6e63 0%, #5d4037 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Dark</div>">> <<set $appearance.skinTone = "dark">> <<replace "#currentSkinTone">><<= $appearance.skinTone.charAt(0).toUpperCase() + $appearance.skinTone.slice(1)>><</replace>> <</link>> </div> </div> <!-- Hair Color --> <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;">Hair Color: <span id="currentHairColor" style="color: #e0e0e0;"><<= $appearance.hairColor>></span></h3> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); gap: 8px;"> <<link "<div style='background: linear-gradient(135deg, #212529 0%, #000000 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Black</div>">> <<set $appearance.hairColor = "Black">> <<replace "#currentHairColor">><<= $appearance.hairColor>><</replace>> <</link>> <<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Brown</div>">> <<set $appearance.hairColor = "Brown">> <<replace "#currentHairColor">><<= $appearance.hairColor>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ffe066 0%, #ffd43b 100%); color: #333; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Blonde</div>">> <<set $appearance.hairColor = "Blonde">> <<replace "#currentHairColor">><<= $appearance.hairColor>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff8787 0%, #fa5252 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Red</div>">> <<set $appearance.hairColor = "Red">> <<replace "#currentHairColor">><<= $appearance.hairColor>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #f1f3f5 0%, #dee2e6 100%); color: #333; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Platinum</div>">> <<set $appearance.hairColor = "Platinum Blonde">> <<replace "#currentHairColor">><<= $appearance.hairColor>><</replace>> <</link>> </div> </div> <!-- Hair Length --> <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;">Hair Length: <span id="currentHairLength" style="color: #e0e0e0;"><<= $appearance.hairLength.charAt(0).toUpperCase() + $appearance.hairLength.slice(1)>></span></h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<div style='background: linear-gradient(135deg, #748ffc 0%, #5c7cfa 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Short</div>">> <<set $appearance.hairLength = "short">> <<if $physicalTraits.includes("Long Hair")>> <<run $physicalTraits.delete("Long Hair")>> <</if>> <<if !$physicalTraits.includes("Short Hair")>> <<run $physicalTraits.push("Short Hair")>> <</if>> <<replace "#currentHairLength">><<= $appearance.hairLength.charAt(0).toUpperCase() + $appearance.hairLength.slice(1)>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #da77f2 0%, #cc5de8 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Long</div>">> <<set $appearance.hairLength = "long">> <<if $physicalTraits.includes("Short Hair")>> <<run $physicalTraits.delete("Short Hair")>> <</if>> <<if !$physicalTraits.includes("Long Hair")>> <<run $physicalTraits.push("Long Hair")>> <</if>> <<replace "#currentHairLength">><<= $appearance.hairLength.charAt(0).toUpperCase() + $appearance.hairLength.slice(1)>><</replace>> <</link>> </div> </div> <!-- Age --> <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;">Age: <span id="currentAge" style="color: #e0e0e0;"><<= $appearance.age>></span></h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Adult</div>">> <<set $appearance.age = "Adult">> <<replace "#currentAge">><<= $appearance.age>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #868e96 0%, #495057 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Mature Adult</div>">> <<set $appearance.age = "Mature Adult">> <<replace "#currentAge">><<= $appearance.age>><</replace>> <</link>> </div> </div> <!-- Name --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Name: <span id="currentName" style="color: #e0e0e0;"><<= $firstName>> <<= $lastName>></span></h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 10px;"> <div> <label style="color: #aaa; font-size: 14px; display: block; margin-bottom: 5px;">First Name:</label> <<textbox "_newFirstName" $firstName>> </div> <div> <label style="color: #aaa; font-size: 14px; display: block; margin-bottom: 5px;">Last Name:</label> <<textbox "_newLastName" $lastName>> </div> </div> <<link "<div style='background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Update Name</div>">> <<if _newFirstName && _newFirstName.trim() !== "">> <<set $firstName = _newFirstName.trim()>> <</if>> <<if _newLastName && _newLastName.trim() !== "">> <<set $lastName = _newLastName.trim()>> <</if>> <<replace "#currentName">><<= $firstName>> <<= $lastName>><</replace>> <</link>> </div> </div> <!-- Job Management Section --> <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;">💼 Job Management</h2> <!-- Current Job Display --> <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;">Current Job:</h3> <span id="currentJob"> <<if $jobs && $jobs.length > 0>> <span style="color: #51cf66; font-size: 18px; font-weight: bold;"><<print $jobs[0]>></span> <<else>> <span style="color: #ff6b6b; font-size: 18px; font-weight: bold;">Unemployed</span> <</if>> </span> </div> <!-- Job Selection --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #4dabf7; margin: 0 0 10px 0;">Change Job:</h3> <select id="replaceJob" style="width: 100%; padding: 12px; background: #0a0a0a; color: #fff; border: 2px solid #667eea; border-radius: 8px; margin-bottom: 15px; font-size: 15px; cursor: pointer;"> <option value="">-- Select Job --</option> <option value="Unemployed">Unemployed</option> <option value="Street Performer">Street Performer</option> <option value="Package Courier">Package Courier</option> <option value="Construction Worker">Construction Worker</option> <option value="Dock Worker">Dock Worker</option> <option value="Security Guard">Security Guard</option> <option value="Baker">Baker</option> <option value="Maid">Maid</option> <option value="Hooker">Hooker</option> <option value="Stripper">Stripper</option> <option value="Prostitute">Prostitute</option> <option value="Fitness Shop Clerk">Fitness Shop Clerk</option> <option value="Ecentric Shop Worker">Ecentric Shop Worker</option> <option value="Tech Store Clerk">Tech Store Clerk</option> <option value="Adult Store Clerk">Adult Store Clerk</option> <option value="Beauty Salon Stylist">Beauty Salon Stylist</option> <option value="Brothel Worker">Brothel Worker</option> <option value="Model">Model</option> <option value="Bouncer">Bouncer</option> <option value="Clinic Assistant">Clinic Assistant</option> <option value="Data Analyst">Data Analyst</option> <option value="Negotiator">Negotiator</option> <option value="Enforcer">Enforcer</option> <option value="Porn Star">Porn Star</option> <option value="Social Media Influencer">Social Media Influencer</option> <option value="Black Market Dealer">Black Market Dealer</option> <option value="Police Officer">Police Officer</option> <option value="Brothel Owner">Brothel Owner</option> <option value="Mayor's Secretary">Mayor's Secretary</option> <option value="City Mayor">City Mayor</option> <option value="Fitness Trainer">Fitness Trainer</option> </select> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 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);'>Apply Job Change</div>">> <<set _selectedJob = jQuery("#replaceJob").val()>> <<if _selectedJob && _selectedJob !== "">> <<if _selectedJob === "Unemployed">> <<set $jobs = []>> <<set $homeless = true>> <<else>> <<set $jobs = [_selectedJob]>> <<set $homeless = false>> /* Update stats to meet job requirements */ <<set _jobReqs = setup.jobRequirements[_selectedJob] || {}>> <<for _stat, _minValue range _jobReqs>> <<if $stats[_stat] < _minValue>> <<set $stats[_stat] = _minValue>> <</if>> <</for>> <</if>> <<replace "#currentJob">> <<if $jobs && $jobs.length > 0>> <span style="color: #51cf66; font-size: 18px; font-weight: bold;"><<print $jobs[0]>></span> <<else>> <span style="color: #ff6b6b; font-size: 18px; font-weight: bold;">Unemployed</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <<replace "#statCharisma">><<= setup.getTotalStat("charisma")>><</replace>> <<replace "#statIntelligence">><<= setup.getTotalStat("intelligence")>><</replace>> <</if>> <</link>> </div> </div> <!-- Special Skills Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #ff6b9d; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #ff6b9d; margin: 0 0 15px 0;">🧪 Special Skills</h2> <!-- BtestBraitBeesBigBeenore --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0;">BtestBraitBeesBigBeenore</h3> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;">Ultimate power skill with 999 trade value and +90 to all stats</p> <div style="background-color: #0a0a0a; padding: 12px; border-radius: 6px; margin-bottom: 12px; border: 1px solid #444;"> <strong style="color: #ff6b9d;">Status:</strong> <span id="btestStatus"> <<if $skills.includes("BtestBraitBeesBigBeenore")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> </span> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>➕ Add</div>">> <<if !$skills.includes("BtestBraitBeesBigBeenore")>> <<run $skills.push("BtestBraitBeesBigBeenore")>> <</if>> <<replace "#btestStatus">> <<if $skills.includes("BtestBraitBeesBigBeenore")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <<replace "#statCharisma">><<= setup.getTotalStat("charisma")>><</replace>> <<replace "#statIntelligence">><<= setup.getTotalStat("intelligence")>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>❌ Remove</div>">> <<if $skills.includes("BtestBraitBeesBigBeenore")>> <<run $skills.delete("BtestBraitBeesBigBeenore")>> <</if>> <<replace "#btestStatus">> <<if $skills.includes("BtestBraitBeesBigBeenore")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <<replace "#statCharisma">><<= setup.getTotalStat("charisma")>><</replace>> <<replace "#statIntelligence">><<= setup.getTotalStat("intelligence")>><</replace>> <</link>> </div> </div> <!-- Were-Creature --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0;">Were-Creature</h3> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;">Powerful transformation skill with 450 trade value and +20 Strength/Dexterity</p> <div style="background-color: #0a0a0a; padding: 12px; border-radius: 6px; margin-bottom: 12px; border: 1px solid #444;"> <strong style="color: #ff6b9d;">Status:</strong> <span id="wereStatus"> <<if $skills.includes("Were-Creature")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> </span> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>➕ Add</div>">> <<if !$skills.includes("Were-Creature")>> <<run $skills.push("Were-Creature")>> <</if>> <<replace "#wereStatus">> <<if $skills.includes("Were-Creature")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>❌ Remove</div>">> <<if $skills.includes("Were-Creature")>> <<run $skills.delete("Were-Creature")>> <</if>> <<replace "#wereStatus">> <<if $skills.includes("Were-Creature")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <</link>> </div> </div> <!-- Sunfish --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #ff6b9d; margin: 0 0 10px 0;">Sunfish</h3> <p style="color: #aaa; margin: 0 0 10px 0; font-size: 14px;">Legendary aquatic skill with 500 trade value and +50 to all stats</p> <div style="background-color: #0a0a0a; padding: 12px; border-radius: 6px; margin-bottom: 12px; border: 1px solid #444;"> <strong style="color: #ff6b9d;">Status:</strong> <span id="sunfishStatus"> <<if $skills.includes("Sunfish")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> </span> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<link "<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>➕ Add</div>">> <<if !$skills.includes("Sunfish")>> <<run $skills.push("Sunfish")>> <</if>> <<replace "#sunfishStatus">> <<if $skills.includes("Sunfish")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <<replace "#statCharisma">><<= setup.getTotalStat("charisma")>><</replace>> <<replace "#statIntelligence">><<= setup.getTotalStat("intelligence")>><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>❌ Remove</div>">> <<if $skills.includes("Sunfish")>> <<run $skills.delete("Sunfish")>> <</if>> <<replace "#sunfishStatus">> <<if $skills.includes("Sunfish")>> <span style="color: #51cf66; font-size: 16px; font-weight: bold;"> ✓ Active</span> <<else>> <span style="color: #ff6b6b; font-size: 16px; font-weight: bold;"> ✗ Inactive</span> <</if>> <</replace>> <<replace "#statStrength">><<= setup.getTotalStat("strength")>><</replace>> <<replace "#statDexterity">><<= setup.getTotalStat("dexterity")>><</replace>> <<replace "#statCharisma">><<= setup.getTotalStat("charisma")>><</replace>> <<replace "#statIntelligence">><<= setup.getTotalStat("intelligence")>><</replace>> <</link>> </div> </div> </div> <!-- NPC Relationship Management Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #e91e63; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #e91e63; margin: 0 0 15px 0;">💕 NPC Relationship Management</h2> <span id="relationshipsSection"> <<include "CheatMenuRelationships">> </span> </div> <!-- Physical Traits 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;"> <h2 style="color: #51cf66; margin: 0 0 15px 0;">💪 Physical Traits</h2> <!-- Current Physical Traits --> <span id="physicalTraitsSection"> <<include "CheatMenuPhysicalTraits">> </span> </div> <!-- Voice Traits Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #da77f2; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #da77f2; margin: 0 0 15px 0;">🎤 Voice Trait</h2> <span id="voiceTraitsSection"> <<include "CheatMenuVoiceTraits">> </span> </div> <!-- Mental Traits Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #9b59b6; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #9b59b6; margin: 0 0 15px 0;">🧠 Mental Traits</h2> <span id="mentalTraitsSection"> <<include "CheatMenuMentalTraits">> </span> </div> <!-- Skills Section --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #ff922b; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 20px;"> <h2 style="color: #ff922b; margin: 0 0 15px 0;">⚡ Skills</h2> <span id="skillsSection"> <<include "CheatMenuSkills">> </span> </div> </span> <!-- 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);'>← Return to game</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</if>> <</nobr>>/* This passage runs before StoryInit */ /* IMPORTANT: This passage MUST have the tag "script" */ /* NPC Generation Function */ setup.generateNPC = function(name, jobs, overrides) { var genders = ["male", "female"]; var skinTones = ["pale", "tan", "dark"]; var hairColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]; var hairStyles = ["messy", "short", "long", "ponytail"]; var physiques = ["slim", "athletic", "stocky", "average"]; var chestSizes = ["flat", "small", "medium", "large", "huge"]; var buttSizes = ["flat", "small", "medium", "large", "huge"]; var skills = ["Cooking", "Singing", "Dancing", "Painting", "Writing", "Photography", "Guitar", "Piano", "Coding", "Math Skills", "Languages", "Public Speaking", "Athletics", "Yoga", "Swimming", "Martial Arts", "Heavy Lifting", "Combat", "Persuasion", "Medicine", "Trading", "Stealth", "Driving", "Lock Picking", "First Aid", "Gardening", "Construction", "Social Media", "Baking", "Sexually Skilled", "Modeling", "Makeup", "High Heels Proficient", "Hair Styling", "Cleaning", "Maid", "Serving", "Plumbing"]; var physicalTraits = ["Tall", "Short", "Muscular", "Curvy", "Petite", "Broad-shouldered", "Flexible", "Strong", "Quick", "Graceful", "Sturdy", "Lean", "Soft", "Sharp Features", "Smooth Skin", "Scarred", "Pierced", "Youthful", "Mature", "Tattooed"]; var mentalTraits = ["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", "Jealous", "Supportive", "Lazy", "Hardworking", "Arrogant", "Humble", "Paranoid", "Trusting", "Complacent", "Dull", "Brave", "Cowardly", "Immature", "Impatient", "Wise", "Foolish", "Nonchalant", "Charming", "Diplomatic", "Organized", "Resourceful", "Focused", "Disciplined", "Determined", "Steadfast", "Considerate", "Blunt", "Perfectionist", "Overthinker", "Moody", "Unpredictable", "Risk Taker", "Impulsive", "Cynical", "Forgetful", "Disorganized", "Selfish", "Deceitful", "Erratic", "Obsessive", "Insecure", "Short Tempered", "Polite", "Funny", "Reassuring", "Loyal", "Talkative", "Direct", "Quiet", "Rude", "Awkward", "Tone Deaf", "Efficient", "Negotiator", "Crafty", "Workaholic", "Unreliable", "Slow Learner", "High Stamina", "Reckless", "Flirty", "Seductive", "Alluring", "Warm", "Cold", "Tease", "Clingy", "Insensitive", "Sensitive", "Bookworm", "Unskilled", "Corporate Drone", "Lucky", "Unlucky", "Nerd", "Geek", "Jock", "Prep", "Tomboy", "Femboy", "Diva", "Goth"]; "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"]; /* Add character creation traits to possible mental traits */ var characterTraits = ["Quick Learner", "Swift", "Silver-Tongued", "Pensive", "Jock", "Naturally Gifted"]; function getRandomItems(array, count) { var shuffled = array.sort(function() { return 0.5 - Math.random(); }); return shuffled.slice(0, count); } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } var gender = genders[Math.floor(Math.random() * genders.length)]; var skinTone = skinTones[Math.floor(Math.random() * skinTones.length)]; /* Generate stats (1-20, capped at 12 unless professional) */ var jobData = State.variables.availableJobs[Array.isArray(jobs) ? jobs[0] : jobs]; var isProfessional = jobData && jobData.income >= 5; var statMax = isProfessional ? 20 : 12; var npcStats = { charisma: getRandomInt(1, statMax), dexterity: getRandomInt(1, statMax), strength: getRandomInt(1, statMax), intelligence: getRandomInt(1, statMax) }; /* Initialize NPC stat max caps */ var npcStatMaxCaps = { charisma: 20, dexterity: 20, strength: 20, intelligence: 20 }; /* Generate hard traits (randomized difficulty) */ var hardTraits = {}; var allSkills = overrides && overrides.skills ? overrides.skills : getRandomItems(skills, getRandomInt(2, 5)); var allPhysicalTraits = getRandomItems(physicalTraits, getRandomInt(2, 4)); /* Mental traits - randomly include character creation traits */ var baseMentalTraits = overrides && overrides.mentalTraits ? overrides.mentalTraits : getRandomItems(mentalTraits, getRandomInt(2, 4)); var allMentalTraits = baseMentalTraits.slice(); /* 20% chance to have one character creation trait */ if (Math.random() < 0.2) { var charTrait = characterTraits[Math.floor(Math.random() * characterTraits.length)]; allMentalTraits.push(charTrait); } /* Randomize difficulty for each trait */ allSkills.forEach(function(skill) { hardTraits["skill:" + skill] = getRandomInt(0, 40); }); allPhysicalTraits.forEach(function(trait) { hardTraits["physical:" + trait] = getRandomInt(0, 40); }); allMentalTraits.forEach(function(trait) { hardTraits["mental:" + trait] = getRandomInt(0, 40); }); ["charisma", "dexterity", "strength", "intelligence"].forEach(function(stat) { hardTraits["stat:" + stat] = getRandomInt(0, 40); }); ["chest", "butt", "gender"].forEach(function(bodyPart) { hardTraits["bodyPart:" + bodyPart] = getRandomInt(10, 50); }); var npc = { name: name, jobs: Array.isArray(jobs) ? jobs : [jobs], stats: npcStats, statMaxCaps: npcStatMaxCaps, bodyParts: { gender: gender, chest: chestSizes[Math.floor(Math.random() * chestSizes.length)], butt: buttSizes[Math.floor(Math.random() * buttSizes.length)] }, appearance: { skinTone: skinTone, hairColor: hairColors[Math.floor(Math.random() * hairColors.length)], hairStyle: hairStyles[Math.floor(Math.random() * hairStyles.length)], physique: physiques[Math.floor(Math.random() * physiques.length)] }, skills: allSkills, physicalTraits: allPhysicalTraits, mentalTraits: allMentalTraits, hardTraits: hardTraits }; /* Apply bonuses from character creation traits */ allMentalTraits.forEach(function(trait) { if (setup.traitBonuses && setup.traitBonuses[trait]) { setup.applyTraitBonus(trait, npc); } }); return npc; };:: 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; }>> /* ---------------------------------- */ /* --- NPC SCHEDULES --- */ /* ---------------------------------- */ <<set $npcSchedules = { /* Main Story NPCs */ "Marcus Carter": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Elena Romero": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Silva Silva": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Grimm Patel": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["afternoon", "evening"], alwaysAvailable: true }, "Scarlett Vex": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["afternoon", "evening"], alwaysAvailable: true }, "Jade Nightshade": { days: ["Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Apollo Sterling": { days: ["Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Diamond Murphy": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Tank Morrison": { days: ["Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Candace Luxe": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Ruby Becker": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Sapphire Wallace": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Jasmine Abrams": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Ebony Vasquez": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Amber Skye": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Kate Velvet": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["afternoon", "evening", "night"], alwaysAvailable: true }, "Bella Carver": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, /* Construction Workers */ "Jake Steel": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Marco Rodriguez": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Tyrone Washington": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Sheryl Williams": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "David O'Brien": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, /* Dock Workers */ "Mike Murphy": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Carlos Mendez": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Jamal Rivers": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Rosa Otterino": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Keisha Jackson": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon"], alwaysAvailable: true }, /* City Government */ "Dick Richardson": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Creo Applesauce": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, /* Mall NPCs */ "Brad Icus": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Raven Bido": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Crystal Meffin": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Sophi Boris": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Naomi Light": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Kevin Oats": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Destiny Pumpkin": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["afternoon", "evening", "night"], alwaysAvailable: true }, "Alex Passionfruit": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["afternoon", "evening", "night"], alwaysAvailable: true }, "Hannah Chuckins": { days: ["Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon"], alwaysAvailable: true }, /* Other NPCs */ "Fen Ris": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["night"], alwaysAvailable: false }, "Pheiffer Coms": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening", "night"], alwaysAvailable: false }, "Selkira Onyxia": { days: ["Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Janis Besser": { days: ["Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Dennis Fungi": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["afternoon", "evening"], alwaysAvailable: true }, "Yvela Mushroom": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["afternoon", "evening"], alwaysAvailable: true }, "Banana Banana": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon"], alwaysAvailable: true }, "Xenis Aku": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], times: ["morning", "afternoon", "evening"], alwaysAvailable: true }, "Zanithar Galdenentri": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening", "night"], alwaysAvailable: true }, "Trixie Rye": { days: ["Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], alwaysAvailable: true }, "Revna McKraken": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["morning", "afternoon", "evening", "night"], alwaysAvailable: true } }>> /* ---------------------------------- */ /* --- MANUAL NPC CREATION FUNCTION --- */ /* ---------------------------------- */ <<set setup.createNPC = function(config) { var skinTones = ["pale", "tan", "dark"]; var hairColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]; var hairStyles = ["messy", "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, 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 }, 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, hardTraits: {} }; // 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", jobs: "Security Guard", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: ["Clinic Assistant", "Data Analyst"], gender: "female", chest: "small", butt: "small", 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", jobs: ["Package Courier", "Negotiator"], gender: "female", chest: "medium", butt: "medium", 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", jobs: ["Negotiator", "Enforcer"], gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Porn Star", gender: "female", chest: "huge", butt: "huge", 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", jobs: "Stripper", gender: "female", chest: "large", butt: "large", 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", jobs: "Stripper", gender: "male", chest: "flat masculine", butt: "flat masculine", 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" }))>> /* Diamond Murphy - Hooker */ <<run $npcs.push(setup.createNPC({ name: "Diamond Murphy", jobs: "Hooker", gender: "female", chest: "large", butt: "large", 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", jobs: "Bouncer", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Brothel Worker", gender: "female", chest: "huge", butt: "huge", 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" }))>> /* Ruby Becker - Brothel Worker */ <<run $npcs.push(setup.createNPC({ name: "Ruby Becker", jobs: "Brothel Worker", gender: "female", chest: "large", butt: "large", 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", jobs: "Brothel Worker", gender: "female", chest: "huge", butt: "large", 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", jobs: "Brothel Worker", gender: "female", chest: "medium", butt: "huge", 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", jobs: "Brothel Worker", gender: "female", chest: "large", butt: "huge", 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", jobs: "Brothel Worker", gender: "female", chest: "medium", butt: "large", 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", jobs: "Brothel Owner", gender: "female", chest: "huge", butt: "huge", 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"], skinTone: "pale", hairColor: "Red", hairLength: "long", age: "Mature Adult" }))>> /* Bella Carver - Social Media Influencer */ <<run $npcs.push(setup.createNPC({ name: "Bella Carver", jobs: "Social Media Influencer", gender: "female", chest: "large", butt: "large", 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", jobs: "Construction Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Construction Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Construction Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Construction Worker", gender: "female", chest: "small", butt: "medium", 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", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Dock Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Dock Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Dock Worker", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Dock Worker", gender: "female", chest: "small", butt: "medium", baseStats: {charisma: 18, dexterity: 22, strength: 30, intelligence: 18}, physicalTraits: ["Muscular", "Strong", "Athletic Build", "Tattooed"], mentalTraits: ["Hardworking", "Honest", "Calm", "Reliable", "Reserved"], 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", jobs: "Dock Worker", gender: "female", chest: "medium", butt: "large", 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", jobs: "City Mayor", gender: "male", chest: "flat masculine", butt: "flat masculine", 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" }))>> /* Creo Applesauce - Mayor's Secretary */ <<run $npcs.push(setup.createNPC({ name: "Creo Applesauce", jobs: "Mayor's Secretary", gender: "male", chest: "flat masculine", butt: "flat masculine", baseStats: {charisma: 60, dexterity: 25, strength: 15, intelligence: 75}, physicalTraits: ["Sharp Features", "Lean"], mentalTraits: ["Intelligent", "Analytical", "Patient", "Submissive", "Anxious", "Nerd"], 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", jobs: "Fitness Shop Clerk", gender: "male", chest: "flat masculine", butt: "flat masculine", 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" }))>> /* Raven Bido - Ecentric Shop Worker */ <<run $npcs.push(setup.createNPC({ name: "Raven Bido", jobs: "Ecentric Shop Worker", gender: "female", chest: "small", butt: "small", 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" }))>> /* Crystal Meffin - Beauty Salon Stylist */ <<run $npcs.push(setup.createNPC({ name: "Crystal Meffin", jobs: "Beauty Salon Stylist", gender: "female", chest: "medium", butt: "medium", 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", jobs: "Beauty Salon Stylist", gender: "female", chest: "large", butt: "large", 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", jobs: "Beauty Salon Stylist", gender: "female", chest: "small", butt: "medium", 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", jobs: "Tech Store Clerk", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Adult Store Clerk", gender: "female", chest: "huge", butt: "large", 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", jobs: "Adult Store Clerk", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Baker", gender: "female", chest: "medium", butt: "large", 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", jobs: "Fitness Trainer", gender: "female", chest: "huge", butt: "medium", 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" }))>> /* Pheiffer Coms - Police Officer */ <<run $npcs.push(setup.createNPC({ name: "Pheiffer Coms", jobs: "Police Officer", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Brothel Worker", gender: "female", chest: "giant", butt: "giant", 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", jobs: "Baker", gender: "female", chest: "small", butt: "small", 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", jobs: "Dancing Instructor", gender: "male", chest: "flat masculine", butt: "flat masculine", 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", jobs: "Dancing Instructor", gender: "female", chest: "medium", butt: "large", 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", jobs: "Barista", gender: "female", chest: "medium", butt: "medium", 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", jobs: "Bus Driver", gender: "male", chest: "flat masculine", butt: "flat masculine", 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" }))>> /* Zanithar Galdenentri - Unemployed */ <<run $npcs.push(setup.createNPC({ name: "Zanithar Galdenentri", jobs: "Unemployed", gender: "male", chest: "flat masculine", butt: "flat masculine", baseStats: {charisma: 15, dexterity: 15, strength: 12, intelligence: 35}, physicalTraits: ["Mature", "Underweight", "Mumbly Voice", "Freckled", "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", jobs: "Cocktail Waitress", gender: "female", chest: "huge", butt: "huge", 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", jobs: "Mysterious Book Shop owner", gender: "female", chest: "medium", butt: "medium", 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" }))>> /* Initialize permanent IDs for trading system */ <<for _npc range $npcs>> <<if !_npc.permanentId>> <<set _npc.permanentId = _npc.name>> <</if>> <</for>> <</silently>><<nobr>> <!-- Track the original location if not already in NPC flow --> <<if !$lastLocation || !["NPCInteraction", "NPCTalk", "NPCTalkResponse", "TradeInterface", "TradeSelectItems", "TradeResult"].includes($lastLocation)>> <<set $preNPCLocation = $lastLocation>> <</if>> <<set _npc = $tradingWithNPC>> <<if !_npc>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <p style="color: #ff6b6b;">Error: NPC not found.</p> <<if $lastLocation>> [[Go Back|$lastLocation]] <<else>> [[Go Back|Mall]] <</if>> </div> <<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="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;">Physique:</strong> <<print _npc.appearance.physique.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;">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> </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 --> <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>">> <<goto "NPCTalk">> <</link>> </div> <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>> <<goto $preNPCLocation>> <</link>> </div> </div> <</if>> <</nobr>><<nobr>> <<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: [] }>> <</if>> <<if !$npcTradePackage>> <<set $npcTradePackage = { stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: [] }>> <</if>> <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 _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;">$tradesRemainingToday / 5</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 _npc.name today! </div> <</if>> </div> <!-- Trade Value Calculation --> <<set _playerValue = setup.calculateTradeValue($playerTradePackage, true)>> <<set _npcValue = setup.calculateTradeValue($npcTradePackage, false)>> <!-- Apply preference-based adjustments FIRST (willing/reluctant) --> <<set _adjustedNpcValue = setup.calculatePreferenceValueAdjustment(_npc, $playerTradePackage, $npcTradePackage, _npcValue)>> <<set _preferenceAdjustment = _adjustedNpcValue - _npcValue>> <!-- THEN apply relationship-based threshold reduction --> <<set _relLevel = 0>> <<if $relationships[_npc.name]>> <<set _relLevel = $relationships[_npc.name].level>> <</if>> <<if _relLevel === 2>> <<set _adjustedNpcValue = Math.floor(_adjustedNpcValue * 0.95)>> <<elseif _relLevel === 3>> <<set _adjustedNpcValue = Math.floor(_adjustedNpcValue * 0.90)>> <<elseif _relLevel === 4>> <<set _adjustedNpcValue = Math.floor(_adjustedNpcValue * 0.85)>> <<elseif _relLevel >= 5>> <<set _adjustedNpcValue = Math.floor(_adjustedNpcValue * 0.80)>> <</if>> <!-- Calculate bonus breakdown for display --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _charismaBonus = 0>> <<if _totalCharisma > 0>> <<set _logValue = Math.log(_totalCharisma + 1) / Math.log(101)>> <<set _charismaBonus = Math.floor(8.67 * _logValue)>> <<if _totalCharisma > 100>> <<set _highBonus = ((_totalCharisma - 100) / 899) * (20 - 8)>> <<set _charismaBonus = Math.floor(8 + _highBonus)>> <</if>> <<set _charismaBonus = Math.max(0, Math.min(20, _charismaBonus))>> <</if>> <<set _tradingBonus = $skills.includes("Trading") ? 2 : 0>> <<set _persuasionBonus = $skills.includes("Persuasion") ? 3 : 0>> <<set _bitchyPenalty = $mentalTraits.includes("Bitchy") ? -5 : 0>> <!-- Initialize relationship level ONCE at the top --> <<set _relLevel = 1>> <<if $relationships[_npc.name]>> <<set _relLevel = $relationships[_npc.name].level>> <</if>> <!-- Calculate relationship bonus --> <<set _relationshipBonus = setup.getRelationshipTradeBonus(_npc.name)>> <!-- Calculate total modifier --> <<set _totalModifier = _charismaBonus + _tradingBonus + _persuasionBonus + _bitchyPenalty + _relationshipBonus>> <!-- Calculate final trade chance (ONCE) --> <<set _tradeChance = setup.calculateTradeChance(_playerValue, _adjustedNpcValue, _npc, $playerTradePackage, $npcTradePackage)>> <!-- Success Chance Modifiers Display --> <<if _totalModifier !== 0>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid <<if _totalModifier > 0>>#51cf66<<else>>#ff6b6b<</if>>;"> <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: +_charismaBonus% (Charisma: _totalCharisma) </div> <</if>> <<if _tradingBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Trading Skill: +_tradingBonus% </div> <</if>> <<if _persuasionBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Persuasion Skill: +_persuasionBonus% </div> <</if>> <<if _relationshipBonus > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Relationship Bonus: +_relationshipBonus% (Level _relLevel) </div> <</if>> <<if _bitchyPenalty < 0>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0;"> ✗ Bitchy Trait: _bitchyPenalty% </div> <</if>> <div style="color: <<if _totalModifier > 0>>#51cf66<<else>>#ff6b6b<</if>>; font-size: 15px; margin-top: 8px; font-weight: bold; border-top: 1px solid #444; padding-top: 8px;"> Total Modifier: <<if _totalModifier > 0>>+<</if>>_totalModifier% </div> </div> <</if>> <!-- Value Adjustment Breakdown --> <<if _preferenceAdjustment !== 0 || _relLevel > 1>> <<set _prefs = setup.getNPCPreferences(_npc)>> <<set _willingCount = 0>> <<set _desiredCount = 0>> <<set _reluctantCount = 0>> <!-- Count willing items in player's offer --> <<if _prefs && _prefs.willingToTrade>> <<for _trait range $playerTradePackage.physical>> <<if _prefs.willingToTrade.physical && _prefs.willingToTrade.physical.includes(_trait)>> <<set _willingCount++>> <</if>> <</for>> <<for _trait range $playerTradePackage.mental>> <<if _prefs.willingToTrade.mental && _prefs.willingToTrade.mental.includes(_trait)>> <<set _willingCount++>> <</if>> <</for>> <<for _skill range $playerTradePackage.skills>> <<if _prefs.willingToTrade.skills && _prefs.willingToTrade.skills.includes(_skill)>> <<set _willingCount++>> <</if>> <</for>> <</if>> <!-- Count desired items in player's offer --> <<if _prefs && _prefs.desires>> <<for _trait range $playerTradePackage.physical>> <<if _prefs.desires.physical && _prefs.desires.physical.includes(_trait)>> <<set _desiredCount++>> <</if>> <</for>> <<for _trait range $playerTradePackage.mental>> <<if _prefs.desires.mental && _prefs.desires.mental.includes(_trait)>> <<set _desiredCount++>> <</if>> <</for>> <<for _skill range $playerTradePackage.skills>> <<if _prefs.desires.skills && _prefs.desires.skills.includes(_skill)>> <<set _desiredCount++>> <</if>> <</for>> <</if>> <!-- Count reluctant items in NPC's offer --> <<if _prefs && _prefs.reluctantToTrade>> <<for _trait range $npcTradePackage.physical>> <<if _prefs.reluctantToTrade.physical && _prefs.reluctantToTrade.physical.includes(_trait)>> <<set _reluctantCount++>> <</if>> <</for>> <<for _trait range $npcTradePackage.mental>> <<if _prefs.reluctantToTrade.mental && _prefs.reluctantToTrade.mental.includes(_trait)>> <<set _reluctantCount++>> <</if>> <</for>> <<for _skill range $npcTradePackage.skills>> <<if _prefs.reluctantToTrade.skills && _prefs.reluctantToTrade.skills.includes(_skill)>> <<set _reluctantCount++>> <</if>> <</for>> <</if>> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 2px solid <<if _preferenceAdjustment > 0>>#ff6b6b<<else>>#51cf66<</if>>;"> <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: _npcValue </div> <<if _willingCount > 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Willing Items: _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: _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: _reluctantCount item<<if _reluctantCount > 1>>s<</if>> (+50% cost each) </div> <</if>> <<if _willingCount > 0 || _desiredCount > 0 || _reluctantCount > 0>> <<if _preferenceAdjustment > 0>> <div style="color: #ff6b6b; font-size: 14px; margin: 3px 0; font-style: italic;"> Total Preference Penalty: +<<print Math.abs(_preferenceAdjustment)>> </div> <<elseif _preferenceAdjustment < 0>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0; font-style: italic;"> Total Preference Discount: <<print _preferenceAdjustment>> </div> <</if>> <</if>> <<if _relLevel > 1>> <<set _relDiscount = _adjustedNpcValue - Math.floor(_adjustedNpcValue * [1.0, 1.0, 0.95, 0.90, 0.85, 0.80][_relLevel])>> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Relationship Discount (Level _relLevel): -_relDiscount </div> <</if>> <div style="color: <<if _adjustedNpcValue > _npcValue>>#ff6b6b<<else>>#51cf66<</if>>; font-size: 15px; margin-top: 8px; font-weight: bold; border-top: 1px solid #444; padding-top: 8px;"> Final NPC Value Required: _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 _excessValue more than required (+_excessPercent% extra) </div> <div style="color: #51cf66; font-size: 14px; margin: 3px 0;"> ✓ Base success chance from value: _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;">_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;">_npcValue</div> </div> <div style="background: #1a1a1a; padding: 20px; border-radius: 10px; border: 3px solid <<if _tradeChance >= 50>>#51cf66<<elseif _tradeChance >= 30>>#ffc107<<else>>#ff6b6b<</if>>; 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: <<if _tradeChance >= 50>>#51cf66<<elseif _tradeChance >= 30>>#ffc107<<else>>#ff6b6b<</if>>;">_tradeChance%</div> </div> </div> <<if _playerValue < _adjustedNpcValue>> <div style="background: #1a1a1a; border: 3px solid #ff6b6b; padding: 15px; border-radius: 8px; margin-bottom: 20px; color: #ccc;"> <strong style="color: #ff6b6b;">⚠️ Insufficient Value!</strong> You need to offer at least <strong>_adjustedNpcValue</strong> value to attempt this trade. <<if _relLevel > 1>><span style="color: #51cf66;">(Relationship discount applied! Originally _npcValue)</span><</if>> You are offering <strong>_playerValue</strong>. </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 _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 _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> <!-- Display Current Offer --> <<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>> <!-- Names in offer --> <<if $playerTradePackage.name.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #9b59b6; font-size: 18px; display: block; margin-bottom: 10px;">👤 Name:</strong> <<for _name range $playerTradePackage.name>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #9b59b6;"> <<if _name.type === "firstName">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">First Name: _name.value</span> <<else>> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Last Name: _name.value</span> <</if>> <<capture _name>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>" >> <<run $playerTradePackage.name.delete(_name)>> <!-- Also remove matching name from NPC side --> <<for _npcName range $npcTradePackage.name>> <<if _npcName.type === _name.type>> <<run $npcTradePackage.name.delete(_npcName)>> <</if>> <</for>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Stats in offer --> <<if $playerTradePackage.stats.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #17a2b8; font-size: 18px; display: block; margin-bottom: 10px;">📊 Stats (3 points = 1 value):</strong> <<for _stat range $playerTradePackage.stats>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #17a2b8;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;">_stat.name: <span style="color: #ff6b6b;">-_stat.amount</span></span> <<capture _stat>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>" >> <<run $playerTradePackage.stats.delete(_stat)>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Physical traits in offer --> <<if $playerTradePackage.physical.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #51cf66; font-size: 18px; display: block; margin-bottom: 10px;">💪 Physical Traits:</strong> <<for _trait range $playerTradePackage.physical>> <<set _isAutoSwap = false>> <<set _swappedTrait = "">> <!-- Check if this trait has a matching swap in NPC package --> <<set _conflict = setup.getConflictingTrait(_trait, _npc.physicalTraits)>> <<if _conflict && $npcTradePackage.physical.includes(_conflict)>> <<set _isAutoSwap = true>> <<set _swappedTrait = _conflict>> <</if>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <<set _prefs = setup.getNPCPreferences(_npc)>> <<set _valueModifier = "">> <<if _prefs && _prefs.desires && _prefs.desires.physical && _prefs.desires.physical.includes(_trait)>> <<set _valueModifier = " 💚 Desired (-15%)">> <<elseif _prefs && _prefs.willingToTrade && _prefs.willingToTrade.physical && _prefs.willingToTrade.physical.includes(_trait)>> <<set _valueModifier = " ✓ Willing (-20%)">> <<elseif _prefs && _prefs.reluctantToTrade && _prefs.reluctantToTrade.physical && _prefs.reluctantToTrade.physical.includes(_trait)>> <<set _valueModifier = " ⚠️ Reluctant (+50%)">> <</if>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid <<if _isAutoSwap>>#ffc107<<else>>#51cf66<</if>>;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;"> _trait <span style="color: #667eea; font-size: 13px;">(Value: _traitValue<<print _valueModifier>>)</span> <<if _isAutoSwap>> <span style="color: #ffc107; font-size: 13px; margin-left: 8px;">↔️ _swappedTrait</span> <</if>> </span> <<capture _trait>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $playerTradePackage.physical.delete(_trait)>> <!-- Also remove matching exclusive trait from NPC side --> <<set _conflictToRemove = setup.getConflictingTrait(_trait, _npc.physicalTraits)>> <<if _conflictToRemove>> <<run $npcTradePackage.physical.delete(_conflictToRemove)>> <</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Mental traits in offer --> <<if $playerTradePackage.mental.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #9b59b6; font-size: 18px; display: block; margin-bottom: 10px;">🧠 Mental Traits:</strong> <<for _trait range $playerTradePackage.mental>> <<set _isAutoSwap = false>> <<set _swappedTrait = "">> <!-- Check if this trait has a matching swap in NPC package --> <<set _conflict = setup.getConflictingTrait(_trait, _npc.mentalTraits)>> <<if _conflict && $npcTradePackage.mental.includes(_conflict)>> <<set _isAutoSwap = true>> <<set _swappedTrait = _conflict>> <</if>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<set _prefs = setup.getNPCPreferences(_npc)>> <<set _valueModifier = "">> <<if _prefs && _prefs.desires && _prefs.desires.mental && _prefs.desires.mental.includes(_trait)>> <<set _valueModifier = " 💚 Desired (-15%)">> <<elseif _prefs && _prefs.willingToTrade && _prefs.willingToTrade.mental && _prefs.willingToTrade.mental.includes(_trait)>> <<set _valueModifier = " ✓ Willing (-20%)">> <<elseif _prefs && _prefs.reluctantToTrade && _prefs.reluctantToTrade.mental && _prefs.reluctantToTrade.mental.includes(_trait)>> <<set _valueModifier = " ⚠️ Reluctant (+50%)">> <</if>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid <<if _isAutoSwap>>#ffc107<<else>>#9b59b6<</if>>;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;"> _trait <span style="color: #667eea; font-size: 13px;">(Value: _traitValue<<print _valueModifier>>)</span> <<if _isAutoSwap>> <span style="color: #ffc107; font-size: 13px; margin-left: 8px;">↔️ _swappedTrait</span> <</if>> </span> <<capture _trait>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $playerTradePackage.mental.delete(_trait)>> <!-- Also remove matching exclusive trait from NPC side --> <<set _conflictToRemove = setup.getConflictingTrait(_trait, _npc.mentalTraits)>> <<if _conflictToRemove>> <<run $npcTradePackage.mental.delete(_conflictToRemove)>> <</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Skills in offer --> <<if $playerTradePackage.skills.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ffc107; font-size: 18px; display: block; margin-bottom: 10px;">🎯 Skills:</strong> <<for _skill range $playerTradePackage.skills>> <<set _skillValue = setup.getTraitValue("skill", _skill)>> <<set _prefs = setup.getNPCPreferences(_npc)>> <<set _valueModifier = "">> <<if _prefs && _prefs.desires && _prefs.desires.skills && _prefs.desires.skills.includes(_skill)>> <<set _valueModifier = " 💚 Desired (-15%)">> <<elseif _prefs && _prefs.willingToTrade && _prefs.willingToTrade.skills && _prefs.willingToTrade.skills.includes(_skill)>> <<set _valueModifier = " ✓ Willing (-20%)">> <<elseif _prefs && _prefs.reluctantToTrade && _prefs.reluctantToTrade.skills && _prefs.reluctantToTrade.skills.includes(_skill)>> <<set _valueModifier = " ⚠️ Reluctant (+50%)">> <</if>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #ffc107;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;">_skill <span style="color: #667eea; font-size: 13px;">(Value: _skillValue<<print _valueModifier>>)</span></span> <<capture _skill>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $playerTradePackage.skills.delete(_skill)>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Body parts in offer --> <<if $playerTradePackage.bodyParts.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ff6b6b; font-size: 18px; display: block; margin-bottom: 10px;">🫀 Body Parts:</strong> <<for _part range $playerTradePackage.bodyParts>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #ff6b6b;"> <<if _part.name === "chest">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Chest: $bodyParts.chest ↔️ _npc.bodyParts.chest</span> <<elseif _part.name === "butt">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Butt: $bodyParts.butt ↔️ _npc.bodyParts.butt</span> <<elseif _part.name === "gender">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Gender: $bodyParts.gender ↔️ _npc.bodyParts.gender</span> <<elseif _part.name === "skinTone">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Skin: $appearance.skinTone ↔️ _npc.appearance.skinTone</span> <<elseif _part.name === "hairColor">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Hair: $appearance.hairColor ↔️ _npc.appearance.hairColor</span> <<elseif _part.name === "age">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Age: <<print $appearance.age || "Adult">> ↔️ <<print _npc.appearance.age || "Adult">></span> <<elseif _part.name === "hairLength">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Hair Length: <<print $appearance.hairLength || "short">> ↔️ <<print _npc.appearance.hairLength || "short">></span> <</if>> <<capture _part>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <!-- Remove from both sides --> <<set _partName = _part.name>> <<run $playerTradePackage.bodyParts.delete(_part)>> <<for _npcPart range $npcTradePackage.bodyParts>> <<if _npcPart.name === _partName>> <<run $npcTradePackage.bodyParts.delete(_npcPart)>> <</if>> <</for>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Job in offer --> <<if $playerTradePackage.job>> <div style="margin-bottom: 20px;"> <strong style="color: #17a2b8; font-size: 18px; display: block; margin-bottom: 10px;">💼 Job:</strong> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #17a2b8;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;">$playerTradePackage.job</span> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<set $playerTradePackage.job = null>> <<goto "TradeInterface">> <</link>> </div> </div> <</if>> <</if>> <!-- Add Items Button --> <<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> <!-- Display Current Request --> <<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>> <!-- Names in request --> <<if $npcTradePackage.name.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #9b59b6; font-size: 18px; display: block; margin-bottom: 10px;">👤 Name (Auto Selected):</strong> <<for _name range $npcTradePackage.name>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #51cf66; opacity: 0.9;"> <<if _name.type === "firstName">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">First Name: _name.value</span> <<else>> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Last Name: _name.value</span> <</if>> <span style="color: #51cf66; font-size: 13px; margin-left: 10px;">✓ Auto</span> </div> <</for>> </div> <</if>> <!-- Stats in request --> <<if $npcTradePackage.stats.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #17a2b8; font-size: 18px; display: block; margin-bottom: 10px;">📊 Stats (1 point = 1 value):</strong> <<for _stat range $npcTradePackage.stats>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #17a2b8;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;">_stat.name: <span style="color: #51cf66;">+_stat.amount</span></span> <<capture _stat>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $npcTradePackage.stats.delete(_stat)>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Physical traits in request --> <<if $npcTradePackage.physical.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #51cf66; font-size: 18px; display: block; margin-bottom: 10px;">💪 Physical Traits:</strong> <<for _trait range $npcTradePackage.physical>> <<set _isAutoSwap = false>> <<set _swappedTrait = "">> <!-- Check if this trait has a matching swap in player package --> <<set _conflict = setup.getConflictingTrait(_trait, $physicalTraits)>> <<if _conflict && $playerTradePackage.physical.includes(_conflict)>> <<set _isAutoSwap = true>> <<set _swappedTrait = _conflict>> <</if>> <<set _traitValue = setup.getTraitValue("physical", _trait)>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid <<if _isAutoSwap>>#ffc107<<else>>#51cf66<</if>>;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;"> _trait <span style="color: #667eea; font-size: 13px;">(Value: _traitValue)</span> <<if _isAutoSwap>> <span style="color: #ffc107; font-size: 13px; margin-left: 8px;">↔️ _swappedTrait</span> <</if>> </span> <<capture _trait>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $npcTradePackage.physical.delete(_trait)>> <!-- Also remove matching exclusive trait from player side --> <<set _conflictToRemove = setup.getConflictingTrait(_trait, $physicalTraits)>> <<if _conflictToRemove>> <<run $playerTradePackage.physical.delete(_conflictToRemove)>> <</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Mental traits in request --> <<if $npcTradePackage.mental.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #9b59b6; font-size: 18px; display: block; margin-bottom: 10px;">🧠 Mental Traits:</strong> <<for _trait range $npcTradePackage.mental>> <<set _isAutoSwap = false>> <<set _swappedTrait = "">> <!-- Check if this trait has a matching swap in player package --> <<set _conflict = setup.getConflictingTrait(_trait, $mentalTraits)>> <<if _conflict && $playerTradePackage.mental.includes(_conflict)>> <<set _isAutoSwap = true>> <<set _swappedTrait = _conflict>> <</if>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid <<if _isAutoSwap>>#ffc107<<else>>#9b59b6<</if>>;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;"> _trait <span style="color: #667eea; font-size: 13px;">(Value: _traitValue)</span> <<if _isAutoSwap>> <span style="color: #ffc107; font-size: 13px; margin-left: 8px;">↔️ _swappedTrait</span> <</if>> </span> <<capture _trait>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $npcTradePackage.mental.delete(_trait)>> <!-- Also remove matching exclusive trait from player side --> <<set _conflictToRemove = setup.getConflictingTrait(_trait, $mentalTraits)>> <<if _conflictToRemove>> <<run $playerTradePackage.mental.delete(_conflictToRemove)>> <</if>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Skills in request --> <<if $npcTradePackage.skills.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ffc107; font-size: 18px; display: block; margin-bottom: 10px;">🎯 Skills:</strong> <<for _skill range $npcTradePackage.skills>> <<set _skillValue = setup.getTraitValue("skill", _skill)>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #ffc107;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;">_skill <span style="color: #667eea; font-size: 13px;">(Value: _skillValue)</span></span> <<capture _skill>> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<run $npcTradePackage.skills.delete(_skill)>> <<goto "TradeInterface">> <</link>> <</capture>> </div> <</for>> </div> <</if>> <!-- Body parts in request (Auto-Selected) --> <<if $npcTradePackage.bodyParts.length > 0>> <div style="margin-bottom: 20px;"> <strong style="color: #ff6b6b; font-size: 18px; display: block; margin-bottom: 10px;">🫀 Body Parts (Auto Selected):</strong> <<for _part range $npcTradePackage.bodyParts>> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; border: 2px solid #51cf66; opacity: 0.9;"> <<set _npc = $tradingWithNPC>> <<if _part.name === "chest">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Chest (Swap)</span> <<elseif _part.name === "butt">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Butt (Swap)</span> <<elseif _part.name === "gender">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Gender (Swap)</span> <<elseif _part.name === "skinTone">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Skin Color (Swap)</span> <<elseif _part.name === "hairColor">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Hair Color (Swap)</span> <<elseif _part.name === "age">> <span style="color: #ccc; font-size: 16px; font-weight: 500;">Age (Swap)</span> <</if>> <span style="color: #51cf66; font-size: 13px; margin-left: 10px;">✓ Auto</span> </div> <</for>> </div> <</if>> <!-- Job in request --> <<if $npcTradePackage.job>> <div style="margin-bottom: 20px;"> <strong style="color: #17a2b8; font-size: 18px; display: block; margin-bottom: 10px;">💼 Job:</strong> <div style="background: #1a1a1a; padding: 12px; margin: 8px 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; border: 2px solid #17a2b8;"> <span style="color: #ccc; font-size: 16px; font-weight: 500;">$npcTradePackage.job</span> <<link "<span style='color: #ff6b6b; font-size: 20px; font-weight: bold;'>❌</span>">> <<set $npcTradePackage.job = null>> <<goto "TradeInterface">> <</link>> </div> </div> <</if>> <</if>> <!-- Add Items Button --> <<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>> <<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)>> <<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: [] }>> <<set $npcTradePackage = { stats: [], physical: [], mental: [], skills: [], bodyParts: [], job: null, name: [] }>> <<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>> <</nobr>>Welcome to the Sunfish City! A trait swapping game I made for the fun of it. Disclaimer: not all jobs have functionality yet. Before you begin I must ask, are you 18 years old or older? [[Yes|CharacterCreation]] [[No|Exit]] <<set $cheatMenuUnlocked = false>> <<nobr>> <<set _npc = $tradingWithNPC>> <<set _isPlayerSide = ($tradeSide === "player")>> <<set _npcPrefs = setup.getNPCPreferences(_npc)>> <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> <!-- NAME SECTION (Available on both sides) --> <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> <!-- Check if NPC will never trade name --> <<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>> <!-- Check if names are already selected --> <<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;"> <!-- First Name --> <<set _nameValue = setup.getTraitValue("name", "firstName")>> <<set _npcFirstName = _npc.name.split(" ")[0]>> <<set _nameBlocked = _npcPrefs && _npcPrefs.neverTrade && _npcPrefs.neverTrade.name>> <<if !_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>> <!-- Last Name --> <<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> <!-- BODY PARTS SECTION (Available on both sides) --> <<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>> <<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 (-25%)<</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>> <<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 (-25%)<</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")>> <<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;'>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 (-25%)<</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")>> <<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;'>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 (-25%)<</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")>> <<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 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 (-25%)<</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")>> <<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;'>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 (-25%)<</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">> <!-- Ensure NPC has hair length --> <<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 (-25%)<</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>> </div> </div> <!-- 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>> <!-- Filter out hair length traits from display --> <<set _displayPhysicalTraits = _availablePhysical.filter(function(trait) { return trait !== "Short Hair" && trait !== "Long Hair"; })>> <<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)>> /* Check NPC preferences */ <<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 opposite has a conflicting exclusive trait */ <<set _oppositeConflict = setup.getConflictingTrait(_trait, _oppositeTraits)>> <<set _packageConflict = setup.getConflictingTrait(_trait, _currentPackage.physical)>> <<if _isPlayerSide>> /* Player is OFFERING this trait - only check if NPC won't accept it */ <<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 (-50%)" : (_actuallyBlocked ? "Won't accept" : "")))>> <<else>> /* Player is REQUESTING this trait from NPC */ <<set _actuallyBlocked = _npcBlocked>> <<set _blockedMessage = "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 (-50%)" : (_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 opposite has conflicting trait, auto-add to opposite package */ <<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 opposite has conflicting trait, auto-add to opposite package */ <<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>> <!-- Add character creation trait to player's available mental traits for trading --> <<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>> <<capture _trait>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<set _alreadyInPackage = _currentPackage.mental.includes(_trait)>> <<set _oppositeHasTrait = _oppositeTraitsMental.includes(_trait)>> /* Check NPC preferences */ <<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 opposite has a conflicting exclusive trait */ <<set _oppositeConflict = setup.getConflictingTrait(_trait, _oppositeTraitsMental)>> <<set _packageConflict = setup.getConflictingTrait(_trait, _currentPackage.mental)>> <<if _isPlayerSide>> /* Player is OFFERING this trait - only check if NPC won't accept it */ <<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 (-15%)" : (_actuallyBlocked ? "Won't accept" : "")))>> <<else>> /* Player is REQUESTING this trait from NPC */ <<set _actuallyBlocked = _npcBlocked>> <<set _blockedMessage = "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 (-15%)" : (_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 opposite has conflicting trait, auto-add to opposite package */ <<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 opposite has conflicting trait, auto-add to opposite package */ <<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)>> /* Check NPC preferences */ <<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)>> <<if _isPlayerSide>> /* Player is OFFERING this skill - only check if NPC won't accept it */ <<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 (-20%)" : (_actuallyBlocked ? "Won't accept" : "")))>> <<else>> /* Player is REQUESTING this skill from NPC */ <<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 (-20%)" : (_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>> <!-- JOB SECTION --> <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 !_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> <!-- 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;"> <<if $tradeResult.success>> <!-- 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> <!-- 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 <</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 <</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>> </div> <!-- Physical Transformation Descriptions --> <<if $tradeResult.playerReceived.bodyParts && $tradeResult.playerReceived.bodyParts.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-top: 0; font-size: 24px; border-bottom: 3px solid #ff6b6b; padding-bottom: 10px;">🔄 Physical Changes</h2> <<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;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getChestTransformationText(_oldSize, _newSize)>> </p> </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;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getButtTransformationText(_oldSize, _newSize)>> </p> </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 #ff6b6b;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print setup.getGenderTransformationText(_oldGender, _newGender)>> </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 === "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;"> You watch as your hair shifts from <<print _oldColor.toLowerCase()>> to <<print _newColor.toLowerCase()>>, the color bleeding through strand by strand until the transformation is complete. </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;"> A tingling sensation spreads across your entire body as your skin tone shifts from <<print _oldTone.toLowerCase()>> to <<print _newTone.toLowerCase()>>, the change rippling outward from your core. </p> </div> <</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 #ff6b6b;"> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<if _newAge === "Mature Adult" && _oldAge === "Adult">> Your face feels different - more lined, more experienced. You can feel yourself aging, your features taking on a more mature quality. <<elseif _newAge === "Adult" && _oldAge === "Mature Adult">> Your skin feels tighter, smoother. Years seem to peel away as you grow younger, your features becoming more youthful. <</if>> </p> </div> <</if>> <</for>> </div> <</if>> <!-- Relationship Change from Trade --> <<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 $tradeResult.relationshipChange>> points) </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>> <!-- 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 / 5 </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>> <<set $relationships = {}>> <<set $dayCount = $dayNumber>> <<if !$imageSettings>> <<set $imageSettings = { imagesEnabled: true, customImages: { face: "", chest: "", butt: "" } }>> <</if>> /* ---------------------------------- */ /* --- TRAIT BONUSES SYSTEM (MUST BE FIRST) --- */ /* ---------------------------------- */ <<set setup.traitBonuses = { // Character Creation Traits "Quick Learner": {}, "Swift": { dexterity: 5 }, "Silver-Tongued": { charisma: 5 }, "Pensive": { intelligence: 5 }, "Jock": { strength: 5 }, "Naturally Gifted": { charisma: 2, dexterity: 2, strength: 2, intelligence: 2 }, // Physical Traits - POSITIVE "Tall": {}, "Curvy": {charisma: 5}, "Lean": {dexterity: 4, strength: 2}, "Muscular": {strength: 8}, "Soft": {charisma: 3}, "Sharp Features": {charisma: 4}, "Smooth Skin": {charisma: 3}, "Pierced": {charisma: 2}, "Youthful": {charisma: 3, dexterity: 2}, "Mature": {intelligence: 4, charisma: 2}, "Tan Skin": {}, "Dark Skin": {}, "Pale Skin": {}, "Attractive": {charisma: 8}, "Fit": {strength: 5, dexterity: 4}, "Graceful": {dexterity: 6, charisma: 3}, "Strong": {strength: 7}, "Flexible": {dexterity: 6}, "Freckled": {charisma: 2}, "Tattooed": {charisma: 3}, "Athletic Build": {strength: 5, dexterity: 5}, "Short Hair": {}, "Long Hair": {}, "Petite": {dexterity: 4}, "Voluptuous": {charisma: 6}, "Broad-shouldered": {strength: 4}, "Quick": {dexterity: 5}, "Sturdy": {strength: 4}, "High Energy": {dexterity: 3, charisma: 4}, "Deep Thinker": {intelligence: 4}, "Monotone Expression": {intelligence: 1}, "Sarcastic": {charisma: 2, intelligence: 1}, "Artistic": {intelligence: 2, dexterity: 2}, "Relaxed": {charisma: 2}, "Humorous": {charisma: 2}, "Perceptive": {intelligence: 3, charisma: 1}, "Detail-Oriented": {intelligence: 3, dexterity: 2}, "Customer-Focused": {charisma: 3, intelligence: 1}, "Punctual": {intelligence: 1, charisma: 1}, "Totally not a Vampire": {strength: 50, charisma: 50, dexterity: 50}, "Were-Creature": {strength: 60, dexterity: 60}, // Physical Traits - MIXED "Short": {}, "Scarred": {strength: 2, charisma: -3}, // Physical Traits - NEGATIVE "Plain": {charisma: -3}, "Ugly": {charisma: -8}, "Overweight": {strength: -4, dexterity: -4, charisma: -3}, "Underweight": {strength: -5, charisma: -2}, "Clumsy": {dexterity: -6}, "Weak": {strength: -7}, "Stiff": {dexterity: -5}, "Blemished": {charisma: -4}, // Voice Traits - POSITIVE "Smooth Voice": {charisma: 4}, "Soft-Spoken": {charisma: 2}, "Warm Tone": {charisma: 5}, "Gentle Voice": {charisma: 3}, "Soothing Tone": {charisma: 4}, "Silky Voice": {charisma: 5}, "Clear Enunciation": {charisma: 3, intelligence: 2}, "Articulate Speech": {charisma: 4, intelligence: 3}, "Smooth Talker": {charisma: 6}, "Friendly Tone": {charisma: 4}, "Charismatic Voice": {charisma: 7}, "Steady Voice": {charisma: 3}, "Pleasant Cadence": {charisma: 4}, "Calm Voice": {charisma: 3}, "Expressive Voice": {charisma: 5}, "Animated Tone": {charisma: 4}, "Lively Tone": {charisma: 4}, "Charming Tone": {charisma: 5}, "Hushed Intimate Voice": {charisma: 4}, "Balanced Neutral Tone": {}, "Sing-Songy Voice": {charisma: 3}, "Eager Tone": {charisma: 3}, "Bouncy Tone": {charisma: 3}, "Melodic Voice": {charisma: 5}, "Clear Pronunciation": {charisma: 3, intelligence: 2}, "Even-Paced Voice": {charisma: 2}, "Understated Voice": {charisma: 1}, "Soft Monologue Style": {charisma: 2}, // Voice Traits - MIXED "Fast Talker": {dexterity: 2, charisma: -1}, "Rapid-Fire Speech": {dexterity: 3, charisma: -2}, "Deep Voice": {charisma: 2}, "High-Pitched Tone": {charisma: -1}, "Raspy Voice": {}, "Gravelly Voice": {charisma: 1}, "Croaky Voice": {charisma: -2}, "Breathy Voice": {charisma: 2}, "Nasally Tone": {charisma: -3}, "Stoic Tone": {intelligence: 2, charisma: -1}, "Measured Speech": {intelligence: 3}, "Choppy Speech": {charisma: -2}, "Interruptive Tone": {charisma: -3}, "Sharp Voice": {charisma: -1}, "Snappy Tone": {charisma: -2}, "Flat Voice": {charisma: -2}, "Monotone": {charisma: -3}, "Deadpan Delivery": {intelligence: 2, charisma: -2}, "Detached Voice": {charisma: -3}, "Emotionless Tone": {charisma: -4}, "Slow Calm Voice": {charisma: 2}, "Lazy Drawl": {charisma: -2}, "Mumbly Voice": {charisma: -4}, "Stuttering Speech": {charisma: -3}, "Grim Tone": {charisma: -2}, "Robotic Tone": {intelligence: 2, charisma: -3}, "Shaky Voice": {charisma: -3}, // Additional Mental Traits - POSITIVE "Nonchalant": {charisma: 2}, "Charming": {charisma: 6}, "Diplomatic": {charisma: 5, intelligence: 3}, "Organized": {intelligence: 4}, "Resourceful": {intelligence: 5, dexterity: 2}, "Focused": {intelligence: 4}, "Disciplined": {strength: 3, intelligence: 3}, "Determined": {strength: 4, intelligence: 2}, "Steadfast": {strength: 3, intelligence: 2}, "Considerate": {charisma: 5}, "Polite": {charisma: 4}, "Funny": {charisma: 5}, "Reassuring": {charisma: 4}, "Loyal": {charisma: 4}, "Talkative": {charisma: 3}, "Direct": {charisma: 2, intelligence: 1}, "Efficient": {intelligence: 4, dexterity: 2}, "Negotiator": {charisma: 6, intelligence: 3}, "Crafty": {intelligence: 4, dexterity: 3}, "Workaholic": {intelligence: 3, strength: 2}, "High Stamina": {strength: 6, dexterity: 3}, "Flirty": {charisma: 5}, "Seductive": {charisma: 6}, "Alluring": {charisma: 7}, "Warm": {charisma: 5}, "Bookworm": {intelligence: 6}, "Lucky": {charisma: 3, dexterity: 3}, // Stereotype Traits "Nerd": {intelligence: 6, charisma: -2}, "Geek": {intelligence: 5, charisma: -1}, "Jock": {strength: 5, dexterity: 4, intelligence: -2}, "Prep": {charisma: 5, intelligence: 2}, "Tomboy": {strength: 3, dexterity: 3, charisma: -2}, "Femboy": {charisma: 4, dexterity: 3}, "Diva": {charisma: 6, intelligence: -3}, "Goth": {charisma: 2, intelligence: 2}, // Additional Mental Traits - MIXED "Blunt": {charisma: -2, intelligence: 2}, "Perfectionist": {intelligence: 4, charisma: -2}, "Overthinker": {intelligence: 3, charisma: -3}, "Moody": {charisma: -3}, "Unpredictable": {charisma: -2}, "Risk Taker": {strength: 3, intelligence: -2}, "Impulsive": {dexterity: 3, intelligence: -3}, "Cynical": {intelligence: 2, charisma: -3}, "Quiet": {charisma: -2, intelligence: 2}, "Awkward": {charisma: -4}, "Tone Deaf": {charisma: -3}, "Tease": {charisma: 2}, "Clingy": {charisma: -3}, "Sensitive": {charisma: -2, intelligence: 2}, "Corporate Drone": {intelligence: 2, charisma: -2}, // Additional Mental Traits - NEGATIVE "Forgetful": {intelligence: -5}, "Disorganized": {intelligence: -4, dexterity: -2}, "Selfish": {charisma: -6}, "Deceitful": {charisma: -5, intelligence: -2}, "Erratic": {charisma: -4, intelligence: -3}, "Obsessive": {intelligence: -3, charisma: -4}, "Insecure": {charisma: -5}, "Short Tempered": {charisma: -5, intelligence: -2}, "Rude": {charisma: -6}, "Unreliable": {charisma: -5, intelligence: -3}, "Slow Learner": {intelligence: -6}, "Reckless": {intelligence: -4, strength: -3}, "Cold": {charisma: -5}, "Insensitive": {charisma: -5}, "Unskilled": {dexterity: -5, intelligence: -3}, "Unlucky": {charisma: -3, dexterity: -3}, "Cowardly": {strength: -5, charisma: -4}, // Additional Physical Traits "Fashionable": {charisma: 5}, "Quick Reflexes": {dexterity: 6}, "Tech Savvy": {intelligence: 5, dexterity: 2}, "Fast": {dexterity: 6}, "Slow": {dexterity: -5, strength: -2}, // Mental Traits - POSITIVE "Extroverted": {charisma: 5}, "Kind": {charisma: 6}, "Sly": {intelligence: 4, charisma: 2}, "Dominant": {charisma: 4, strength: 3}, "Confident": {charisma: 6}, "Optimistic": {charisma: 4}, "Empathetic": {charisma: 5, intelligence: 2}, "Supportive": {charisma: 5}, "Friendly": {charisma: 6}, "Competitive": {strength: 3, intelligence: 2}, "Logical": {intelligence: 6}, "Shrewd": {intelligence: 5, charisma: 2}, "Hardworking": {strength: 3, intelligence: 3}, "Humble": {charisma: 4}, "Trusting": {charisma: 3}, "Ambitious": {intelligence: 4, charisma: 3}, "Creative": {intelligence: 5}, "Brave": {strength: 4, charisma: 3}, "Patient": {intelligence: 3, charisma: 2}, "Wise": {intelligence: 7}, "Intelligent": {intelligence: 5}, "Analytical": {intelligence: 5}, "Outgoing": {charisma: 4}, "Curious": {intelligence: 3}, "Witty": {charisma: 3, intelligence: 2}, "Calm": {intelligence: 2, charisma: 2}, "Energetic": {dexterity: 2, charisma: 2}, "Thoughtful": {intelligence: 3}, "Chill": {charisma: 3, intelligence: 2}, // Mental Traits - MIXED "Introverted": {intelligence: 3, charisma: -3}, "Honest": {charisma: 3, intelligence: -2}, "Submissive": {charisma: -3, dexterity: 2}, "Shy": {charisma: -5, intelligence: 2}, "Aggressive": {strength: 5, charisma: -2}, "Passive": {charisma: -2, intelligence: 3}, "Pessimistic": {intelligence: 3, charisma: -3}, "Stubborn": {strength: 4, intelligence: -2}, "Paranoid": {intelligence: 2, charisma: -4}, // Mental Traits - PURELY NEGATIVE "Bitchy": {charisma: -5, intelligence: -2}, "Cruel": {charisma: -8, intelligence: -2}, "Jealous": {charisma: -5, intelligence: -2}, "Lazy": {strength: -5, intelligence: -4}, "Arrogant": {charisma: -6, intelligence: -2}, "Complacent": {intelligence: -4, strength: -3}, "Dull": {intelligence: -6, charisma: -3}, "Cowardly": {strength: -5, charisma: -4}, "Immature": {intelligence: -4, charisma: -3}, "Impatient": {intelligence: -3, charisma: -4}, "Foolish": {intelligence: -7, charisma: -2} }>> <<set setup.skillBonuses = { "Math Skills": {intelligence: 5}, "Coding": {intelligence: 6}, "Dancing": {dexterity: 5, charisma: 3}, "Plumbing": {strength: 3, intelligence: 2}, "High Heels Proficient": {dexterity: 4, charisma: 2}, "Swimmer": {strength: 4, dexterity: 3}, "Swimming": {strength: 4, dexterity: 3}, "Sexually Skilled": {charisma: 5, dexterity: 2}, "Modeling": {charisma: 6}, "Makeup": {dexterity: 3, charisma: 3}, "Cooking": {intelligence: 3, dexterity: 2}, "Photography": {intelligence: 3, charisma: 2}, "Maid": {dexterity: 4}, "Singing": {charisma: 5}, "Serving": {charisma: 4, dexterity: 2}, "Hair Styling": {dexterity: 5, charisma: 2}, "Cleaning": {dexterity: 3}, "Combat": {strength: 6, dexterity: 3}, "Persuasion": {charisma: 7}, "Medicine": {intelligence: 7}, "Trading": {charisma: 4, intelligence: 3}, "Stealth": {dexterity: 6}, "Driving": {dexterity: 4}, "Lock Picking": {dexterity: 6, intelligence: 2}, "First Aid": {intelligence: 4}, "Gardening": {intelligence: 2, strength: 2}, "Construction": {strength: 5, intelligence: 2}, "Heavy Lifting": {strength: 7}, "Social Media": {charisma: 5, intelligence: 2}, "Baking": {dexterity: 4, intelligence: 2}, "Public Speaking": {charisma: 6, intelligence: 2}, "Writing": {intelligence: 5}, "Art": {dexterity: 4, intelligence: 3}, "Painting": {dexterity: 4, intelligence: 3}, "Music": {dexterity: 3, charisma: 4}, "Guitar": {dexterity: 4, charisma: 2}, "Piano": {dexterity: 5, intelligence: 2}, "Acting": {charisma: 6, intelligence: 2}, "Teaching": {intelligence: 5, charisma: 3}, "Sales": {charisma: 6, intelligence: 2}, "Management": {intelligence: 5, charisma: 4}, "Accounting": {intelligence: 6}, "Legal Knowledge": {intelligence: 7}, "Languages": {intelligence: 5}, "Foreign Language": {intelligence: 5}, "Martial Arts": {strength: 5, dexterity: 5}, "Athletics": {strength: 5, dexterity: 4}, "Yoga": {dexterity: 5, intelligence: 2}, "Retail": {charisma: 3, intelligence: 2}, "Tech-Savvy": {intelligence: 3, dexterity: 1}, "Troubleshooting": {intelligence: 3, dexterity: 2}, "Forklift Certified": {dexterity: 3, strength: 2}, "Product Knowledge": {intelligence: 2, charisma: 1}, "Inventory Management": {intelligence: 3, dexterity: 1}, "Customer Service": {charisma: 3, intelligence: 1}, "Occult Expert": {intelligence: 30}, "BtestBraitBeesBigBeenore": {charisma: 90, dexterity: 90, strength: 90, intelligence: 90}, "Sunfish": {charisma: 50, dexterity: 50, strength: 50, intelligence: 50} }>> /* Function to calculate total stat bonuses from traits and skills */ <<set setup.calculateStatBonuses = function() { var v = State.variables; var bonuses = { charisma: 0, dexterity: 0, strength: 0, intelligence: 0 }; // Add bonuses from physical traits if (v.physicalTraits) { v.physicalTraits.forEach(function(trait) { var traitBonus = setup.traitBonuses[trait]; if (traitBonus) { for (var stat in traitBonus) { bonuses[stat] += traitBonus[stat]; } } }); } // Add bonuses from mental traits if (v.mentalTraits) { v.mentalTraits.forEach(function(trait) { var traitBonus = setup.traitBonuses[trait]; if (traitBonus) { for (var stat in traitBonus) { bonuses[stat] += traitBonus[stat]; } } }); } // Add bonuses from character creation trait if (v.characterCreationTrait && setup.traitBonuses[v.characterCreationTrait]) { var traitBonus = setup.traitBonuses[v.characterCreationTrait]; for (var stat in traitBonus) { bonuses[stat] += traitBonus[stat]; } } // Add bonuses from skills if (v.skills) { v.skills.forEach(function(skill) { var skillBonus = setup.skillBonuses[skill]; if (skillBonus) { for (var stat in skillBonus) { bonuses[stat] += skillBonus[stat]; } } }); } return bonuses; }>> /* Function to get total stat (base + bonuses) */ <<set setup.getTotalStat = function(statName) { var v = State.variables; var bonuses = setup.calculateStatBonuses(); var total = v.stats[statName] + bonuses[statName]; // Cap at max if (total > v.statMaxCaps[statName]) { total = v.statMaxCaps[statName]; } return total; }>> /* 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 "height": ["Tall", "Short"], // Hair length traits "hairLength": ["Short Hair", "Long Hair"], // Body type traits with chest/butt requirements "bodyType": ["Curvy", "Voluptuous", "Petite", "Slim", "Muscular", "Stocky", "Lean"], // Voice traits - only one voice trait allowed "voice": ["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", "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"], // 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"], "maturity": ["Mature", "Immature"], "patience": ["Patient", "Impatient"], "wisdom": ["Wise", "Foolish"], "work": ["Hardworking", "Lazy"], "aggression": ["Aggressive", "Passive"], "attraction": ["Attractive", "Ugly"], "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"], "impulsiveness": ["Disciplined", "Impulsive", "Reckless"], "stability": ["Steadfast", "Erratic", "Unpredictable"], "security": ["Confident", "Insecure"], "stereotypes": ["Nerd", "Geek", "Jock", "Prep", "Tomboy", "Femboy", "Diva", "Goth"] }>> <<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"]>> <<set setup.buttSizeOrder = ["flat", "small", "medium", "large", "huge", "giant"]>> /* Check if a trait is exclusive with any existing traits */ <<set setup.getConflictingTrait = function(newTrait, 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 group for (var i = 0; i < existingTraits.length; i++) { if (group.includes(existingTraits[i]) && existingTraits[i] !== newTrait) { return existingTraits[i]; } } } } 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; }>> /* ---------------------------------- */ /* --- JOB STAT REQUIREMENTS (NO LONGER USED FOR TRADING) --- */ /* ---------------------------------- */ <<set setup.jobRequirements = { "Unemployed": {}, "Street Performer": {charisma: 10}, "Package Courier": {dexterity: 10}, "Construction Worker": {strength: 15}, "Dock Worker": {strength: 15}, "Security Guard": {strength: 15}, "Baker": {dexterity: 10}, "Maid": {dexterity: 10}, "Hooker": {charisma: 30}, "Stripper": {charisma: 35}, "Prostitute": {charisma: 30}, "Fitness Shop Clerk": {strength: 25}, "Ecentric Shop Worker": {charisma: 20}, "Tech Store Clerk": {intelligence: 20}, "Adult Store Clerk": {charisma: 20}, "Beauty Salon Stylist": {dexterity: 30}, "Brothel Worker": {charisma: 35}, "Model": {charisma: 35}, "Bouncer": {strength: 40}, "Clinic Assistant": {intelligence: 40}, "Data Analyst": {intelligence: 50}, "Negotiator": {charisma: 50}, "Enforcer": {strength: 50}, "Porn Star": {charisma: 50}, "Social Media Influencer": {charisma: 45}, "Black Market Dealer": {charisma: 45}, "Police Officer": {strength: 45}, "Brothel Owner": {charisma: 70}, "Mayor's Secretary": {intelligence: 65}, "City Mayor": {charisma: 80, intelligence: 60}, "Fitness Trainer": {strength: 70}, "Barista": {charisma: 10, dexterity: 10}, "Dancing Instructor": {strength: 45, dexterity: 50}, "Bus Driver": {strength: 15, dexterity: 20}, "Cocktail Waitress": {charisma: 35, dexterity: 20}, "Mysterious Book Shop owner": {charisma: 100, intelligence: 50} }>> <<set setup.meetsJobRequirements = function(stats, jobName) { var requirements = setup.jobRequirements[jobName]; if (!requirements) return true; for (var stat in requirements) { if (stats[stat] < requirements[stat]) { return false; } } return true; }>> <<set setup.canTradeJob = function(playerJob, npcJob) { // Jobs can always be traded regardless of stats return true; }>> /* ---------------------------------- */ /* --- TRAIT VALUE FUNCTION --- */ /* ---------------------------------- */ <<set setup.getTraitValue = function(type, name, size) { // Special test trait - DON'T CHANGE if (name === "BtestBraitBeesBigBeenore") { return 999; } // Were-Creature - DON'T CHANGE if (name === "Were-Creature") { return 450; } // Special handling for jobs - value = total stat requirements if (type === "job") { if (name === "Unemployed") { return -5; } 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 }; return sizeValues[size.toLowerCase()] || 12; } // 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 = { // Character Creation Traits "Quick Learner": 30, "Swift": 30, "Silver-Tongued": 30, "Pensive": 30, "Jock": 30, "Naturally Gifted": 30, // Physical Traits - POSITIVE "Tall": 35, "Curvy": 70, "Lean": 45, "Muscular": 95, "Soft": 30, "Sharp Features": 35, "Smooth Skin": 50, "Pierced": 15, "Youthful": 69, "Mature": 35, "Tan Skin": 10, "Dark Skin": 10, "Pale Skin": 10, "Attractive": 70, "Fit": 70, "Graceful": 55, "Strong": 55, "Flexible": 50, "Freckled": 20, "Tattooed": 15, "Athletic Build": 70, "Short Hair": 5, "Long Hair": 10, "Petite": 30, "Voluptuous": 105, "Broad-shouldered": 35, "Quick": 55, "Sturdy": 25, "High Energy": 35, "Deep Thinker": 50, "Monotone Expression": 10, "Sarcastic": 15, "Artistic": 36, "Relaxed": 25, "Humorous": 20, "Perceptive": 40, "Detail-Oriented": 35, "Customer-Focused": 40, "Punctual": 20, // Physical Traits - MIXED "Short": 10, "Scarred": 5, // Physical Traits - NEGATIVE "Plain": -15, "Ugly": -40, "Overweight": -30, "Underweight": -28, "Clumsy": -30, "Weak": -35, "Stiff": -25, "Blemished": -20, // Voice Traits - POSITIVE "Smooth Voice": 39, "Soft-Spoken": 18, "Warm Tone": 28, "Gentle Voice": 20, "Soothing Tone": 25, "Silky Voice": 50, "Clear Enunciation": 28, "Articulate Speech": 32, "Smooth Talker": 35, "Friendly Tone": 25, "Charismatic Voice": 38, "Steady Voice": 20, "Pleasant Cadence": 25, "Calm Voice": 20, "Expressive Voice": 28, "Animated Tone": 25, "Lively Tone": 25, "Charming Tone": 28, "Hushed Intimate Voice": 25, "Balanced Neutral Tone": 10, "Sing-Songy Voice": 20, "Eager Tone": 20, "Bouncy Tone": 20, "Melodic Voice": 28, "Clear Pronunciation": 28, "Even-Paced Voice": 18, "Understated Voice": 12, "Soft Monologue Style": 18, // Voice Traits - MIXED "Fast Talker": 8, "Rapid-Fire Speech": 10, "Deep Voice": 15, "High-Pitched Tone": 5, "Raspy Voice": 10, "Gravelly Voice": 12, "Croaky Voice": 5, "Breathy Voice": 15, "Nasally Tone": -8, "Stoic Tone": 8, "Measured Speech": 18, "Choppy Speech": -5, "Interruptive Tone": -8, "Sharp Voice": 5, "Snappy Tone": -5, "Flat Voice": -5, "Monotone": -8, "Deadpan Delivery": 5, "Detached Voice": -8, "Emotionless Tone": -10, "Slow Calm Voice": 15, "Lazy Drawl": -5, "Mumbly Voice": -10, "Stuttering Speech": -8, "Grim Tone": -5, "Robotic Tone": -5, "Shaky Voice": -8, // Mental Traits - POSITIVE "Nonchalant": 18, "Charming": 45, "Diplomatic": 45, "Organized": 25, "Resourceful": 32, "Focused": 25, "Disciplined": 32, "Determined": 60, "Steadfast": 28, "Considerate": 28, "Polite": 25, "Funny": 28, "Reassuring": 25, "Loyal": 30, "Talkative": 20, "Direct": 10, "Efficient": 60, "Negotiator": 40, "Crafty": 30, "Workaholic": 30, "High Stamina": 90, "Flirty": 30, "Seductive": 95, "Alluring": 90, "Warm": 30, "Bookworm": 30, "Lucky": 100, // Stereotype Traits "Nerd": 25, "Geek": 23, "Prep": 32, "Tomboy": 22, "Femboy": 32, "Diva": 20, "Goth": 35, // Mental Traits - MIXED "Blunt": 10, "Perfectionist": 15, "Overthinker": 8, "Moody": -8, "Unpredictable": -5, "Risk Taker": 8, "Impulsive": 5, "Cynical": -5, "Quiet": 5, "Awkward": -10, "Tone Deaf": -8, "Tease": 15, "Clingy": -8, "Sensitive": 5, "Corporate Drone": 5, // Mental Traits - NEGATIVE "Forgetful": -25, "Disorganized": -22, "Selfish": -30, "Deceitful": -28, "Erratic": -28, "Obsessive": -28, "Insecure": -25, "Short Tempered": -28, "Rude": -30, "Unreliable": -32, "Slow Learner": -30, "Reckless": -28, "Cold": -25, "Insensitive": -25, "Unskilled": -32, "Unlucky": -28, "Cowardly": -38, "Bitchy": -30, "Cruel": -45, "Jealous": -28, "Lazy": -38, "Arrogant": -35, "Complacent": -30, "Dull": -38, "Immature": -28, "Impatient": -28, "Foolish": -40, // Additional Physical/Mental Positive Traits "Fashionable": 40, "Quick Reflexes": 35, "Tech Savvy": 32, "Fast": 35, "Slow": -28, // Additional Mental Traits - POSITIVE "Extroverted": 28, "Kind": 35, "Sly": 30, "Dominant": 32, "Confident": 35, "Optimistic": 25, "Empathetic": 32, "Supportive": 28, "Friendly": 35, "Competitive": 28, "Logical": 35, "Shrewd": 32, "Hardworking": 32, "Humble": 25, "Trusting": 20, "Ambitious": 32, "Creative": 28, "Brave": 32, "Patient": 28, "Wise": 40, "Intelligent": 28, "Analytical": 28, "Outgoing": 25, "Curious": 20, "Witty": 28, "Calm": 25, "Energetic": 25, "Thoughtful": 20, "Chill": 28, // Mental Traits - MIXED "Introverted": 8, "Honest": 12, "Submissive": 8, "Shy": -10, "Aggressive": 18, "Passive": 5, "Pessimistic": 5, "Stubborn": 15, "Paranoid": -5, // Skills "Math Skills": 28, "Coding": 35, "Dancing": 38, "Plumbing": 28, "High Heels Proficient": 30, "Swimmer": 32, "Swimming": 32, "Sexually Skilled": 32, "Modeling": 35, "Makeup": 30, "Cooking": 28, "Photography": 28, "Maid": 25, "Singing": 28, "Serving": 30, "Hair Styling": 32, "Cleaning": 20, "Combat": 40, "Persuasion": 38, "Medicine": 42, "Trading": 32, "Stealth": 35, "Driving": 25, "Lock Picking": 38, "First Aid": 25, "Gardening": 22, "Construction": 32, "Heavy Lifting": 38, "Social Media": 32, "Baking": 30, "Public Speaking": 38, "Writing": 28, "Art": 32, "Painting": 32, "Music": 32, "Guitar": 30, "Piano": 32, "Acting": 38, "Teaching": 38, "Sales": 38, "Management": 42, "Accounting": 35, "Legal Knowledge": 42, "Languages": 28, "Foreign Language": 28, "Martial Arts": 45, "Athletics": 40, "Yoga": 32, "Retail": 28, "Tech-Savvy": 22, "Troubleshooting": 28, "Forklift Certified": 28, "Product Knowledge": 18, "Inventory Management": 22, "Customer Service": 25, "Occult Expert": 60, "Sunfish": 500, "Definitely not a Vampire": 500 }; // 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; }>> /* ---------------------------------- */ /* --- MALL HOURS FUNCTION --- */ /* ---------------------------------- */ <<set setup.isMallOpen = function() { var minutes = State.variables.timeInMinutes; var hour = Math.floor(minutes / 60) % 24; // Mall is open from 9am (hour 9) to 5pm (hour 17) return (hour >= 9 && hour < 17); }>> /* ---------------------------------- */ /* --- 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]; // 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; }>> <<set setup.isNPCAvailable = function(npcName) { var npc = setup.getNPCByName(npcName); if (!npc) return false; var schedule = State.variables.npcSchedules[npcName]; if (!schedule) return false; // Check if NPC is always available if (schedule.alwaysAvailable) return true; // Check current day and time var currentDay = State.variables.dayOfWeek; var currentTime = getTimeOfDay(); // Check if current day is in NPC's schedule if (!schedule.days.includes(currentDay)) return false; // Check if current time is in NPC's schedule if (!schedule.times.includes(currentTime)) return false; return true; }>> /* ---------------------------------- */ /* --- JOB-SPECIFIC STARTING TRAITS --- */ /* ---------------------------------- */ <<set setup.jobStartingSkills = { // Physical labor jobs "Construction Worker": ["Heavy Lifting", "Construction"], "Dock Worker": ["Heavy Lifting", "Athletics"], "Security Guard": ["Combat", "Athletics"], // Service jobs "Street Performer": ["Public Speaking", "Acting"], "Package Courier": ["Driving", "Athletics"], "Baker": ["Baking", "Cooking"], "Maid": ["Cleaning", "Maid"], // Entertainment/Sex work "Hooker": ["Sexually Skilled", "Persuasion"], "Stripper": ["Dancing", "Sexually Skilled", "High Heels Proficient"], "Prostitute": ["Sexually Skilled", "Acting"], "Brothel Worker": ["Sexually Skilled", "Persuasion", "High Heels Proficient"], "Model": ["Modeling", "High Heels Proficient"], "Bouncer": ["Combat", "Heavy Lifting"], "Porn Star": ["Sexually Skilled", "Acting"], // Retail/Shop jobs "Fitness Shop Clerk": ["Athletics", "Sales"], "Ecentric Shop Worker": ["Sales", "Art"], "Tech Store Clerk": ["Coding", "Sales"], "Adult Store Clerk": ["Sales", "Persuasion"], "Beauty Salon Stylist": ["Hair Styling", "Makeup"], // Professional jobs "Clinic Assistant": ["Medicine", "First Aid"], "Data Analyst": ["Coding", "Math Skills"], "Negotiator": ["Persuasion", "Public Speaking"], "Enforcer": ["Combat", "Stealth"], "Social Media Influencer": ["Social Media", "Photography"], "Black Market Dealer": ["Trading", "Stealth"], "Police Officer": ["Combat", "Driving", "First Aid"], // Elite jobs "Brothel Owner": ["Management", "Persuasion", "Accounting"], "Mayor's Secretary": ["Management", "Accounting"], "City Mayor": ["Public Speaking", "Management", "Legal Knowledge"] }>> <<set setup.jobStartingPhysicalTraits = { // Physical labor jobs "Construction Worker": ["Muscular", "Strong", "Sturdy"], "Dock Worker": ["Muscular", "Strong", "Broad-shouldered"], "Security Guard": ["Muscular", "Tall", "Strong"], // Service jobs "Street Performer": ["Energetic", "Graceful"], "Package Courier": ["Quick", "Lean"], "Baker": ["Soft"], "Maid": ["Graceful"], // Entertainment/Sex work "Hooker": ["Attractive", "Curvy"], "Stripper": ["Attractive", "Flexible", "Graceful"], "Prostitute": ["Attractive", "Curvy"], "Brothel Worker": ["Attractive", "Voluptuous", "Smooth Skin"], "Model": ["Attractive", "Tall", "Lean"], "Bouncer": ["Muscular", "Tall", "Strong", "Broad-shouldered"], "Porn Star": ["Attractive", "Fit", "Smooth Skin"], // Retail/Shop jobs "Fitness Shop Clerk": ["Fit", "Muscular", "Athletic Build"], "Ecentric Shop Worker": ["Tattooed", "Pierced"], "Tech Store Clerk": ["Lean"], "Adult Store Clerk": ["Attractive", "Pierced"], "Beauty Salon Stylist": ["Attractive", "Graceful"], // Professional jobs "Clinic Assistant": ["Graceful", "Youthful"], "Data Analyst": ["Sharp Features"], "Negotiator": ["Attractive", "Sharp Features"], "Enforcer": ["Muscular", "Strong", "Scarred"], "Social Media Influencer": ["Attractive", "Youthful"], "Black Market Dealer": ["Scarred", "Sharp Features"], "Police Officer": ["Fit", "Strong", "Athletic Build"], // Elite jobs "Brothel Owner": ["Attractive", "Mature", "Voluptuous"], "Mayor's Secretary": ["Attractive", "Sharp Features"], "City Mayor": ["Mature", "Sharp Features"] }>> /* ---------------------------------- */ /* --- NPC GENERATION FUNCTION --- */ /* ---------------------------------- */ <<set setup.generateNPC = function(name, jobs, overrides) { overrides = overrides || {}; var skinTones = ["pale", "tan", "dark"]; var hairColors = ["Black", "Brown", "Blonde", "Red", "Platinum Blonde"]; var hairStyles = ["messy", "short", "long"]; var physiques = ["slim", "athletic", "stocky", "average"]; var ages = ["Adult", "Mature Adult"]; // Gender-specific body part arrays var maleChestSizes = ["flat masculine"]; var femaleChestSizes = ["flat", "small", "medium", "large", "huge", "giant"]; var maleButtSizes = ["flat masculine"]; var femaleButtSizes = ["flat", "small", "medium", "large", "huge", "giant"]; var skills = ["Cooking", "Singing", "Dancing", "Painting", "Writing", "Photography", "Guitar", "Piano", "Coding", "Math Skills", "Languages", "Public Speaking", "Athletics", "Yoga", "Swimming", "Martial Arts", "Heavy Lifting", "Combat", "Persuasion", "Medicine", "Trading", "Stealth", "Driving", "Lock Picking", "First Aid", "Gardening", "Construction", "Social Media", "Baking", "Sexually Skilled", "Modeling", "Makeup", "High Heels Proficient", "Hair Styling", "Cleaning", "Maid", "Serving", "Plumbing", "Art", "Music", "Acting", "Teaching", "Sales", "Management", "Accounting", "Legal Knowledge", "Foreign Language"]; var physicalTraits = ["Tall", "Short", "Muscular", "Curvy", "Petite", "Broad-shouldered", "Flexible", "Strong", "Quick", "Graceful", "Sturdy", "Lean", "Soft", "Sharp Features", "Smooth Skin", "Scarred", "Pierced", "Youthful", "Mature", "Tattooed", "Attractive", "Plain", "Ugly", "Fit", "Overweight", "Underweight", "Clumsy", "Weak", "Stiff", "Blemished", "Freckled", "Athletic Build", "Voluptuous"]; var voiceTraits = ["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", "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"]; var mentalTraits = ["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", "Jealous", "Supportive", "Lazy", "Hardworking", "Arrogant", "Humble", "Paranoid", "Trusting", "Complacent", "Dull", "Brave", "Cowardly", "Immature", "Impatient", "Wise", "Foolish", "Nonchalant", "Charming", "Diplomatic", "Organized", "Resourceful", "Focused", "Disciplined", "Determined", "Steadfast", "Considerate", "Blunt", "Perfectionist", "Overthinker", "Moody", "Unpredictable", "Risk Taker", "Impulsive", "Cynical", "Forgetful", "Disorganized", "Selfish", "Deceitful", "Erratic", "Obsessive", "Insecure", "Short Tempered", "Polite", "Funny", "Reassuring", "Loyal", "Talkative", "Direct", "Quiet", "Rude", "Awkward", "Tone Deaf", "Efficient", "Negotiator", "Crafty", "Workaholic", "Unreliable", "Slow Learner", "High Stamina", "Reckless", "Flirty", "Seductive", "Alluring", "Warm", "Cold", "Tease", "Clingy", "Insensitive", "Sensitive", "Bookworm", "Unskilled", "Corporate Drone", "Lucky", "Unlucky", "Nerd", "Geek", "Jock", "Prep", "Tomboy", "Femboy", "Diva", "Goth"]; var characterTraits = ["Quick Learner", "Swift", "Silver-Tongued", "Pensive", "Jock", "Naturally Gifted"]; function getRandomItems(array, count) { var shuffled = array.sort(function() { return 0.5 - Math.random(); }); return shuffled.slice(0, count); } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } // Use gender from overrides if provided, otherwise random var gender = overrides.gender || ["male", "female"][Math.floor(Math.random() * 2)]; var skinTone = skinTones[Math.floor(Math.random() * skinTones.length)]; var jobName = Array.isArray(jobs) ? jobs[0] : jobs; // Get job requirements var jobReqs = setup.jobRequirements[jobName] || {}; // Generate base stats - start at 10-30 for all stats var npcStats = { charisma: getRandomInt(10, 30), dexterity: getRandomInt(10, 30), strength: getRandomInt(10, 30), intelligence: getRandomInt(10, 30) }; // Ensure all required stats meet minimums, then add random bonus for (var stat in jobReqs) { var minRequired = jobReqs[stat]; var bonus = getRandomInt(0, 20); // Can be 0-20 above minimum npcStats[stat] = Math.max(npcStats[stat], minRequired + bonus); } // Special handling for elite jobs - give them even higher stats if (jobName === "City Mayor") { npcStats.charisma = getRandomInt(85, 99); npcStats.intelligence = getRandomInt(70, 90); } else if (jobName === "Mayor's Secretary") { npcStats.intelligence = getRandomInt(75, 95); npcStats.charisma = getRandomInt(50, 70); } else if (jobName === "Brothel Owner") { npcStats.charisma = getRandomInt(75, 95); npcStats.intelligence = getRandomInt(50, 70); } // Cap all stats at 99 for (var stat in npcStats) { npcStats[stat] = Math.min(99, npcStats[stat]); } var npcStatMaxCaps = { charisma: 100, dexterity: 100, strength: 100, intelligence: 100 }; var hardTraits = {}; // Select body parts based on gender var chestSize, buttSize; if (gender === "male") { chestSize = maleChestSizes[0]; buttSize = maleButtSizes[0]; } else { chestSize = femaleChestSizes[Math.floor(Math.random() * femaleChestSizes.length)]; buttSize = femaleButtSizes[Math.floor(Math.random() * femaleButtSizes.length)]; } // Start with job-specific skills var jobSkills = setup.jobStartingSkills[jobName] || []; var randomSkillCount = Math.max(0, getRandomInt(2, 5) - jobSkills.length); var randomSkills = getRandomItems(skills.filter(function(s) { return !jobSkills.includes(s); }), randomSkillCount); var allSkills = overrides && overrides.skills ? overrides.skills : jobSkills.concat(randomSkills); // Start with job-specific physical traits var jobPhysicalTraits = setup.jobStartingPhysicalTraits[jobName] || []; // Filter out conflicting traits var validPhysicalTraits = physicalTraits.filter(function(trait) { if (jobPhysicalTraits.includes(trait)) return false; // Check if this trait conflicts with any job trait var conflict = setup.getConflictingTrait(trait, jobPhysicalTraits); if (conflict) return false; // Check body type compatibility var bodyTypeTraits = ["Curvy", "Voluptuous", "Petite", "Slim"]; if (bodyTypeTraits.includes(trait)) { return setup.isBodyTypeCompatible(trait, chestSize, buttSize); } return true; }); var randomPhysicalCount = Math.max(0, getRandomInt(2, 4) - jobPhysicalTraits.length); var randomPhysicalTraits = getRandomItems(validPhysicalTraits, randomPhysicalCount); // Filter random traits to avoid conflicts with each other var finalRandomTraits = []; for (var i = 0; i < randomPhysicalTraits.length; i++) { var trait = randomPhysicalTraits[i]; var hasConflict = setup.getConflictingTrait(trait, jobPhysicalTraits.concat(finalRandomTraits)); if (!hasConflict) { finalRandomTraits.push(trait); } } var allPhysicalTraits = jobPhysicalTraits.concat(finalRandomTraits); // Mental traits with conflict filtering var baseMentalTraits = overrides && overrides.mentalTraits ? overrides.mentalTraits : getRandomItems(mentalTraits, getRandomInt(2, 4)); // Filter out conflicting mental traits var validMentalTraits = []; for (var i = 0; i < baseMentalTraits.length; i++) { var trait = baseMentalTraits[i]; var hasConflict = setup.getConflictingTrait(trait, validMentalTraits); if (!hasConflict) { validMentalTraits.push(trait); } } var allMentalTraits = validMentalTraits.slice(); if (Math.random() < 0.2) { var charTrait = characterTraits[Math.floor(Math.random() * characterTraits.length)]; allMentalTraits.push(charTrait); } allSkills.forEach(function(skill) { hardTraits["skill:" + skill] = getRandomInt(0, 40); }); allPhysicalTraits.forEach(function(trait) { hardTraits["physical:" + trait] = getRandomInt(0, 40); }); allMentalTraits.forEach(function(trait) { hardTraits["mental:" + trait] = getRandomInt(0, 40); }); ["charisma", "dexterity", "strength", "intelligence"].forEach(function(stat) { hardTraits["stat:" + stat] = getRandomInt(0, 40); }); ["chest", "butt", "gender"].forEach(function(bodyPart) { hardTraits["bodyPart:" + bodyPart] = getRandomInt(10, 50); }); // Randomly select hair length based on gender // Females: 75% long, 25% short // Males: 75% short, 25% long var hairLength; if (gender === "female") { hairLength = Math.random() < 0.75 ? "long" : "short"; } else { hairLength = Math.random() < 0.75 ? "short" : "long"; } var npc = { name: name, jobs: Array.isArray(jobs) ? jobs : [jobs], stats: npcStats, statMaxCaps: npcStatMaxCaps, bodyParts: { gender: gender, chest: chestSize, butt: buttSize }, appearance: { skinTone: skinTone, hairColor: hairColors[Math.floor(Math.random() * hairColors.length)], hairStyle: hairStyles[Math.floor(Math.random() * hairStyles.length)], hairLength: hairLength, physique: physiques[Math.floor(Math.random() * physiques.length)], age: ages[Math.floor(Math.random() * ages.length)] }, skills: allSkills, physicalTraits: allPhysicalTraits, mentalTraits: allMentalTraits, hardTraits: hardTraits }; // Apply bonuses from all traits and skills allMentalTraits.forEach(function(trait) { if (setup.traitBonuses && setup.traitBonuses[trait]) { setup.applyTraitBonus(trait, npc); } }); allPhysicalTraits.forEach(function(trait) { if (setup.traitBonuses && setup.traitBonuses[trait]) { setup.applyTraitBonus(trait, npc); } }); allSkills.forEach(function(skill) { if (setup.skillBonuses && setup.skillBonuses[skill]) { setup.applyTraitBonus(skill, npc); } }); // Add hair length as a physical trait if (hairLength === "short") { npc.physicalTraits.push("Short Hair"); } else { npc.physicalTraits.push("Long Hair"); } // Add one random voice trait (mutually exclusive) var randomVoiceTrait = voiceTraits[Math.floor(Math.random() * voiceTraits.length)]; npc.physicalTraits.push(randomVoiceTrait); return npc; }>> /* ---------------------------------- */ /* --- INITIALIZE CORE VARIABLES --- */ /* ---------------------------------- */ /* Initialize NPC array BEFORE loading data passages */ <<set $npcs = []>> <<set $metNPCs = []>> <<set $currentTradeNPC = null>> <<set $tradeHistory = []>> /* 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 CHANCE CALCULATION --- */ /* ---------------------------------- */ <<set setup.calculatePreferenceValueAdjustment = function(npc, playerPackage, npcPackage, baseNpcValue) { var preferences = setup.getNPCPreferences(npc.name); if (!preferences) return baseNpcValue; var adjustedValue = 0; // 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); var multiplier = 1.0; if (preferences.reluctantToTrade && preferences.reluctantToTrade.skills && preferences.reluctantToTrade.skills.includes(skill)) { multiplier = 1.5; } else if (preferences.willingToTrade && preferences.willingToTrade.skills && preferences.willingToTrade.skills.includes(skill)) { multiplier = 0.8; } adjustedValue += Math.ceil(skillValue * multiplier); } } // 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); var multiplier = 1.0; if (preferences.reluctantToTrade && preferences.reluctantToTrade.mental && preferences.reluctantToTrade.mental.includes(trait)) { multiplier = 1.5; } else if (preferences.willingToTrade && preferences.willingToTrade.mental && preferences.willingToTrade.mental.includes(trait)) { multiplier = 0.8; } adjustedValue += Math.ceil(traitValue * multiplier); } } // 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); var multiplier = 1.0; if (preferences.reluctantToTrade && preferences.reluctantToTrade.physical && preferences.reluctantToTrade.physical.includes(trait)) { multiplier = 1.5; } else if (preferences.willingToTrade && preferences.willingToTrade.physical && preferences.willingToTrade.physical.includes(trait)) { multiplier = 0.8; } adjustedValue += Math.ceil(traitValue * multiplier); } } // 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]; var partValue = setup.getTraitValue("bodyPart", part.name, npc.bodyParts[part.name]); var multiplier = 1.0; if (preferences.reluctantToTrade && preferences.reluctantToTrade.bodyParts && preferences.reluctantToTrade.bodyParts.includes(part.name)) { multiplier = 1.5; } else if (preferences.willingToTrade && preferences.willingToTrade.bodyParts && preferences.willingToTrade.bodyParts.includes(part.name)) { multiplier = 0.8; } adjustedValue += Math.ceil(partValue * multiplier); } } // Job - check job preference if (npcPackage.job !== null && npcPackage.job !== undefined) { var jobValue = setup.getTraitValue("job", npcPackage.job || "Unemployed"); var multiplier = 1.0; if (preferences.reluctantToTrade && preferences.reluctantToTrade.job) { multiplier = 1.5; } else if (preferences.willingToTrade && preferences.willingToTrade.job) { multiplier = 0.8; } adjustedValue += Math.ceil(jobValue * multiplier); } // 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(1, adjustedValue); }>> <<set setup.calculateTradeChance = function(playerValue, npcValue, npc, playerPackage, npcPackage) { 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: Logarithmic scaling // 8% at 100 charisma, 20% at 999 charisma var totalCharisma = setup.getTotalStat("charisma"); var charismaBonus = 0; if (totalCharisma > 0) { // Use logarithmic formula adjusted for desired scaling // At charisma = 100: should give ~8% // At charisma = 999: should give ~20% // Formula: baseValue * log(charisma) / log(targetCharisma) // Adjusted: 8.67 * log(charisma + 1) / log(101) gives ~8% at 100 // Then scale up to 20% at 999 var logValue = Math.log(totalCharisma + 1) / Math.log(101); charismaBonus = Math.floor(8.67 * logValue); // Additional scaling for higher values if (totalCharisma > 100) { var highBonus = ((totalCharisma - 100) / 899) * (20 - 8); charismaBonus = Math.floor(8 + highBonus); } charismaBonus = Math.max(0, Math.min(20, charismaBonus)); // Cap between 0-20% } chance += charismaBonus; // Apply Trading skill bonus: +2% if (v.skills.includes("Trading")) { chance += 2; } // Apply Bitchy trait penalty: -5% if (v.mentalTraits.includes("Bitchy")) { chance -= 5; } // Apply Persuasion skill bonus: +3% if (v.skills.includes("Persuasion")) { chance += 3; } // Apply NPC preference modifier var preferenceModifier = setup.calculatePreferenceModifier(npc, playerPackage, npcPackage); chance += preferenceModifier; // Apply relationship bonus var relationshipBonus = setup.getRelationshipTradeBonus(npc.name); chance += relationshipBonus; // Clamp between 0 and 100 return Math.max(0, Math.min(100, Math.round(chance))); }>> /* ---------------------------------- */ /* --- 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: 1, points: 0 }; } }>> <<set setup.addRelationshipPoints = function(npcName, points) { var v = State.variables; // Initialize relationship if it doesn't exist if (!v.relationships[npcName]) { v.relationships[npcName] = { level: 1, points: 0 }; } // Add points (can be negative) v.relationships[npcName].points += points; // Prevent negative points if (v.relationships[npcName].points < 0) { v.relationships[npcName].points = 0; } // Define points needed for each level var levelThresholds = [0, 10, 30, 60, 100]; // Calculate new level based on points var newLevel = 1; for (var i = levelThresholds.length - 1; i >= 0; i--) { if (v.relationships[npcName].points >= levelThresholds[i]) { newLevel = i + 1; break; } } v.relationships[npcName].level = newLevel; // Return the updated relationship for verification return v.relationships[npcName]; }>> <<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 totalValue = 0; // Name if (tradePackage.name && tradePackage.name.length > 0) { tradePackage.name.forEach(function(nameItem) { totalValue += 5; // Each name part worth 5 }); } // Stats value (player gives 3 points for 1 value, NPC gives 1 point for 1 value) if (tradePackage.stats && tradePackage.stats.length > 0) { tradePackage.stats.forEach(function(stat) { if (isPlayer) { totalValue += Math.floor(stat.amount / 3); } else { totalValue += stat.amount; } }); } // Physical traits if (tradePackage.physical && tradePackage.physical.length > 0) { tradePackage.physical.forEach(function(trait) { totalValue += setup.getTraitValue("physical", trait); }); } // Mental traits if (tradePackage.mental && tradePackage.mental.length > 0) { tradePackage.mental.forEach(function(trait) { totalValue += setup.getTraitValue("mental", trait); }); } // Skills if (tradePackage.skills && tradePackage.skills.length > 0) { tradePackage.skills.forEach(function(skill) { totalValue += setup.getTraitValue("skill", skill); }); } // Body parts if (tradePackage.bodyParts && tradePackage.bodyParts.length > 0) { tradePackage.bodyParts.forEach(function(part) { if (part.name === "chest" || part.name === "butt") { var value = isPlayer ? setup.getTraitValue("bodyPart", part.name, State.variables.bodyParts[part.name]) : setup.getTraitValue("bodyPart", part.name, part.npc.bodyParts[part.name]); totalValue += value; } else if (part.name === "gender") { totalValue += 20; } else if (part.name === "skinTone") { totalValue += 10; } else if (part.name === "hairColor") { totalValue += 8; } else if (part.name === "hairLength") { totalValue += 8; } else if (part.name === "age") { totalValue += 12; } }); } // Job if (tradePackage.job) { totalValue += setup.getTraitValue("job", tradePackage.job); } return totalValue; }>> /* ---------------------------------- */ /* --- NPC TRADING PREFERENCES --- */ /* ---------------------------------- */ <<set setup.npcTradingPreferences = { "Marcus Carter": { desires: { skills: ["Medicine", "Coding"], mental: ["Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Combat", "Athletics", "Public Speaking", "Acting"], mental: ["Confident", "Brave"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Guitar"], mental: ["Outgoing"], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Shy", "Cowardly"], physical: ["Weak", "Underweight", "Ugly"], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] } }, "Elena Romero": { desires: { skills: ["Languages", "Art"], mental: ["Creative", "Empathetic"], physical: ["Attractive"], bodyParts: [], chestSize: ["medium", "large"], buttSize: ["medium", "large"] }, willingToTrade: { skills: ["Coding", "Math Skills", "Painting"], mental: ["Analytical", "Shy"], physical: ["Graceful", "Youthful"], bodyParts: [], chestSize: ["small"], buttSize: ["small"], job: true }, reluctantToTrade: { skills: ["Medicine", "First Aid"], mental: ["Patient", "Kind", "Intelligent"], physical: ["Sharp Features"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cruel", "Aggressive", "Arrogant"], physical: ["Muscular", "Scarred", "Ugly"], bodyParts: [], chestSize: ["giant","flat masculine"], buttSize: ["giant","flat masculine"] } }, "Silva Silva": { desires: { skills: ["Management", "Accounting"], mental: ["Diplomatic", "Organized"], physical: ["Fashionable", "Attractive"], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["large", "huge"] }, willingToTrade: { skills: ["Driving", "Athletics", "Languages"], mental: ["Ambitious"], physical: ["Quick", "Lean"], bodyParts: [], chestSize: ["medium"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Persuasion", "Public Speaking"], mental: ["Shrewd", "Confident"], physical: ["Athletic Build"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Disorganized", "Dull"], physical: ["Overweight", "Clumsy", "Plain"], bodyParts: [], chestSize: ["small", "flat"], buttSize: ["small", "flat"] } }, "Grimm Patel": { desires: { skills: ["Legal Knowledge"], mental: ["Calm", "Patient"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Cooking"], mental: ["Stubborn", "Cynical"], physical: ["Scarred"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Combat", "Stealth", "Persuasion"], mental: ["Dominant", "Shrewd"], physical: ["Muscular", "Strong"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], 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"] } }, "Scarlett Vex": { desires: { skills: ["Management", "Business"], mental: ["Shrewd", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"] }, willingToTrade: { skills: ["Photography", "Dancing"], mental: ["Ambitious", "Arrogant"], physical: ["Fit", "Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled", "Acting", "Modeling"], mental: ["Confident", "Outgoing"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Submissive"], physical: ["Ugly", "Plain", "Overweight"], bodyParts: [], chestSize: ["flat", "small", "medium","flat masculine"], buttSize: ["flat", "small", "medium","flat masculine"] } }, "Jade Nightshade": { desires: { skills: ["Persuasion", "Social Media"], mental: ["Confident", "Alluring"], physical: ["Voluptuous"], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Singing", "Acting"], mental: ["Creative"], physical: ["Flexible", "Graceful"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Dancing", "Sexually Skilled"], mental: ["Sly"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Honest", "Naive", "Insecure"], physical: ["Plain", "Stiff", "Clumsy"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small","flat masculine"] } }, "Apollo Sterling": { desires: { skills: ["Acting", "Photography"], mental: ["Ambitious", "Charismatic"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Music", "Athletics"], mental: ["Creative"], physical: ["Flexible", "Graceful"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Dancing", "Modeling"], mental: ["Confident", "Outgoing"], physical: ["Muscular"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Awkward", "Insecure"], physical: ["Ugly", "Overweight", "Weak"], bodyParts: [], chestSize: ["medium", "large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Diamond Murphy": { desires: { skills: ["Management", "Sales"], mental: ["Organized", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Baking", "Stealth"], mental: ["Stubborn", "Selfish"], physical: ["Tattooed"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled", "Persuasion"], mental: ["Sly", "Hardworking"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Naive", "Trusting", "Kind"], physical: ["Soft", "Youthful", "Plain"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small", "medium","flat masculine"] } }, "Tank Morrison": { desires: { skills: ["First Aid", "Driving"], mental: ["Patient", "Intelligent"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Cooking", "Athletics"], mental: [], physical: ["Scarred"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Combat", "Heavy Lifting"], mental: ["Brave", "Calm", "Honest", "Loyal"], physical: ["Muscular", "Tall", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Deceitful", "Selfish", "Cowardly"], physical: ["Weak", "Clumsy", "Frail"], bodyParts: [], chestSize: ["medium", "large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Candace Luxe": { desires: { skills: ["Photography", "Art"], mental: ["Creative", "Sensitive"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"] }, willingToTrade: { skills: ["Painting", "Dancing"], mental: ["Friendly", "Empathetic"], physical: ["Pierced", "Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Confident", "Warm"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cold", "Cruel", "Aggressive"], physical: ["Scarred", "Blemished", "Ugly"], bodyParts: [], chestSize: ["flat", "small", "medium"], buttSize: ["flat", "small", "medium"] } }, "Ruby Becker": { desires: { skills: ["Public Speaking", "Acting"], mental: ["Confident", "Outgoing"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Writing", "Photography"], mental: ["Creative", "Shy"], physical: ["Freckled", "Smooth Skin"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Kind", "Sensitive"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cruel", "Aggressive", "Arrogant"], physical: ["Scarred", "Ugly", "Overweight"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"] } }, "Sapphire Wallace": { desires: { skills: ["Management", "Business"], mental: ["Shrewd", "Organized"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"] }, willingToTrade: { skills: ["Martial Arts", "Dancing"], mental: ["Ambitious", "Aggressive"], physical: ["Tattooed", "Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Dominant", "Confident"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Shy", "Weak"], physical: ["Soft", "Weak", "Plain"], bodyParts: [], chestSize: ["flat", "small", "medium","flat masculine"], buttSize: ["flat", "small","flat masculine"] } }, "Jasmine Abrams": { desires: { skills: ["Meditation", "Art"], mental: ["Calm", "Creative"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["giant"] }, willingToTrade: { skills: ["Yoga"], mental: ["Patient", "Submissive"], physical: ["Flexible", "Graceful", "Smooth Skin"], bodyParts: [], chestSize: ["medium"], buttSize: ["huge"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled", "Dancing"], mental: ["Friendly", "Kind"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Scarred", "Ugly", "Stiff"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small","flat masculine"] } }, "Ebony Vasquez": { desires: { skills: ["Management", "Public Speaking"], mental: ["Confident", "Ambitious"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["giant"] }, willingToTrade: { skills: ["Acting", "Singing"], mental: ["Competitive"], physical: ["Smooth Skin"], bodyParts: [], chestSize: ["large"], buttSize: ["huge"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Sly", "Witty"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Dull"], physical: ["Ugly", "Plain", "Clumsy"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small", "medium","flat masculine"] } }, "Amber Skye": { desires: { skills: ["Photography", "Acting"], mental: ["Creative", "Ambitious"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Social Media", "Music"], mental: ["Curious", "Naive"], physical: ["Youthful", "Smooth Skin"], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Sexually Skilled"], mental: ["Optimistic", "Energetic"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cynical", "Cruel", "Pessimistic"], physical: ["Scarred", "Ugly", "Mature"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small","flat masculine"] } }, "Kate Velvet": { desires: { skills: ["Legal Knowledge", "Public Speaking"], mental: ["Intelligent", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"] }, willingToTrade: { skills: ["Languages"], mental: ["Arrogant"], physical: [], bodyParts: [], chestSize: [], buttSize: [], 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"], job: false }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Naive", "Foolish"], physical: ["Ugly", "Youthful", "Plain"], bodyParts: [], chestSize: ["flat", "small", "medium","flat masculine"], buttSize: ["flat", "small", "medium","flat masculine"] } }, "Bella Carver": { desires: { skills: ["Management", "Business"], mental: ["Shrewd", "Organized"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Acting", "Makeup"], mental: ["Creative", "Naive"], physical: ["Youthful"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Social Media", "Photography"], mental: ["Outgoing", "Ambitious"], physical: ["Attractive", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Introverted", "Cynical", "Mature"], physical: ["Ugly", "Mature", "Scarred"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small","flat masculine"] } }, "Jake Steel": { desires: { skills: ["Mechanical Repair"], mental: ["Patient", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Fishing", "Driving"], mental: ["Calm"], physical: ["Sturdy"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Hardworking", "Honest", "Loyal"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Deceitful", "Lazy"], physical: ["Weak", "Clumsy", "Soft"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Marco Rodriguez": { desires: { skills: ["Dancing", "Music"], mental: ["Creative", "Outgoing"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Cooking", "Guitar"], mental: ["Friendly"], physical: ["Tattooed"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Competitive", "Brave"], physical: ["Muscular", "Strong", "Sturdy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Introverted", "Cold"], physical: ["Weak", "Stiff", "Plain"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Tyrone Washington": { desires: { skills: ["Business", "Public Speaking"], mental: ["Ambitious", "Confident"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Basketball", "Music"], mental: [], physical: ["Tall"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Outgoing", "Witty"], physical: ["Muscular", "Strong", "Sturdy", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Submissive"], physical: ["Short", "Weak", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Sheryl Williams": { desires: { skills: ["Management", "Leadership"], mental: ["Organized", "Diplomatic"], physical: [], bodyParts: [], chestSize: ["medium", "large"], buttSize: ["large", "huge"] }, willingToTrade: { skills: ["Gardening"], mental: ["Stubborn"], physical: ["Athletic Build"], bodyParts: [], chestSize: ["small"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction", "Martial Arts"], mental: ["Hardworking", "Brave"], physical: ["Muscular", "Strong", "Sturdy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive", "Shy", "Weak"], physical: ["Soft", "Weak", "Graceful"], bodyParts: [], chestSize: ["flat", "giant"], buttSize: ["flat", "small"] } }, "David O'Brien": { desires: { skills: ["Art", "Music"], mental: ["Creative", "Calm"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Plumbing", "Painting"], mental: [], physical: ["Freckled"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Construction"], mental: ["Calm", "Patient", "Thoughtful"], physical: ["Muscular", "Strong", "Sturdy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Loud", "Arrogant"], physical: ["Weak", "Clumsy", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Mike Murphy": { desires: { skills: ["Combat Training"], mental: ["Disciplined", "Focused"], physical: [], bodyParts: [], chestSize: [], buttSize: [], desiredJob: "Brothel Worker" }, willingToTrade: { skills: ["Cooking", "Swimming"], mental: ["Aggressive", "Short Tempered"], physical: ["Tattooed"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Competitive", "Brave"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Calm", "Patient", "Submissive"], physical: ["Weak", "Soft", "Graceful"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Carlos Mendez": { desires: { skills: ["Cooking", "Performance"], mental: ["Creative", "Charming"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Dancing", "Guitar"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Friendly", "Outgoing", "Optimistic"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cold", "Cruel", "Pessimistic"], physical: ["Ugly", "Scarred", "Weak"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Jamal Rivers": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Basketball", "Writing"], mental: [], physical: ["Athletic Build"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Intelligent", "Competitive"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Foolish", "Disorganized"], physical: ["Weak", "Overweight", "Clumsy"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Rosa Otterino": { desires: { skills: ["Art", "Photography"], mental: ["Creative", "Patient"], physical: [], bodyParts: [], chestSize: ["medium", "large"], buttSize: ["large", "huge"] }, willingToTrade: { skills: ["Swimming", "Painting"], mental: [], physical: ["Athletic Build", "Tattooed"], bodyParts: [], chestSize: ["small"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Hardworking", "Honest", "Calm"], physical: ["Muscular", "Strong"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Deceitful", "Lazy"], physical: ["Weak", "Soft", "Clumsy"], bodyParts: [], chestSize: ["flat", "giant"], buttSize: ["flat", "small"] } }, "Keisha Jackson": { desires: { skills: ["Performance", "Music"], mental: ["Creative", "Outgoing"], physical: ["Attractive"], bodyParts: [], chestSize: ["large", "huge","flat masculine"], buttSize: ["huge", "giant","flat masculine"] }, willingToTrade: { skills: ["Singing", "Cooking"], mental: [], physical: ["Curvy"], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Heavy Lifting", "Athletics"], mental: ["Confident", "Outgoing", "Brave"], physical: ["Muscular", "Strong", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Introverted", "Cold"], physical: ["Weak", "Plain", "Slim"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"] } }, "Dick Richardson": { desires: { skills: ["Business", "Finance"], mental: ["Shrewd", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: [], mental: ["Arrogant", "Selfish"], physical: [], bodyParts: [], chestSize: [], buttSize: [], job: false }, reluctantToTrade: { skills: ["Public Speaking", "Management", "Legal Knowledge"], mental: ["Shrewd", "Ambitious", "Dominant"], physical: ["Mature", "Sharp Features"], bodyParts: [], chestSize: [], buttSize: [], job: false }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Honest", "Kind", "Submissive"], physical: ["Youthful", "Attractive", "Weak"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Creo Applesauce": { desires: { skills: ["Art", "Music"], mental: ["Creative", "Confident"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Piano", "Languages"], mental: ["Submissive", "Anxious"], physical: ["Lean"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Management", "Accounting", "Coding"], mental: ["Intelligent", "Analytical", "Patient"], physical: ["Sharp Features"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Dominant", "Arrogant"], physical: ["Muscular", "Scarred", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Brad Icus": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Gardening", "Cooking"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Athletics", "Sales", "Heavy Lifting"], mental: ["Energetic", "Friendly", "Optimistic"], physical: ["Fit", "Muscular", "Athletic Build", "Attractive"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Pessimistic", "Introverted"], physical: ["Weak", "Overweight", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Raven Bido": { desires: { skills: ["Music", "Performance"], mental: ["Confident", "Outgoing"], physical: [], bodyParts: [], chestSize: ["medium", "large","flat masculine"], buttSize: ["medium", "large","flat masculine"] }, willingToTrade: { skills: [], mental: ["Introverted", "Shy"], physical: ["Lean", "Youthful"], bodyParts: [], chestSize: ["small"], buttSize: ["small"], job: true }, reluctantToTrade: { skills: ["Sales", "Art", "Painting", "Music", "Writing"], mental: ["Creative", "Curious"], physical: ["Tattooed", "Pierced"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Prep", "Optimistic"], physical: ["Plain", "Fashionable", "Smooth Skin"], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"] } }, "Crystal Meffin": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["large", "huge"] }, willingToTrade: { skills: ["Art", "Photography"], mental: [], physical: ["Youthful"], bodyParts: [], chestSize: ["medium"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Hair Styling", "Makeup"], mental: ["Friendly", "Outgoing", "Creative"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Introverted", "Cynical", "Rude"], physical: ["Ugly", "Clumsy", "Scarred"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"] } }, "Sophi Boris": { desires: { skills: ["Acting", "Performance"], mental: ["Creative", "Confident"], physical: [], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Social Media", "Singing"], mental: ["Arrogant"], physical: ["Curvy"], bodyParts: [], chestSize: ["large"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Hair Styling", "Makeup", "Dancing"], mental: ["Witty", "Ambitious"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Humble", "Submissive"], physical: ["Plain", "Ugly", "Stiff"], bodyParts: [], chestSize: ["flat", "small", "medium"], buttSize: ["flat", "small"] } }, "Naomi Light": { desires: { skills: ["Meditation", "Teaching"], mental: ["Calm", "Wise"], physical: [], bodyParts: [], chestSize: ["medium", "large","flat masculine"], buttSize: ["large", "huge","flat masculine"] }, willingToTrade: { skills: ["Yoga", "Gardening"], mental: [], physical: ["Flexible"], bodyParts: [], chestSize: ["small"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Hair Styling", "Makeup"], mental: ["Kind", "Patient", "Empathetic"], physical: ["Attractive", "Graceful"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Scarred", "Ugly", "Stiff"], bodyParts: [], chestSize: ["flat", "giant"], buttSize: ["flat", "small"] } }, "Kevin Oats": { desires: { skills: ["Social Skills", "Public Speaking"], mental: ["Confident", "Outgoing"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [], desiredJob: "Brothel Worker" }, willingToTrade: { skills: ["Gaming"], mental: ["Shy", "Awkward", "Insecure"], physical: ["Lean", "Youthful"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Coding", "Sales", "Math Skills"], mental: ["Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: ["flat masculine"], buttSize: ["flat masculine"] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Arrogant", "Aggressive", "Dominant"], physical: ["Ugly", "Muscular", "Scarred"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Destiny Pumpkin": { desires: { skills: ["Business", "Management"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Art", "Writing"], mental: ["Selfish"], physical: ["Tattooed", "Pierced"], bodyParts: [], chestSize: ["huge"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Sales", "Persuasion", "Sexually Skilled"], mental: ["Confident", "Sly", "Creative"], physical: ["Attractive", "Voluptuous"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Kind", "Honest", "Submissive"], physical: ["Plain", "Ugly", "Soft"], bodyParts: [], chestSize: ["flat", "small", "medium"], buttSize: ["flat", "small"] } }, "Alex Passionfruit": { desires: { skills: ["Art", "Photography"], mental: ["Creative", "Sensitive"], physical: [], bodyParts: ["huge"], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Music", "Gaming"], mental: [], physical: ["Lean", "Pierced"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Sales", "Persuasion", "Sexually Skilled"], mental: ["Outgoing", "Witty", "Curious"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Ugly", "Muscular", "Overweight"], bodyParts: [], chestSize: ["huge", "giant"], buttSize: ["huge", "giant"] } }, "Hannah Chuckins": { desires: { skills: ["Business", "Sales"], mental: ["Ambitious", "Confident"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Painting", "Singing"], mental: ["Shy"], physical: ["Freckled"], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Baking", "Cooking", "Gardening"], mental: ["Kind", "Patient", "Creative"], physical: ["Soft", "Curvy"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cruel", "Aggressive", "Arrogant"], physical: ["Ugly", "Scarred", "Athletic Build"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"] } }, "Pheiffer Coms": { desires: { skills: ["Medicine", "Investigation"], mental: ["Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Fishing"], mental: ["Stubborn"], physical: [], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Combat", "Driving", "First Aid", "Athletics"], mental: ["Brave", "Honest"], physical: ["Fit", "Strong", "Athletic Build", "Broad-shouldered"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Deceitful", "Cowardly", "Lazy"], physical: ["Weak", "Overweight", "Clumsy"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Fen Ris": { desires: { skills: ["Legal Knowledge", "Sexually Skilled"], mental: ["Calm", "Patient", "Honest"], physical: ["Curvy"], bodyParts: [], chestSize: ["giant"], buttSize: ["large", "huge", "giant"] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: ["huge"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Teaching", "Athletics", "Heavy Lifting", "Combat", "Yoga"], mental: ["Confident"], physical: ["Sharp Features", "Muscular", "Athletic Build", "Tall"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: ["Calm", "Patient", "Honest"], physical: ["Were-Creature"], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Deceitful", "Cowardly", "Cruel"], physical: ["Weak", "Ugly", "Blemished"], bodyParts: [], chestSize: ["flat", "small","flat masculine"], buttSize: ["flat", "small","flat masculine"] } }, "Selkira Onyxia": { desires: { skills: ["Public Speaking", "Social Media"], mental: ["Extroverted", "Patient", "Warm"], physical: ["Pale Skin"], bodyParts: [], chestSize: ["huge"], buttSize: [] }, willingToTrade: { skills: ["Serving", "Acting", "Languages"], mental: ["Overthinker", "Impulsive", "Cold", "Jealous"], physical: ["Broad-shouldered"], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"], job: true }, reluctantToTrade: { skills: ["High Heels Proficient", "Sexually Skilled"], mental: ["Seductive", "Alluring"], physical: ["Silky Voice"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: ["Dominant"], physical: ["Curvy", "Flexible"], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Submissive"], physical: ["Ugly", "Overweight", "Blemished", "Scarred"], bodyParts: [], chestSize: ["flat masculine", "flat", "small", "medium"], buttSize: ["flat masculine", "flat", "small", "medium", "large"] } }, "Janis Besser": { desires: { skills: ["Modeling", "Sexually Skilled"], mental: ["Competitive", "Creative", "Intelligent"], physical: ["Voluptuous"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"] }, willingToTrade: { skills: ["Gardening", "Painting"], mental: ["Shy", "Nurturing"], physical: ["Petite", "Soft", "Freckled", "Youthful"], bodyParts: [], chestSize: ["small"], buttSize: ["small"], job: true }, reluctantToTrade: { skills: ["Baking", "Cooking"], mental: ["Kind", "Patient", "Creative"], physical: ["Warm Tone", "Quick"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Aggressive", "Cruel", "Arrogant"], physical: ["Muscular", "Tall", "Scarred", "Ugly"], bodyParts: [], chestSize: ["flat masculine", "giant"], buttSize: ["flat masculine", "giant"] } }, "Dennis Fungi": { desires: { skills: ["Music", "Performance", "Art"], mental: ["Creative", "Ambitious"], physical: ["Attractive"], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Yoga"], mental: ["Energetic"], physical: ["Flexible"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Dancing", "Teaching", "Athletics"], mental: ["Confident", "Outgoing", "Disciplined"], physical: ["Fit", "Athletic Build", "Graceful"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Clumsy", "Stiff"], physical: ["Overweight", "Weak", "Ugly"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["huge", "giant"] } }, "Yvela Mushroom": { desires: { skills: ["Performance", "Acting", "Music"], mental: ["Outgoing", "Creative"], physical: ["Attractive", "Flexible"], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["huge", "giant"] }, willingToTrade: { skills: ["Martial Arts"], mental: ["Competitive"], physical: [], bodyParts: [], chestSize: ["medium"], buttSize: ["large"], job: true }, reluctantToTrade: { skills: ["Dancing", "Teaching", "Athletics", "Yoga"], mental: ["Confident", "Ambitious", "Disciplined"], physical: ["Fit", "Athletic Build", "Graceful"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Lazy", "Shy", "Submissive"], physical: ["Overweight", "Weak", "Clumsy", "Stiff", "Ugly"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"] } }, "Banana Banana": { desires: { skills: ["Customer Service", "Social Media"], mental: ["Creative", "Outgoing"], physical: [], bodyParts: [], chestSize: ["large", "huge"], buttSize: ["large", "huge"] }, willingToTrade: { skills: ["Music"], mental: ["Talkative"], physical: ["Youthful", "Quick"], bodyParts: [], chestSize: ["medium"], buttSize: ["medium"], job: true }, reluctantToTrade: { skills: ["Cooking", "Art"], mental: ["Friendly", "Optimistic", "Energetic", "Bubbly"], physical: ["Friendly Tone", "Fashionable"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Cynical", "Rude", "Introverted"], physical: ["Ugly", "Mature", "Plain"], bodyParts: [], chestSize: ["flat", "small"], buttSize: ["flat", "small"] } }, "Xenis Aku": { desires: { skills: ["Navigation", "Mechanical Repair"], mental: ["Organized", "Patient"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: [], mental: ["Introverted"], physical: ["Mature", "Relaxed"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: ["Driving", "Customer Service", "First Aid"], mental: ["Calm", "Honest", "Reliable", "Thoughtful"], physical: ["Sturdy", "Calm Voice"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Unreliable", "Reckless", "Aggressive"], physical: ["Weak", "Clumsy", "Youthful"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Zanithar Galdenentri": { desires: { skills: ["Medicine", "Teaching"], mental: ["Wise", "Intelligent", "Analytical"], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, willingToTrade: { skills: ["Writing", "Languages"], mental: ["Paranoid", "Erratic", "Obsessive"], physical: ["Underweight", "Mumbly Voice", "Scarred"], bodyParts: [], chestSize: [], buttSize: [], job: true }, reluctantToTrade: { skills: [], mental: ["Crazy", "Eccentric", "Intelligent", "Bookworm"], physical: ["Mature", "Freckled"], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { skills: ["Magic Theory"], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Dull", "Foolish", "Simple"], physical: ["Muscular", "Attractive", "Youthful"], bodyParts: [], chestSize: ["large", "huge", "giant"], buttSize: ["large", "huge", "giant"] } }, "Trixie Rye": { desires: { skills: ["Management", "Business"], mental: ["Ambitious", "Organized"], physical: [], bodyParts: [], chestSize: ["giant"], buttSize: ["giant"] }, willingToTrade: { skills: ["Dancing"], mental: ["Sly"], physical: ["Smooth Skin"], bodyParts: [], chestSize: ["huge"], buttSize: ["huge"], 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: [] }, neverTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], name: false, job: false }, wontTradeFor: { skills: [], mental: ["Shy", "Insecure", "Honest"], physical: ["Ugly", "Plain", "Clumsy", "Stiff"], bodyParts: [], chestSize: ["flat", "small", "medium"], buttSize: ["flat", "small", "medium"] } }, "Revna McKraken": { desires: { 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: [] }, willingToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [], job: false }, reluctantToTrade: { skills: [], mental: [], physical: [], bodyParts: [], chestSize: [], buttSize: [] }, neverTrade: { 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", "Silky Voice", "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"], bodyParts: ["gender", "skinTone", "hairColor", "hairLength", "age"], chestSize: ["medium"], buttSize: ["medium"], name: true, job: true }, wontTradeFor: { skills: ["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", "Yoga", "Retail", "Troubleshooting", "Forklift Certified", "Inventory Management", "Customer Service", "Were-Creature", "Sunfish", "BtestBraitBeesBigBeenore"], mental: ["Swift", "Silver-Tongued", "Pensive", "Jock", "Naturally Gifted", "Extroverted", "Introverted", "Bitchy", "Kind", "Honest", "Dominant", "Submissive", "Shy", "Aggressive", "Passive", "Optimistic", "Pessimistic", "Cruel", "Empathetic", "Stubborn", "Flexible", "Jealous", "Supportive", "Friendly", "Competitive", "Logical", "Lazy", "Hardworking", "Arrogant", "Humble", "Paranoid", "Trusting", "Ambitious", "Complacent", "Dull", "Brave", "Cowardly", "Mature", "Immature", "Impatient", "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", "Tech Savvy"], physical: ["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"], bodyParts: [], chestSize: [], buttSize: [] } } }>> /* ================================== */ /* === 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; } }); } } 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) { 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 "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; } } } } } return false; }>> /* 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 if (preferences.reluctantToTrade) { if (npcPackage.skills && preferences.reluctantToTrade.skills) { npcPackage.skills.forEach(function(skill) { if (preferences.reluctantToTrade.skills.includes(skill)) { multiplier *= 1.5; // 50% premium for reluctant items } }); } if (npcPackage.mental && preferences.reluctantToTrade.mental) { npcPackage.mental.forEach(function(trait) { if (preferences.reluctantToTrade.mental.includes(trait)) { multiplier *= 1.5; } }); } if (npcPackage.physical && preferences.reluctantToTrade.physical) { npcPackage.physical.forEach(function(trait) { if (preferences.reluctantToTrade.physical.includes(trait)) { multiplier *= 1.5; } }); } } return Math.round(baseValue * multiplier); }>> /* ---------------------------------- */ /* --- TRADE EXECUTION FUNCTION --- */ /* ---------------------------------- */ <<set setup.attemptTrade = function(npc, playerPackage, npcPackage) { var v = State.variables; // 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) } // 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 } }; 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]; // 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 === "skinTone" ? v.appearance.skinTone : part.name === "hairColor" ? v.appearance.hairColor : 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 === "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 if (playerPackage.name && playerPackage.name.length > 0) { // 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 tempFirst = v.firstName; v.firstName = 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 schedule key with the new name if (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) { v.physicalTraits.delete(trait); // Check for conflicts with NPC's existing traits var conflict = setup.getConflictingTrait(trait, targetNPC.physicalTraits); if (conflict) { targetNPC.physicalTraits.delete(conflict); } if (!targetNPC.physicalTraits.includes(trait)) { targetNPC.physicalTraits.push(trait); // Auto-adjust body parts if it's a body type trait if (setup.bodyTypeRequirements[trait]) { setup.adjustBodyPartsForTrait(trait, false, targetNPC); } } }); } // Mental traits - player gives to NPC if (playerPackage.mental) { playerPackage.mental.forEach(function(trait) { // 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); } if (!targetNPC.mentalTraits.includes(trait)) { targetNPC.mentalTraits.push(trait); } }); } // 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); } }); } // Body parts swap if (playerPackage.bodyParts) { playerPackage.bodyParts.forEach(function(part) { if (part.name === "chest" || part.name === "butt" || part.name === "gender") { var temp = v.bodyParts[part.name]; v.bodyParts[part.name] = targetNPC.bodyParts[part.name]; targetNPC.bodyParts[part.name] = temp; } else if (part.name === "skinTone" || part.name === "hairColor" || part.name === "age") { var temp = v.appearance[part.name]; v.appearance[part.name] = targetNPC.appearance[part.name]; targetNPC.appearance[part.name] = temp; } else if (part.name === "hairLength") { // Swap hair length var tempHairLength = v.appearance.hairLength; v.appearance.hairLength = targetNPC.appearance.hairLength; targetNPC.appearance.hairLength = tempHairLength; // 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"); } }); } // NPC gives traits/skills to player if (npcPackage.physical) { npcPackage.physical.forEach(function(trait) { targetNPC.physicalTraits.delete(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); // Auto-adjust body parts if it's a body type trait if (setup.bodyTypeRequirements[trait]) { setup.adjustBodyPartsForTrait(trait, true); } } }); } if (npcPackage.mental) { npcPackage.mental.forEach(function(trait) { targetNPC.mentalTraits.delete(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); } }); } if (npcPackage.skills) { npcPackage.skills.forEach(function(skill) { targetNPC.skills.delete(skill); if (!v.skills.includes(skill)) { v.skills.push(skill); } }); } // 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"; // 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]; } // CRITICAL: Update NPC schedule for new job AFTER setting the job if (v.npcSchedules[targetNPC.name]) { setup.updateNPCScheduleForJob(targetNPC.name, playerOldJob); } else { // If no schedule exists, create one setup.updateNPCScheduleForJob(targetNPC.name, playerOldJob); } } else { // Player gave Unemployed - remove first job but keep others if (targetNPC.jobs.length > 1) { targetNPC.jobs.shift(); // Remove first job setup.updateNPCScheduleForJob(targetNPC.name, targetNPC.jobs[0]); } else { targetNPC.jobs = []; setup.updateNPCScheduleForJob(targetNPC.name, "Unemployed"); } } } // Update the reference v.tradingWithNPC = targetNPC; // Calculate and apply relationship points BEFORE clearing packages var relationshipPoints = setup.addTradeRelationshipBonus(npc, playerPackage, npcPackage); if (relationshipPoints !== 0) { setup.addRelationshipPoints(npc.name, relationshipPoints); } // Store relationship points in result for display result.relationshipChange = relationshipPoints; // 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; } return result; }>> /* ---------------------------------- */ /* --- UPDATE NPC SCHEDULE FOR JOB --- */ /* ---------------------------------- */ <<set setup.updateNPCScheduleForJob = function(npcName, newJob) { var v = State.variables; // Job-specific schedules var 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 }, "Hooker": { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"], times: ["evening", "night"], 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 the NPC's schedule var newSchedule = jobSchedules[newJob]; if (newSchedule) { v.npcSchedules[npcName] = newSchedule; } else { // Default schedule if job not found v.npcSchedules[npcName] = { days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"], times: ["morning", "afternoon"], alwaysAvailable: 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, customImages: { face: "", chest: "", butt: "" } }; } // If images are disabled, return custom image or empty string if (!v.imageSettings.imagesEnabled) { return v.imageSettings.customImages.face || ""; } // Otherwise return default image path var gender = v.bodyParts.gender === "male" ? "Male" : "Female"; var hairStyle = v.appearance.hairStyle === "messy" ? "Messy_" : ""; 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"; var filename = gender + "_" + hairStyle + hairLength + "_" + skinTone + "_" + hairColor + "_" + age + ".webp"; 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, 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" }; 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, 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" }; var buttSize = buttSizeMap[v.bodyParts.butt.toLowerCase()] || "Flat"; var filename = buttSize + "_" + skinTone + ".webp"; return "Images/Butts/" + filename; }>> /* ---------------------------------- */ /* --- TRANSFORMATION TEXT FUNCTIONS --- */ /* ---------------------------------- */ <<set setup.getChestTransformationText = function(oldSize, newSize) { var texts = []; var oldIndex = setup.chestSizeOrder.indexOf(oldSize.toLowerCase()); var newIndex = setup.chestSizeOrder.indexOf(newSize.toLowerCase()); var change = newIndex - oldIndex; if (change === 0) { return "Your chest remains unchanged."; } if (change > 0) { // Growing if (change === 1) { texts.push("You feel a subtle warmth in your chest as it swells slightly, filling out a bit more."); texts.push("A tingling sensation spreads across your chest as it grows modestly larger."); } else if (change === 2) { texts.push("Your chest tingles intensely as it expands noticeably, the weight becoming more pronounced."); texts.push("You gasp as your chest swells considerably, pushing outward with newfound fullness."); } else if (change >= 3) { texts.push("Your chest surges outward dramatically, growing substantially as intense waves of sensation course through you."); texts.push("You feel an overwhelming pressure as your chest expands massively, the transformation both shocking and profound."); } } else { // Shrinking change = Math.abs(change); if (change === 1) { texts.push("Your chest tingles as it diminishes slightly, becoming a bit smaller and lighter."); texts.push("You feel a subtle shift as your chest reduces modestly in size."); } else if (change === 2) { texts.push("Your chest shrinks noticeably, the reduction clearly visible as it becomes significantly smaller."); texts.push("A pulling sensation courses through your chest as it decreases considerably in size."); } else if (change >= 3) { texts.push("Your chest rapidly diminishes, shrinking dramatically as the transformation takes hold completely."); texts.push("You feel an intense pulling sensation as your chest reduces massively in size, the change profound and immediate."); } } return texts[Math.floor(Math.random() * texts.length)]; }>> <<set setup.getButtTransformationText = function(oldSize, newSize) { var texts = []; var oldIndex = setup.buttSizeOrder.indexOf(oldSize.toLowerCase()); var newIndex = setup.buttSizeOrder.indexOf(newSize.toLowerCase()); var change = newIndex - oldIndex; if (change === 0) { return "Your butt remains unchanged."; } if (change > 0) { // Growing if (change === 1) { texts.push("You feel a pleasant warmth as your butt swells slightly, filling out a bit more."); texts.push("A tingling sensation spreads through your rear as it grows modestly larger."); } else if (change === 2) { texts.push("Your butt tingles intensely as it expands noticeably, becoming considerably fuller."); texts.push("You gasp as your rear swells substantially, the curves becoming much more pronounced."); } else if (change >= 3) { texts.push("Your butt surges outward dramatically, expanding massively as waves of sensation course through you."); texts.push("You feel an overwhelming pressure as your rear grows enormously, the transformation profound and immediate."); } } else { // Shrinking change = Math.abs(change); if (change === 1) { texts.push("Your butt tingles as it diminishes slightly, becoming a bit smaller and firmer."); texts.push("You feel a subtle shift as your rear reduces modestly in size."); } else if (change === 2) { texts.push("Your butt shrinks noticeably, the reduction clearly visible as it becomes significantly smaller."); texts.push("A pulling sensation courses through your rear as it decreases considerably in size."); } else if (change >= 3) { texts.push("Your butt rapidly diminishes, shrinking dramatically as the transformation takes hold completely."); texts.push("You feel an intense pulling sensation as your rear reduces massively in size, the change immediate and profound."); } } return texts[Math.floor(Math.random() * texts.length)]; }>> <<set setup.getGenderTransformationText = function(oldGender, newGender) { if (oldGender === newGender) { return "Your gender remains unchanged."; } var texts = []; if (newGender === "female") { texts.push("Your entire body tingles as a profound transformation washes over you. Your frame shifts, curves emerging where there were none before. Your face softens, features becoming more delicate. The change is total and unmistakable - you are now female."); texts.push("An overwhelming wave of sensation courses through your entire being. Your body reshapes itself completely - hips widening, waist narrowing, your very essence transforming. When it's over, you stand as a woman."); } else { texts.push("Your entire body tingles as a profound transformation washes over you. Your frame broadens, muscles becoming more prominent. Your face takes on harder angles, your jawline becoming more pronounced. The change is total and unmistakable - you are now male."); texts.push("An overwhelming wave of sensation courses through your entire being. Your body reshapes itself completely - shoulders broadening, frame becoming more angular, your very essence transforming. When it's over, you stand as a man."); } return texts[Math.floor(Math.random() * texts.length)]; }>> <<set setup.getSkinToneTransformationText = function(oldTone, newTone) { if (oldTone === newTone) { return "Your skin tone remains unchanged."; } return "Your skin tingles as its tone shifts, transforming from " + oldTone + " to " + newTone + "."; }>> <<set setup.getHairColorTransformationText = function(oldColor, newColor) { if (oldColor === newColor) { return "Your hair color remains unchanged."; } return "You feel a strange sensation across your scalp as your hair color changes from " + oldColor + " to " + newColor + "."; }>> <<set setup.getHairLengthTransformationText = function(oldLength, newLength) { if (oldLength === newLength) { return "Your hair length remains unchanged."; } var texts = []; if (newLength === "long" || newLength === "long hair") { texts.push("Your hair tingles as it flows downward, growing longer and longer until it reaches well past your shoulders."); texts.push("You feel your hair growing rapidly, cascading down your back as it extends to a much greater length."); } else { texts.push("Your hair tingles as it recedes upward, shortening considerably until it sits close to your head."); texts.push("You feel your hair pulling back, shortening rapidly until it's cropped close and manageable."); } return texts[Math.floor(Math.random() * texts.length)]; }>> <<set setup.getAgeTransformationText = function(oldAge, newAge) { if (oldAge === newAge) { return "Your apparent age remains unchanged."; } var texts = []; if (newAge === "Mature Adult" || newAge === "Mature") { texts.push("You feel your features shifting subtly - fine lines appearing, your face taking on a more mature, distinguished appearance."); texts.push("Your appearance ages gracefully, gaining the wisdom and experience of years in moments."); } else { texts.push("You feel your features smoothing, becoming more youthful and vibrant. Years seem to fall away."); texts.push("Your appearance becomes more youthful, energy and vitality returning to your features."); } return texts[Math.floor(Math.random() * texts.length)]; }>> /* ---------------------------------- */ /* --- 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; 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; }>> /* ---------------------------------- */ /* --- 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 "Hooker": 25, "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; }>> /* ---------------------------------- */ /* --- NPC DIALOGUE SYSTEM --- */ /* ---------------------------------- */ <<set setup.getNPCGreeting = function(npc, relLevel) { var v = State.variables; var greetings = []; // 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"))) { 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; }>> <<set setup.getNPCResponse = function(npc, topic, relLevel) { var v = State.variables; var prefs = setup.getNPCPreferences(npc.name); var responses = []; 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" || job === "Hooker") { 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?"; } } responses.push(jobResponse); } } else if (topic === "opinion") { var opinions = []; // 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")) { 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") { if (npc.mentalTraits.includes("Talkative") || npc.mentalTraits.includes("Outgoing") || npc.mentalTraits.includes("Energetic")) { responses.push("Oh man, you know what I was thinking about the other day? The weather's been absolutely crazy lately! Like, one day it's hot, next day it's cold - make up your mind, nature! But hey, that's Sunfish City for you! Never a dull moment in this place!"); } else if (npc.mentalTraits.includes("Introverted") || npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Quiet")) { responses.push("Um... yeah, things are... fine. Weather's been okay. So... yeah. *awkward silence*"); } else if (npc.mentalTraits.includes("Bitchy") || npc.mentalTraits.includes("Rude") || npc.mentalTraits.includes("Impatient")) { responses.push("Small talk? Really? Fine. Yes, the weather exists. The city is still standing. Congratulations on stating the obvious. There, happy?"); } else if (npc.mentalTraits.includes("Nerd") || npc.mentalTraits.includes("Intelligent")) { 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%. I could talk about city infrastructure for hours if you're interested."); } else if (npc.mentalTraits.includes("Nonchalant") || npc.mentalTraits.includes("Chill")) { responses.push("Yeah, things have been pretty normal. Same routine, you know? Can't complain. Life's just... happening."); } 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 to avoid the void of existence. But sure, the weather's fine, I guess."); } else if (npc.mentalTraits.includes("Jock")) { 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!"); } 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!"); } else { responses.push("Yeah, things have been pretty normal. Same old routine, you know? How about you? Anything interesting going on?"); } } 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. I'm not playing around. Try me and see what happens."); } 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."); } 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... *tears up* I think you should just go. Please."); } 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. You're going to have to try a LOT harder than that to actually hurt my feelings. Try harder next time."); } else if (npc.mentalTraits.includes("Shy") || npc.mentalTraits.includes("Insecure")) { responses.push("What? Why would you... *voice shaking* That's really mean... I... I need you to leave. Please. Just... just go..."); } else if (npc.mentalTraits.includes("Cold") || npc.mentalTraits.includes("Emotionless")) { responses.push("...Is that all? Are you done? Okay. Leave."); } 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? Please, spare me your brilliant wit."); } else { responses.push("What the hell? Why would you say that? Just... just leave me alone. Seriously."); } } else if (topic === "compliment") { 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..."); } 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."); } else if (npc.mentalTraits.includes("Confident")) { responses.push("Hey, thanks! I appreciate that!"); responses.push("That's kind of you to say. Thank you!"); } else if (npc.mentalTraits.includes("Friendly") || npc.mentalTraits.includes("Warm")) { responses.push("Aww, that's so sweet of you! Thank you so much!"); responses.push("You're so kind! That really made my day!"); } else { responses.push("Oh, thank you. That's nice of you to say."); responses.push("I appreciate that. Thanks."); } } 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."); } } // 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."); } } return responses[Math.floor(Math.random() * responses.length)]; }>> <<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; }>> /* ---------------------------------- */ /* --- 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?"); } } // Default fallback if (dialogues.length === 0) { dialogues.push("..."); } return dialogues[Math.floor(Math.random() * dialogues.length)]; }>> /* ---------------------------------- */ /* --- 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"], 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"] } }>> /* 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 if (setup.traitBonuses[newTrait]) { // Determine if physical or mental var physicalTraits = ["Fit", "Muscular", "Attractive"]; var mentalTraits = ["Confident", "Patient", "Optimistic", "Sarcastic", "Artistic", "Humorous", "Intelligent", "Analytical"]; if (physicalTraits.includes(newTrait)) { v.physicalTraits.push(newTrait); } else if (mentalTraits.includes(newTrait)) { v.mentalTraits.push(newTrait); } } else if (setup.skillBonuses[newTrait]) { v.skills.push(newTrait); } changes.push({type: "gain", trait: newTrait}); } } // 1% chance to upgrade existing traits if (Math.random() < 0.01) { for (var oldTrait in config.traitUpgrades) { if (setup.playerHasTrait(oldTrait)) { 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 var physicalTraits = ["Muscular"]; var mentalTraits = ["Chill"]; if (physicalTraits.includes(newTrait)) { v.physicalTraits.push(newTrait); } else if (mentalTraits.includes(newTrait)) { v.mentalTraits.push(newTrait); } else if (setup.skillBonuses[newTrait]) { v.skills.push(newTrait); } changes.push({type: "upgrade", oldTrait: oldTrait, newTrait: newTrait}); break; // Only one upgrade per work session } } } // 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 var physicalTraits = ["Fit", "Strong", "Muscular"]; var mentalTraits = ["Patient"]; if (physicalTraits.includes(positiveTrait)) { v.physicalTraits.push(positiveTrait); } else if (mentalTraits.includes(positiveTrait)) { v.mentalTraits.push(positiveTrait); } else if (setup.skillBonuses[positiveTrait]) { 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 to { common: { price: 500, chance: 0.90, traits: [ {trait: "Broad-shouldered", type: "physical"}, {trait: "Freckled", type: "physical"}, {trait: "Tattooed", type: "physical"}, {trait: "Deep Voice", type: "voice"}, {trait: "Emotionless Tone", type: "voice"}, {trait: "Grim Tone", type: "voice"}, {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"} ] }, uncommon: { price: 2000, chance: 0.20, traits: [ {trait: "Articulate Speech", type: "voice"}, {trait: "Submissive", type: "mental"}, {trait: "Sturdy", type: "physical"}, {trait: "Artistic", 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: "Perceptive", type: "mental"} ] }, aethereal: { price: 10000, chance: 0.01, traits: [ {trait: "Giant Chest", type: "physical"}, {trait: "Giant 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: "Occult Expert", type: "skill"} ] } }>> <<set setup.generateLampreyInventory to function() { var inventory = []; var guaranteedCommon = setup.lampreyTraits.common.traits.random(); inventory.push({ trait: guaranteedCommon.trait, type: guaranteedCommon.type, rarity: 'common', price: setup.lampreyTraits.common.price }); for (var i = 0; i < 3; i++) { var selectedRarity = null; var roll = Math.random(); if (roll < setup.lampreyTraits.legendary.chance) { selectedRarity = 'legendary'; } else if (roll < setup.lampreyTraits.aethereal.chance) { selectedRarity = 'aethereal'; } else if (roll < setup.lampreyTraits.rare.chance) { selectedRarity = 'rare'; } else if (roll < setup.lampreyTraits.uncommon.chance) { 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; }>> <<set setup.shouldRefreshLampreyInventory to function() { var currentDay = State.variables.dayNumber; var lastRefreshDay = State.variables.lampreyLastRefreshDay || -1; var currentHour = Math.floor(State.variables.timeInMinutes / 60) % 24; if (currentDay > lastRefreshDay && currentHour >= 12) { return true; } return false; }>> <<set setup.getRarityColor to function(rarity) { var colors = { common: '#aaa', uncommon: '#51cf66', rare: '#339af0', aethereal: '#b19cd9', legendary: '#ffd700' }; return colors[rarity] || '#aaa'; }>> <<set setup.getRarityName to function(rarity) { var names = { common: 'Common', uncommon: 'Uncommon', rare: 'Rare', aethereal: 'Aethereal', legendary: 'Legendary' }; return names[rarity] || 'Unknown'; }>> /* Handle special body part traits that modify appearance directly */ <<set setup.applyLampreyBodyTrait to function(trait) { var v = State.variables; // Handle chest size traits 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; } // Handle butt size traits 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; } return false; }>> <<set setup.hasLampreyTrait to function(trait) { var v = State.variables; // Check if it's a body part trait if (trait === "Giant Chest" || trait === "Huge Chest" || trait === "Large Chest" || trait === "Medium Chest" || trait === "Small Chest" || trait === "Flat Chest") { return false; // Always allow purchasing body part traits (they modify, not add) } if (trait === "Giant Butt" || trait === "Huge Butt" || trait === "Large Butt" || trait === "Medium Butt" || trait === "Small Butt" || trait === "Flat Butt") { return false; // Always allow purchasing body part traits (they modify, not add) } // Check regular traits return v.physicalTraits.includes(trait) || v.mentalTraits.includes(trait) || v.skills.includes(trait) || (v.voiceTraits && v.voiceTraits.includes(trait)); }>> <<set setup.addLampreyTrait to function(trait, type) { var v = State.variables; // 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 for traits */ <<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", "Giant Chest": "Tome of Magnificent Proportions", "Giant Butt": "Chronicle of Grand Curves", "Were-Creature": "Forbidden Bestiary", // 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", // Skills "Occult Expert": "Necronomicon Fragment" }>> <<set setup.getTraitTomeName = function(trait) { return setup.traitTomeNames[trait] || "Mysterious Tome of " + trait; }>> <<set setup.getLampreyDiscount = function() { var relationship = State.variables.relationships["Revna McKraken"] || {level: 1, points: 0}; var discounts = { 1: 0, // Stranger - no discount 2: 0.03, // Acquaintance - 3% discount 3: 0.07, // Friend - 7% discount 4: 0.12, // Close Friend - 12% discount 5: 0.20 // Lover - 20% discount }; return discounts[relationship.level] || 0; }>> <<set setup.calculateLampreyPrice = function(basePrice) { var discount = setup.getLampreyDiscount(); return Math.floor(basePrice * (1 - discount)); }>> <<set $hoursWorkedToday = 0>> <<set $lastWorkDay = 0>> <<set $lastWorkLocation = "">> <</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>> <<set $lastLocation = "OpahFitness">> <!-- 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>> <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> <!-- Workout 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;"> ⚡ Workouts Remaining Today: <span style="color: #ff6b6b;"><<print 3 - $gymWorkoutCount>> / 3</span> </div> <p style="color: #aaa; font-size: 14px; margin: 10px 0 0 0;"> Each workout takes 2 hours and focuses on specific attributes. </p> </div> <h2 style="color: #ff6b6b;">Workout Programs</h2> <<if $gymWorkoutCount >= 3>> <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 all your workouts 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;">+2 Strength</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 += 2>> <<set $gymWorkoutCount += 1>> <<advancetime 120>> <<goto "OpahFitness">> <</link>> <</if>> </div> <!-- Cardio Training --> <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;">+2 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 += 2>> <<set $gymWorkoutCount += 1>> <<advancetime 120>> <<goto "OpahFitness">> <</link>> <</if>> </div> <!-- 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;">+1 Strength, +1 Dexterity</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 += 1>> <</if>> <<if $stats.dexterity < $statMaxCaps.dexterity>> <<set $stats.dexterity += 1>> <</if>> <<set $gymWorkoutCount += 1>> <<advancetime 120>> <<goto "OpahFitness">> <</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: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px;"> <!-- 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;"> <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;"> <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;"> <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> <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> <</nobr>><<nobr>> <<set $lastLocation = "Cafe">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #8d6e63; text-align: center;">☕ Manta Ray Cafe</h1> <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;"> 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. </p> </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 --> <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 $money >= 5>> <<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 $money -= 5>> <<goto "CafeCoffee">> <</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 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.getNPCsByJob("Barista")>> <<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> <</nobr>><<nobr>> <<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: $1,500 (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> <p style="font-size: 14px; color: #aaa; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Pay next month's rent ($1,500) to extend your lease by 30 days.</p> <<if $money >= 1500>> <<link "<div style='background: #ffc107; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Pay $1,500</div>">> <<set $money -= 1500>> <<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>> </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;">$1,500</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>> <<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>> <<set $lastLocation = "DanceStudio">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ff6b9d; text-align: center;">🎀 Ribbonfish Dance Studio</h1> <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> <h2 style="color: #ff6b9d;">Dance Classes</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 20px; margin-bottom: 30px;"> <!-- Group Dance Lessons --> <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 auto 0;">Cost: $50</p> <<if $money >= 50>> <<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 $money -= 50>> <<goto "DanceGroupLesson">> <</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 --> <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 auto 0;">Cost: $200</p> <<if $money >= 200>> <<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 $money -= 200>> <<goto "DancePrivateLesson">> <</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 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> </div> <</nobr>><<nobr>> <<set $lastLocation = "TrainingCenter">> <!-- 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>> <!-- Initialize skill training progress --> <<if !$skillTrainingProgress>> <<set $skillTrainingProgress = { "Math Skills": {current: 0, required: 3, timesLearned: 0}, "Coding": {current: 0, required: 3, timesLearned: 0}, "Makeup": {current: 0, required: 3, timesLearned: 0}, "Cooking": {current: 0, required: 3, timesLearned: 0}, "Cleaning": {current: 0, required: 3, timesLearned: 0}, "First Aid": {current: 0, required: 3, timesLearned: 0}, "Painting": {current: 0, required: 3, timesLearned: 0} }>> <</if>> <!-- Adjust required values if player has Quick Learner and timesLearned is 0 --> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<if $skillTrainingProgress["Math Skills"].timesLearned === 0 && $skillTrainingProgress["Math Skills"].required === 3>> <<set $skillTrainingProgress["Math Skills"].required = 1>> <</if>> <<if $skillTrainingProgress["Coding"].timesLearned === 0 && $skillTrainingProgress["Coding"].required === 3>> <<set $skillTrainingProgress["Coding"].required = 1>> <</if>> <<if $skillTrainingProgress["Makeup"].timesLearned === 0 && $skillTrainingProgress["Makeup"].required === 3>> <<set $skillTrainingProgress["Makeup"].required = 1>> <</if>> <<if $skillTrainingProgress["Cooking"].timesLearned === 0 && $skillTrainingProgress["Cooking"].required === 3>> <<set $skillTrainingProgress["Cooking"].required = 1>> <</if>> <<if $skillTrainingProgress["Cleaning"].timesLearned === 0 && $skillTrainingProgress["Cleaning"].required === 3>> <<set $skillTrainingProgress["Cleaning"].required = 1>> <</if>> <<if $skillTrainingProgress["First Aid"].timesLearned === 0 && $skillTrainingProgress["First Aid"].required === 3>> <<set $skillTrainingProgress["First Aid"].required = 1>> <</if>> <<if $skillTrainingProgress["Painting"].timesLearned === 0 && $skillTrainingProgress["Painting"].required === 3>> <<set $skillTrainingProgress["Painting"].required = 1>> <</if>> <</if>> <!-- Initialize daily skill training tracker --> <<if !$dailySkillTraining>> <<set $dailySkillTraining = {day: $dayNumber, trained: false}>> <</if>> <!-- Reset daily skill training if new day --> <<if $dailySkillTraining.day !== $dayNumber>> <<set $dailySkillTraining = {day: $dayNumber, trained: false}>> <</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 5 - $trainingCount>> / 5</span> </div> <div style="color: #51cf66; font-size: 18px; font-weight: bold; margin-top: 10px;"> 📚 Skill Class Available Today: <span style="color: <<if $dailySkillTraining.trained>>#ff6b6b<<else>>#5c6bc0<</if>>;"> <<if $dailySkillTraining.trained>>Completed<<else>>Available<</if>> </span> </div> </div> <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 5 times per day.</p> <<if $trainingCount >= 5>> <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>> <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> <<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> <<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 $stats.charisma += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <<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> <<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> <<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 $stats.dexterity += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <<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> <<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> <<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 $stats.strength += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <<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> <<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> <<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 $stats.intelligence += 1>> <<set $trainingCount += 1>> <<advancetime 60>> <<goto "TrainingCenter">> <</link>> <</if>> </div> </div> <</if>> </div> <!-- Skill Courses --> <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;">Take one free class per day to learn professional skills. Complete classes to master a skill (8 hours per class).</p> <<if $dailySkillTraining.trained>> <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 completed your skill class for today. Come back tomorrow!</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;">Bonus: +5 Intelligence</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["Math Skills"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["Math Skills"].current >= $skillTrainingProgress["Math Skills"].required>> <<set $skills.push("Math Skills")>> <<set $stats.intelligence += 5>> <<set $skillTrainingProgress["Math Skills"].timesLearned += 1>> <<set $skillTrainingProgress["Math Skills"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["Math Skills"].required = Math.min(10, Math.max(1, $skillTrainingProgress["Math Skills"].timesLearned))>> <<else>> <<set $skillTrainingProgress["Math Skills"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["Math Skills"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<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;">Bonus: +6 Intelligence</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["Coding"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["Coding"].current >= $skillTrainingProgress["Coding"].required>> <<set $skills.push("Coding")>> <<set $stats.intelligence += 6>> <<set $skillTrainingProgress["Coding"].timesLearned += 1>> <<set $skillTrainingProgress["Coding"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["Coding"].required = Math.min(10, Math.max(1, $skillTrainingProgress["Coding"].timesLearned))>> <<else>> <<set $skillTrainingProgress["Coding"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["Coding"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<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;">Bonus: +3 Dexterity, +3 Charisma</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["Makeup"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["Makeup"].current >= $skillTrainingProgress["Makeup"].required>> <<set $skills.push("Makeup")>> <<set $stats.dexterity += 3>> <<set $stats.charisma += 3>> <<set $skillTrainingProgress["Makeup"].timesLearned += 1>> <<set $skillTrainingProgress["Makeup"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["Makeup"].required = Math.min(10, Math.max(1, $skillTrainingProgress["Makeup"].timesLearned))>> <<else>> <<set $skillTrainingProgress["Makeup"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["Makeup"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<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;">Bonus: +3 Intelligence, +2 Dexterity</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["Cooking"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["Cooking"].current >= $skillTrainingProgress["Cooking"].required>> <<set $skills.push("Cooking")>> <<set $stats.intelligence += 3>> <<set $stats.dexterity += 2>> <<set $skillTrainingProgress["Cooking"].timesLearned += 1>> <<set $skillTrainingProgress["Cooking"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["Cooking"].required = Math.min(10, Math.max(1, $skillTrainingProgress["Cooking"].timesLearned))>> <<else>> <<set $skillTrainingProgress["Cooking"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["Cooking"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<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;">Bonus: +3 Dexterity</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["Cleaning"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["Cleaning"].current >= $skillTrainingProgress["Cleaning"].required>> <<set $skills.push("Cleaning")>> <<set $stats.dexterity += 3>> <<set $skillTrainingProgress["Cleaning"].timesLearned += 1>> <<set $skillTrainingProgress["Cleaning"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["Cleaning"].required = Math.min(10, Math.max(1, $skillTrainingProgress["Cleaning"].timesLearned))>> <<else>> <<set $skillTrainingProgress["Cleaning"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["Cleaning"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<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;">Bonus: +4 Intelligence</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["First Aid"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["First Aid"].current >= $skillTrainingProgress["First Aid"].required>> <<set $skills.push("First Aid")>> <<set $stats.intelligence += 4>> <<set $skillTrainingProgress["First Aid"].timesLearned += 1>> <<set $skillTrainingProgress["First Aid"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["First Aid"].required = Math.min(10, Math.max(1, $skillTrainingProgress["First Aid"].timesLearned))>> <<else>> <<set $skillTrainingProgress["First Aid"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["First Aid"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<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;">Bonus: +4 Dexterity, +3 Intelligence</p> <</if>> <<if $dailySkillTraining.trained || _hasSkill>> <div style="background: #3a3a3a; color: #666; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; margin-top: auto;"> <<if _hasSkill>>Already Learned<<else>>Class Taken Today<</if>> </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)</div>">> <<set $skillTrainingProgress["Painting"].current += 1>> <<set $dailySkillTraining.trained = true>> <<if $skillTrainingProgress["Painting"].current >= $skillTrainingProgress["Painting"].required>> <<set $skills.push("Painting")>> <<set $stats.dexterity += 4>> <<set $stats.intelligence += 3>> <<set $skillTrainingProgress["Painting"].timesLearned += 1>> <<set $skillTrainingProgress["Painting"].current = 0>> <<if ($mentalTraits && $mentalTraits.includes("Quick Learner")) || ($characterCreationTrait && $characterCreationTrait === "Quick Learner")>> <<set $skillTrainingProgress["Painting"].required = Math.min(10, Math.max(1, $skillTrainingProgress["Painting"].timesLearned))>> <<else>> <<set $skillTrainingProgress["Painting"].required = Math.min(30, 3 * Math.pow(2, $skillTrainingProgress["Painting"].timesLearned))>> <</if>> <</if>> <<advancetime 480>> <<goto "TrainingCenter">> <</link>> <</if>> </div> </div> </div> <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> <</nobr>><<nobr>> <<set $lastLocation = "TownHall">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">🏛️ Town Hall</h1> <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> <<set _mayorNPCs = setup.getNPCsByJob("City Mayor")>> <<set _secretaryNPCs = setup.getNPCsByJob("Mayor's Secretary")>> <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]>> <<if setup.isNPCAvailable(_mayorNPC.name)>> <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;">The mayor is not available right now.</p> </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;">🎩 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]>> <<if setup.isNPCAvailable(_secretaryNPC.name)>> <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;">The secretary is not available right now.</p> </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;">📋 Secretary's Office</h3> <p style="font-size: 14px; color: #666;">No secretary currently appointed.</p> </div> <</if>> </div> <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>> <<if !_npc>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <p style="color: #ff6b6b;">Error: No NPC selected.</p> [[Go Back|$lastLocation]] </div> <<else>> <<set _relationship = $relationships[_npc.name] || {level: 1, points: 0}>> <<set _relLevel = _relationship.level>> <<set _npcPrefs = setup.getNPCPreferences(_npc)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header with Relationship Display --> <div style="background: #2a2a2a; 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 15px 0; font-size: 32px; text-align: center;">💬 Talking with _npc.name</h1> <!-- Relationship Level and XP Bar --> <<set _relColor = setup.getRelationshipColor(_relLevel)>> <div style="text-align: center; margin-bottom: 15px;"> <div style="color: #667eea; font-size: 18px; font-weight: bold; margin-bottom: 8px;"> Relationship: Level _relLevel </div> <!-- XP Progress Bar --> <<if _relLevel < 5>> <<set _nextThreshold = [10, 30, 60, 100][_relLevel - 1]>> <<set _currentLevelMin = [0, 10, 30, 60][_relLevel - 1]>> <<set _xpInLevel = _relationship.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <div style="background: #1a1a1a; border: 2px solid #51cf66; border-radius: 10px; height: 30px; position: relative; overflow: hidden;"> <div style="background: #51cf66; height: 100%; width: <<print _xpPercent>>%; transition: width 0.3s ease;"></div> <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-weight: bold; font-size: 14px; text-shadow: 1px 1px 2px rgba(0,0,0,0.8);"> <<print _xpInLevel>> / <<print _xpNeededForLevel>> XP </div> </div> <<else>> <div style="background: #1a1a1a; border: 2px solid #51cf66; border-radius: 10px; height: 30px; position: relative; overflow: hidden;"> <div style="background: #51cf66; height: 100%; width: 100%;"></div> <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-weight: bold; font-size: 14px; text-shadow: 1px 1px 2px rgba(0,0,0,0.8);"> MAX LEVEL </div> </div> <</if>> </div> </div> <!-- NPC's Initial Reaction based on your appearance --> <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;">_npc.name's Reaction</h3> <div style="color: #ccc; font-size: 16px; line-height: 1.8; font-style: italic;"> "<<print setup.getNPCGreeting(_npc, _relLevel)>>" </div> </div> <!-- Conversation Topics --> <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: 22px; border-bottom: 2px solid #17a2b8; padding-bottom: 10px;">💭 What do you want to talk about?</h3> <div style="display: grid; gap: 15px;"> <!-- Compliment them (increases relationship) --> <<link "<div style='background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #51cf66; cursor: pointer;'><span style='color: #51cf66; font-weight: bold;'>😊</span> <span style='color: #ccc;'>Give them a compliment</span></div>">> <<set $currentTopic = "compliment">> <<goto "NPCTalkResponse">> <</link>> <!-- Ask about your appearance --> <<link "<div style='background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #9b59b6; cursor: pointer;'><span style='color: #9b59b6; font-weight: bold;'>👤</span> <span style='color: #ccc;'>Ask what they think of you</span></div>">> <<set $currentTopic = "opinion">> <<goto "NPCTalkResponse">> <</link>> <!-- Small talk --> <<link "<div style='background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #667eea; cursor: pointer;'><span style='color: #667eea; font-weight: bold;'>☕</span> <span style='color: #ccc;'>Make small talk</span></div>">> <<set $currentTopic = "smalltalk">> <<goto "NPCTalkResponse">> <</link>> <!-- Ask about their job --> <<link "<div style='background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #17a2b8; cursor: pointer;'><span style='color: #17a2b8; font-weight: bold;'>💼</span> <span style='color: #ccc;'>Ask about their job</span></div>">> <<set $currentTopic = "job">> <<goto "NPCTalkResponse">> <</link>> <!-- Ask about trading preferences --> <<link "<div style='background: #1a1a1a; padding: 15px; border-radius: 8px; border: 2px solid #ffc107; cursor: pointer;'><span style='color: #ffc107; font-weight: bold;'>💱</span> <span style='color: #ccc;'>Ask what they're interested in trading</span></div>">> <<set $currentTopic = "trading">> <<goto "NPCTalkResponse">> <</link>> </div> </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>">> <<goto "NPCInteraction">> <</link>> </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.includes(_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: 20px; border: 2px solid #51cf66;"><p style="color: #51cf66; margin: 0; font-size: 16px; font-weight: bold;">You have currently chosen <span style="color: #ffc107;"><<print $selectedTraits.length>></span> out of 1 trait.</p></div><</replace>><</link>><<else>><<link "<span style='color: #51cf66; font-weight: bold; font-size: 16px;'>SELECT</span>">><<if $selectedTraits.length < $maxTraits>><<run $selectedTraits.push(_traitName)>><<replace "#trait-list">><<include "TraitListDisplay">><</replace>><<replace "#trait-counter">><div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 20px; border: 2px solid #51cf66;"><p style="color: #51cf66; margin: 0; font-size: 16px; font-weight: bold;">You have currently chosen <span style="color: #ffc107;"><<print $selectedTraits.length>></span> out of 1 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> <p style="font-size: 13px; color: #999; font-style: italic;">Coming soon...</p> </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", "Tan Skin", "Dark Skin", "Pale Skin", "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", "Immature", "Impatient", "Foolish", "Introverted", "Submissive", "Shy", "Aggressive", "Passive", "Pessimistic", "Stubborn", "Paranoid"]>> <!-- Filter out traits player already has --> <<set _availablePositivePhysical = []>> <<for _trait range _positivePhysical>> <<if !$physicalTraits.includes(_trait)>> <<run _availablePositivePhysical.push(_trait)>> <</if>> <</for>> <<set _availablePositiveMental = []>> <<for _trait range _positiveMental>> <<if !$mentalTraits.includes(_trait)>> <<run _availablePositiveMental.push(_trait)>> <</if>> <</for>> <<set _availableNegativePhysical = []>> <<for _trait range _negativePhysical>> <<if !$physicalTraits.includes(_trait)>> <<run _availableNegativePhysical.push(_trait)>> <</if>> <</for>> <<set _availableNegativeMental = []>> <<for _trait range _negativeMental>> <<if !$mentalTraits.includes(_trait)>> <<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 https://discord.gg/z9eDdQC6zA''Alpha Version: 0.0.11.1'' - Add more npc's - Bus stop will have 2 npc's not sure who yet - Add Job board and additional ways to make money such as gambling - Add a phone aswell as a help menu. Not sure if I'll make it an interactable image but I'll figure this out later - Add an inventory - Add new locations - Add talking to npc's and how they act depends on their current traits. - Add shopping - Add speical events that can happen during jobs - Show ideal stats for working your job - Add negative relationship - NPC's are no longer stationary - Add the ability to steal traits - Internal Monologue - The ability to sell positive traits for cash to wealthy NPC's like Dick Richardson (Once you sell these traits you cannot get them back and give a warning to the player) - Make tall the wip and coming soon passages have something in them.test code /* 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; } }); } } 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) { var preferences = setup.getNPCPreferences(npc); if (!preferences) return false; // Check "never trade" - things NPC won't give away if (preferences.neverTrade) { var neverTrade = preferences.neverTrade; if (neverTrade.name && playerPackage.name && playerPackage.name.length > 0) { return true; } if (neverTrade.job && playerPackage.job !== null && playerPackage.job !== undefined) { return true; } 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 "wont trade for" - things NPC won't accept from player 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 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 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; } } } } } return false; <<nobr>> <<set $lastLocation = "Brothel">> <!-- Initialize Brothel Work System --> <<if !$brothelLevel>> <<set $brothelLevel = 1>> <<set $brothelClients = 0>> <<set $brothelClientsToday = 0>> <<set $brothelLastWorkDay = 0>> <</if>> <!-- Reset daily client count if new day --> <<if $brothelLastWorkDay !== $dayNumber>> <<set $brothelClientsToday = 0>> <<set $brothelLastWorkDay = $dayNumber>> <</if>> <!-- Calculate max clients per day --> <<set _maxBrothelClients = 4>> <<if $skills.includes("Sexually Skilled")>> <<set _maxBrothelClients += 2>> <</if>> <<if $mentalTraits.includes("Energetic")>> <<set _maxBrothelClients += 2>> <</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"]>> <<set _brothelBonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait) || $skills.includes(_trait)>> <<set _brothelBonusMoney += 15>> <</if>> <</for>> <!-- Check for level up (silent) --> <<if $brothelLevel === 1 && $brothelClients >= 25>> <<set $brothelLevel = 2>> <<elseif $brothelLevel === 2 && $brothelClients >= 50>> <<set $brothelLevel = 3>> <<elseif $brothelLevel === 3 && $brothelClients >= 150>> <<set $brothelLevel = 4>> <<elseif $brothelLevel === 4 && $brothelClients >= 300>> <<set $brothelLevel = 5>> <</if>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #007FFF; text-align: center;">💋 Azure Angelfish Lounge</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;"> 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> <!-- Work Area (Only shows if player has Brothel Worker job) --> <<if $jobs && $jobs.length > 0 && $jobs.includes("Brothel Worker")>> <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);"> <!-- Level & Progress 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</h3> <p style="color: #ccc; margin: 0 0 5px 0;">Total Clients Served: $brothelClients</p> <p style="color: #ffc107; margin: 0;"> Today's Sessions: $brothelClientsToday / _maxBrothelClients <<if _brothelBonusMoney > 0>> <span style="color: #51cf66;"> (+$<<print _brothelBonusMoney>> per client from skills)</span> <</if>> </p> </div> <!-- Work Button --> <<if $brothelClientsToday >= _maxBrothelClients>> <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> </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</div>">> <<if $brothelLevel === 1>> <<goto "BrothelWorkLevel1">> <<elseif $brothelLevel === 2>> <<goto "BrothelWorkLevel2">> <<elseif $brothelLevel === 3>> <<goto "BrothelWorkLevel3">> <<elseif $brothelLevel === 4>> <<goto "BrothelWorkLevel4">> <<else>> <<goto "BrothelWorkLevel5">> <</if>> <</link>> </div> <</if>> </div> <</if>> <!-- NPCs Present --> <<set _brothelWorkers = setup.getNPCsByJob("Brothel Worker")>> <<set _brothelOwner = setup.getNPCsByJob("Brothel Owner")>> <<set _npcsHere = _brothelWorkers.concat(_brothelOwner)>> <<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>> <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">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9D00FF; text-align: center;">🪼 Electric Jelly Revue</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;"> Bass-heavy music throbs through the air as colorful lights pulse across the stage. Dancers move gracefully on chrome poles while patrons sip drinks and watch from plush booths. The atmosphere is electric with energy and anticipation. </p> </div> <h2 style="color: #9D00FF;">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; margin-bottom: 30px;"> <!-- VIP Lounge --> <<if $stripClubVIPMember>> <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;">👑 VIP Lounge</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 auto 0; line-height: 1.4;">Access the exclusive VIP area with private entertainment.</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;'>Enter VIP Lounge</div>">> <<goto "StripClubVIP">> <</link>> </div> <<else>> <div style="border: 3px solid #9D00FF; 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: #9D00FF; margin: 0 0 10px 0;">👑 VIP Lounge</h4> <p style="color: #aaa; font-size: 14px; margin: 0 0 10px 0; line-height: 1.4;">Exclusive access to private entertainment and premium services.</p> <p style="color: #FFD700; font-size: 16px; font-weight: bold; margin: 0 0 auto 0;">VIP Membership: $5,000</p> <<if $money >= 5000>> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Purchase VIP Membership</div>">> <<set $money -= 5000>> <<set $stripClubVIPMember = true>> <<goto "StripClub">> <</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> <</if>> </div> <!-- NPCs Present --> <<set _strippers = setup.getNPCsByJob("Stripper")>> <<set _bouncers = setup.getNPCsByJob("Bouncer")>> <<set _npcsHere = _strippers.concat(_bouncers)>> <<if _npcsHere && _npcsHere.length > 0>> <h2 style="color: #9D00FF; margin-top: 30px;">People Here</h2> <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(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _npcsHere>> <<capture _npc>> <div style="border: 3px solid #9D00FF; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9D00FF; 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: #9D00FF; 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: #9D00FF; 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;"> The club is quiet right now. No one is available. </p> </div> <</if>> <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 = "Casino">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">🎰 Silver Marlin</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 --> <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;">🎰 Slot Machines</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">Work in Progress</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Coming Soon</div> </div> <!-- Roulette --> <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;">🎡 Roulette</h3> <p style="font-size: 14px; color: #666; margin-bottom: 10px;">Work in Progress</p> <div style='background: #444; color: #888; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed;'>Coming Soon</div> </div> </div> <!-- NPCs Section --> <<set _casinoNPCs = []>> <<for _npc range $npcs>> <<set _hasCasinoJob = false>> <<if typeof _npc.jobs === "string">> <<if _npc.jobs === "Cocktail Waitress" || _npc.jobs === "Security Guard">> <<set _hasCasinoJob = true>> <</if>> <<elseif Array.isArray(_npc.jobs)>> <<if _npc.jobs.includes("Cocktail Waitress") || _npc.jobs.includes("Security Guard")>> <<set _hasCasinoJob = true>> <</if>> <</if>> <<if _hasCasinoJob>> <<run _casinoNPCs.push(_npc)>> <</if>> <</for>> <<if _casinoNPCs.length > 0>> <h2 style="color: #ffd700;">People Here</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);"> <p style="color: #ccc; font-size: 15px; margin: 0 0 15px 0; font-style: italic;"> Casino staff working the floor... </p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _casinoNPCs>> <<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);"> <h3 style="color: #ffd700; margin: 0 0 10px 0;">_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.includes("Cocktail Waitress") ? "Cocktail Waitress" : "Security Guard">> <em>_displayJob</em> <</if>> </p> <<link "<div style='background: #ffd700; color: #000; 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: #ffd700;">Casino Staff</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;"> No staff members are currently available. </p> </div> <</if>> <br><br> <br><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 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;"> <!-- Page Header --> <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; 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; font-size: 28px; text-align: center;">💬 Conversation with <<= _npc.name>></h1> </div> <!-- 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> <div style="color: #ccc; font-size: 17px; line-height: 1.8; font-style: italic;"> "<<print setup.getPlayerDialogue($currentTopic)>>" </div> </div> <!-- 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> <div style="color: #ccc; font-size: 17px; line-height: 1.8; font-style: italic;"> <<set _relationship = $relationships[_npc.name] || {level: 1, points: 0}>> <<set _relLevel = _relationship.level>> "<<print setup.getNPCResponse(_npc, $currentTopic, _relLevel)>>" </div> </div> <!-- Relationship Change - ONLY if not already talked today --> <<if !_alreadyTalkedToday>> <<set _pointsChange = setup.calculateTalkRelationshipChange(_npc, $currentTopic, _relLevel)>> <<if _pointsChange !== 0>> <<run setup.addRelationshipPoints(_npc.name, _pointsChange)>> <<set $dailyConversations[_npc.name] = $dayNumber>> <div style="background: <<if _pointsChange > 0>>#2a4a2a<<else>>#4a2a2a<</if>>; border: 2px solid <<if _pointsChange > 0>>#51cf66<<else>>#ff6b6b<</if>>; padding: 15px; border-radius: 8px; margin-bottom: 25px; text-align: center;"> <span style="color: <<if _pointsChange > 0>>#51cf66<<else>>#ff6b6b<</if>>; font-weight: bold; font-size: 16px;"> <<if _pointsChange > 0>> 💚 Relationship improved! (+<<= _pointsChange>> points) <<else>> 💔 Relationship worsened! (<<= _pointsChange>> points) <</if>> </span> </div> <</if>> <</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);'>← Back to Conversation</div>">> <<goto "NPCTalk">> <</link>> </div> </div> <</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>> <</silently>><<nobr>> <<set $lastLocation = "VIPLounge">> <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> <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 = $dayOrder.indexOf($dayOfWeek)>> <<set _nextDayIndex = (_currentDayIndex + 1) % 7>> <<set $dayOfWeek = $dayOrder[_nextDayIndex]>> /* Check if new week */ <<if $dayOfWeek === "Monday">> <<set $weekNumber += 1>> <</if>> /* Reset daily trades */ <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> /* Check if hair styling has expired */ <<if $hairStyleExpiry && $dayNumber >= $hairStyleExpiry>> <<set $appearance.hairStyle = "messy">> <<set $hairStyleExpiry = null>> <</if>> /* Reset time to morning */ <<set $timeInMinutes = 480>> /* Reset daily conversations */ <<set $dailyConversations = {}>> <</widget>><<nobr>> <<set $lastLocation = "StudioApartment">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center;">🏠 Your Studio Apartment</h1> <div style="padding: 20px; background: linear-gradient(135deg, #6c757d 0%, #495057 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #6c757d;"> <p style="color: white; font-size: 18px; margin: 0;"> A cramped but functional studio apartment. The single room serves as bedroom, living room, and kitchenette all in one. The furniture is basic and worn, but it's yours. A small window overlooks the alley below. At least you're not on the streets. </p> </div> <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;"> <!-- Bed - Sleep Option --> <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;">🛏️ Bed</h3> <p style="font-size: 14px; color: #ccc; margin: 0 0 auto 0; line-height: 1.4; flex-grow: 1;">Get some rest and sleep. You can sleep up to 12 hours.</p> <<link "<div style='background: #51cf66; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; margin-top: 10px;'>Sleep</div>">> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #51cf66; margin-top: 0;">😴 How long do you want to sleep?</h2> <p style="color: #ccc; margin-bottom: 15px;">Enter hours (max 12):</p> <input type="number" id="rest-time-input" min="1" max="12" value="8" style="width: 100px; padding: 8px; font-size: 16px; text-align: center; border: 2px solid #51cf66; border-radius: 5px; background: #2a2a2a; color: white;"> <div style="margin-top: 20px;"> <<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>> <<run advanceTime(_restHours * 60)>> <<run Dialog.close()>> <<goto "StudioApartment">> <</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> <!-- 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> <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> <!-- 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>">> <<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>> </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>">> <<goto "StudioBathroom">> <</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>> <<set $lastLocation = "BasicApartment">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #51cf66; text-align: center;">🏠 Your Basic Apartment</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 decent one-bedroom apartment with separate living and sleeping areas. The furniture is mass-produced but serviceable. A small kitchen lets you cook your own meals, and the bathroom has a proper shower. Windows provide natural light and a view of the street below. It's not fancy, but it's comfortable enough. </p> </div> <h2 style="color: #51cf66;">Apartment Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Rest Option --> <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;">😴 Rest</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 15px;">Sleep and recover. Basic apartments allow up to 8 hours of rest.</p> <div style="text-align: center;"> <<link "Rest">> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #17a2b8; margin-top: 0;">How long do you want to rest?</h2> <p style="color: #ccc; margin-bottom: 15px;">Enter hours (max 8):</p> <input type="number" id="rest-time-input" min="1" max="8" value="4" style="width: 100px; padding: 8px; font-size: 16px; text-align: center; border: 2px solid #17a2b8; border-radius: 5px; background: #2a2a2a; color: white;"> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #17a2b8; 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 > 8 || Number.isNaN(_restHours)>> <<set _restHours = 4>> <</if>> <<set $timeInMinutes += (_restHours * 60)>> <<if $timeInMinutes >= 1440>> <<set $timeInMinutes -= 1440>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<if _currentDayIndex < $dayOrder.length - 1>> <<set $dayOfWeek = $dayOrder[_currentDayIndex + 1]>> <<else>> <<set $dayOfWeek = $dayOrder[0]>> <<set $weekNumber += 1>> <</if>> <<set $dayNumber += 1>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> /* Check if hair styling has expired */ <<if $hairStyleExpiry && $dayNumber >= $hairStyleExpiry>> <<set $appearance.hairStyle = "messy">> <<set $hairStyleExpiry = null>> <</if>> <</if>> <<run Dialog.close()>> <<goto "BasicApartment">> <</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> <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 = "FancyApartment">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffc107; text-align: center;">✨ Your Fancy Apartment</h1> <div style="padding: 20px; background: linear-gradient(135deg, #ffc107 0%, #ff9800 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #ffc107;"> <p style="color: white; font-size: 18px; margin: 0;"> A spacious two-bedroom apartment with modern furnishings and upscale amenities. Hardwood floors gleam under recessed lighting. The kitchen features stainless steel appliances and granite countertops. Large windows offer excellent city views. A comfortable couch faces a wall-mounted flat screen TV. The master bedroom has an en-suite bathroom with a luxurious shower. This is proper middle-class living. </p> </div> <h2 style="color: #ffc107;">Apartment Actions</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Rest Option --> <div style="border: 3px solid #ffc107; border-radius: 10px; padding: 15px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #ffc107; margin: 0 0 10px 0;">😴 Rest</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 15px;">Sleep and recover. Fancy apartments allow up to 12 hours of rest.</p> <div style="text-align: center;"> <<link "Rest">> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #ffc107; margin-top: 0;">How long do you want to rest?</h2> <p style="color: #ccc; margin-bottom: 15px;">Enter hours (max 12):</p> <input type="number" id="rest-time-input" min="1" max="12" value="8" style="width: 100px; padding: 8px; font-size: 16px; text-align: center; border: 2px solid #ffc107; border-radius: 5px; background: #2a2a2a; color: white;"> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #ffc107; color: #000; 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>> <<set $timeInMinutes += (_restHours * 60)>> <<while $timeInMinutes >= 1440>> <<set $timeInMinutes -= 1440>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<if _currentDayIndex < $dayOrder.length - 1>> <<set $dayOfWeek = $dayOrder[_currentDayIndex + 1]>> <<else>> <<set $dayOfWeek = $dayOrder[0]>> <<set $weekNumber += 1>> <</if>> <<set $dayNumber += 1>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> /* Check if hair styling has expired */ <<if $hairStyleExpiry && $dayNumber >= $hairStyleExpiry>> <<set $appearance.hairStyle = "messy">> <<set $hairStyleExpiry = null>> <</if>> <</while>> <<run Dialog.close()>> <<goto "FancyApartment">> <</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> <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 = "PenthouseApartment">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #9b59b6; text-align: center;">👑 Your Penthouse</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;"> An opulent penthouse suite occupying the entire top floor. Floor-to-ceiling windows provide breathtaking panoramic views of Sunfish City. Designer furniture, original artwork, and imported materials throughout. The gourmet kitchen could host a cooking show. Multiple bedrooms each with their own luxurious bathrooms. A private balcony with hot tub overlooks the city lights. This is how the elite live. </p> </div> <h2 style="color: #9b59b6;">Penthouse Amenities</h2> <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 20px;"> <!-- Rest Option --> <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;">😴 Rest</h3> <p style="font-size: 14px; color: #ccc; margin-bottom: 15px;">Sleep and recover in luxury. Penthouses allow rest for any duration up to 24 hours.</p> <div style="text-align: center;"> <<link "Rest">> <<popover 'noclick'>> <div style="padding: 20px; text-align: center; background: #1a1a1a; border-radius: 10px;"> <h2 style="color: #9b59b6; margin-top: 0;">How long do you want to rest?</h2> <p style="color: #ccc; margin-bottom: 15px;">Enter hours (max 24):</p> <input type="number" id="rest-time-input" min="1" max="24" value="8" style="width: 100px; padding: 8px; font-size: 16px; text-align: center; border: 2px solid #9b59b6; border-radius: 5px; background: #2a2a2a; color: white;"> <div style="margin-top: 20px;"> <<link "<div style='display: inline-block; background: #9b59b6; 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 > 24 || Number.isNaN(_restHours)>> <<set _restHours = 8>> <</if>> <<set $timeInMinutes += (_restHours * 60)>> <<while $timeInMinutes >= 1440>> <<set $timeInMinutes -= 1440>> <<set _currentDayIndex = $dayOrder.indexOf($dayOfWeek)>> <<if _currentDayIndex < $dayOrder.length - 1>> <<set $dayOfWeek = $dayOrder[_currentDayIndex + 1]>> <<else>> <<set $dayOfWeek = $dayOrder[0]>> <<set $weekNumber += 1>> <</if>> <<set $dayNumber += 1>> <<set $tradesRemainingToday = 5>> <<set $failedTradesWithToday = []>> /* Check if hair styling has expired */ <<if $hairStyleExpiry && $dayNumber >= $hairStyleExpiry>> <<set $appearance.hairStyle = "messy">> <<set $hairStyleExpiry = null>> <</if>> <</while>> <<run Dialog.close()>> <<goto "PenthouseApartment">> <</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> <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>> <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> <<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: _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: _change.oldTrait → _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: _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: _change.oldTrait → _change.newTrait</p> </div> <</if>> <</for>> </div> <</if>> <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 Summary</h2> <div style="background: #1a1a1a; padding: 20px; border-radius: 8px; margin-top: 15px;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 15px;"> <div> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Hours Worked:</p> <p style="color: #fff; margin: 0; font-size: 24px; font-weight: bold;"><<print $lastWorkHours>> hours</p> </div> <div> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Money Earned:</p> <p style="color: #28a745; margin: 0; font-size: 24px; font-weight: bold;"><<print setup.formatMoney($lastWorkEarnings)>></p> </div> </div> <hr style="border: 0; border-top: 1px solid #666; margin: 15px 0;"> <div style="text-align: center;"> <p style="color: #aaa; margin: 0 0 5px 0; font-size: 14px;">Total Money:</p> <p style="color: #51cf66; margin: 0; font-size: 28px; font-weight: bold;"><<print setup.formatMoney($money)>></p> </div> </div> <div style="background: #3a3020; border: 2px solid #ffc107; padding: 15px; border-radius: 8px; margin-top: 15px;"> <p style="color: #ffc107; margin: 0; text-align: center; font-size: 14px;"> ⏰ <strong>New Time:</strong> <<= getTimeString()>> - $dayOfWeek </p> </div> <div style="background: #1a1a1a; padding: 15px; border-radius: 8px; margin-top: 15px; border: 2px solid #17a2b8;"> <p style="color: #17a2b8; margin: 0; text-align: center; font-size: 14px;"> 📊 <strong>Hours Worked Today:</strong> <<print $hoursWorkedToday>> / 8 </p> </div> </div> <div style="background: #2a2a2a; padding: 20px; border-radius: 12px; border: 3px solid #3498db; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <p style="color: #ccc; margin: 0; font-size: 16px; line-height: 1.6;"> You spent the last <<print $lastWorkHours>> hours working hard at your job. The shift was tiring but the pay makes it worthwhile. </p> </div> <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);'>Continue</div>">> <<goto $lastWorkLocation>> <</link>> </div> </div> <</nobr>>Quick Learner has no value. <<nobr>> <<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> <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> <!-- 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>">> <<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>> <<set $lastLocation = "MirrorView">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <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> <!-- 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 = setup.gender.pronouns().noun>> <<elseif $bodyParts.gender === "male">> <<set _genderWord = "masculine">> <<set _pronounNoun = setup.gender.pronouns().noun>> <<else>> <<set _genderWord = "androgynous">> <<set _pronounNoun = setup.gender.pronouns().noun>> <</if>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0 0 15px 0;"> You look and see <<a _genderWord>> <<print _pronounNoun>> staring back at you in the mirror. </p> <<set _chestDescription = "">> <<if $bodyParts.chest === "flat masculine">> <<set _chestDescription = "You have a flat, masculine chest.">> <<elseif $bodyParts.chest === "flat">> <<set _chestDescription = "You have flat breasts.">> <<elseif $bodyParts.chest === "small">> <<set _chestDescription = "You have small breasts.">> <<elseif $bodyParts.chest === "medium">> <<set _chestDescription = "You have medium-sized breasts.">> <<elseif $bodyParts.chest === "large">> <<set _chestDescription = "You have large breasts.">> <<elseif $bodyParts.chest === "huge">> <<set _chestDescription = "You have huge breasts.">> <<elseif $bodyParts.chest === "giant">> <<set _chestDescription = "You have giant breasts.">> <<else>> <<set _chestDescription = "You have a chest.">> <</if>> <p style="color: #ccc; font-size: 16px; line-height: 1.8; margin: 0;"> <<print _chestDescription>> </p> </div> <!-- Image Display Section --> <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> <!-- 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;"><<print $appearance.hairStyle>></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> <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 Bathroom</div>">> <<goto "StudioBathroom">> <</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>> <!-- Random client gender --> <<set _clientGender = either("male", "female")>> <<set _playerGender = $bodyParts.gender>> <!-- Calculate earnings --> <<set _basePay = random(50, 125)>> <<set _brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _bonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait) || $skills.includes(_trait)>> <<set _bonusMoney += 15>> <</if>> <</for>> <<set _brothelNegativeTraits = ["Ugly", "Scarred", "Plain", "Blemished", "Overweight", "Underweight", "Stubborn", "Paranoid", "Jealous", "Dull", "Immature"]>> <<set _penaltyPercent = 0>> <<for _trait range _brothelNegativeTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait)>> <<set _penaltyPercent += 10>> <</if>> <</for>> <!-- Calculate stat penalty (charisma requirement: 35) --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _statMultiplier = 1.0>> <<if _totalCharisma < 35>> <<set _statMultiplier = _totalCharisma / 35>> <<if _statMultiplier < 0>> <<set _statMultiplier = 0>> <</if>> <</if>> <!-- Apply all multipliers --> <<set _penaltyMultiplier = 1.0 - (_penaltyPercent / 100)>> <<set _totalPay = Math.round(_basePay * _statMultiplier * _penaltyMultiplier) + _bonusMoney>> <<set $money += _totalPay>> <!-- Increment counters --> <<set $brothelClients += 1>> <<set $brothelClientsToday += 1>> <!-- Handle trait gain (15% chance) --> <<set _gainedTrait = "">> <<set _traitGained = false>> <<if random(1, 100) <= 15>> <<set _possibleGains = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _availableGains = []>> <<for _gain range _possibleGains>> <<if !$mentalTraits.includes(_gain) && !$physicalTraits.includes(_gain) && !$skills.includes(_gain)>> <<run _availableGains.push(_gain)>> <</if>> <</for>> <<if _availableGains.length > 0>> <<set _gainedTrait = _availableGains[random(0, _availableGains.length - 1)]>> <<set _traitGained = true>> <<if _gainedTrait === "Dominant" || _gainedTrait === "Submissive">> <<if _gainedTrait === "Dominant">> <<set $mentalTraits.delete("Submissive")>> <<else>> <<set $mentalTraits.delete("Dominant")>> <</if>> <<set $mentalTraits.push(_gainedTrait)>> <<elseif _gainedTrait === "Dancing" || _gainedTrait === "High Heels Proficient" || _gainedTrait === "Sexually Skilled" || _gainedTrait === "Serving" || _gainedTrait === "Persuasion">> <<set $skills.push(_gainedTrait)>> <<else>> <<set $mentalTraits.push(_gainedTrait)>> <</if>> <</if>> <</if>> <!-- Advance time --> <<advancetime 60>> <!-- Select random scene --> <<set _sceneNumber = random(1, 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Client Session</h1> <<if _clientGender === "male" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A nervous man in rumpled work clothes enters, clearly inexperienced. You keep things simple and professional, guiding him through the basics without making him feel judged. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A young man in casual clothes looks uncertain. You take the lead, making him comfortable as you provide straightforward service. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An older gentleman in worn but clean clothes requests something basic. You accommodate his needs with practiced ease. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A shy client barely makes eye contact. You work efficiently, making the experience as smooth as possible for both of you. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A regular in cheap cologne comes in for a quick session. You know exactly what he likes by now and deliver without fuss. </p> </div> <</if>> <</if>> <<if _clientGender === "male" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A shy man in a modest suit fumbles with his wallet. You put him at ease with gentle touches and reassuring words, making his first time memorable. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A young professional looks uncertain. You guide him gently, making sure he enjoys every moment of the experience. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An older man with calloused hands requests traditional service. You provide exactly what he needs with developing skill. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A nervous client barely speaks. You take control gently, leading him through the experience with patient care. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A regular customer returns, smelling of cigarettes and cheap aftershave. You greet him warmly and deliver the familiar service he craves. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A tired woman in office attire arrives after a long shift. You help her unwind with patient attention, learning what she needs. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A woman in simple clothes knows what she wants. You provide exactly what she's paying for without unnecessary flourish. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An older woman seeks comfort and attention. You give her the care and intimacy she deserves. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A first-time client seems nervous, fidgeting with her purse. You make her comfortable and ensure she enjoys the experience. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A regular returns wearing her work uniform. You've learned exactly how to please her over these sessions. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A stressed woman still wearing her name tag sits nervously. You make her comfortable, slowly helping her relax and enjoy the experience. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A confident woman in casual wear knows what she wants. You deliver with enthusiasm, learning as you go. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An older woman seeks companionship and pleasure. You provide both generously, adapting to her pace. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A curious first-timer seems hesitant. You guide her through the experience with patience and gentle encouragement. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A regular returns, eager for your attention. You know just how to satisfy her by now. </p> </div> <</if>> <</if>> <!-- Earnings Display --> <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;">💰 Session Complete</h2> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0;">Base Payment: $<<print _basePay>></p> <<if _statMultiplier < 1.0>> <<set _statPenaltyPercent = Math.round((1.0 - _statMultiplier) * 100)>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Charisma Penalty: -<<print _statPenaltyPercent>>% (<<print _totalCharisma>>/35)</p> <</if>> <<if _penaltyPercent > 0>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Negative Traits Penalty: -<<print _penaltyPercent>>%</p> <</if>> <<if _bonusMoney > 0>> <p style="color: #ffc107; font-size: 16px; margin: 0 0 10px 0;">Skill Bonus: +$<<print _bonusMoney>></p> <</if>> <p style="color: #51cf66; font-size: 20px; margin: 0; font-weight: bold;">Total Earned: $<<print _totalPay>></p> </div> <!-- Trait Gained Notification --> <<if _traitGained>> <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: 0; text-align: center;">✨ NEW TRAIT ACQUIRED! ✨</h2> <p style="color: #9b59b6; font-size: 18px; margin: 10px 0 0 0; text-align: center; font-weight: bold;">_gainedTrait</p> <p style="color: #ccc; font-size: 14px; margin: 5px 0 0 0; text-align: center;">Your experiences have shaped you.</p> </div> <</if>> <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);'>Return to Lounge</div>">> <<goto "Brothel">> <</link>> </div> </div> <</nobr>><<nobr>> <!-- Random client gender --> <<set _clientGender = either("male", "female")>> <<set _playerGender = $bodyParts.gender>> <!-- Calculate earnings --> <<set _basePay = random(100, 325)>> <<set _brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _bonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait) || $skills.includes(_trait)>> <<set _bonusMoney += 15>> <</if>> <</for>> <<set _brothelNegativeTraits = ["Ugly", "Scarred", "Plain", "Blemished", "Overweight", "Underweight", "Stubborn", "Paranoid", "Jealous", "Dull", "Immature"]>> <<set _penaltyPercent = 0>> <<for _trait range _brothelNegativeTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait)>> <<set _penaltyPercent += 10>> <</if>> <</for>> <!-- Calculate stat penalty (charisma requirement: 35) --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _statMultiplier = 1.0>> <<if _totalCharisma < 35>> <<set _statMultiplier = _totalCharisma / 35>> <<if _statMultiplier < 0>> <<set _statMultiplier = 0>> <</if>> <</if>> <!-- Apply all multipliers --> <<set _penaltyMultiplier = 1.0 - (_penaltyPercent / 100)>> <<set _totalPay = Math.round(_basePay * _statMultiplier * _penaltyMultiplier) + _bonusMoney>> <<set $money += _totalPay>> <!-- Increment counters --> <<set $brothelClients += 1>> <<set $brothelClientsToday += 1>> <!-- Handle trait gain (15% chance) --> <<set _gainedTrait = "">> <<set _traitGained = false>> <<if random(1, 100) <= 15>> <<set _possibleGains = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _availableGains = []>> <<for _gain range _possibleGains>> <<if !$mentalTraits.includes(_gain) && !$physicalTraits.includes(_gain) && !$skills.includes(_gain)>> <<run _availableGains.push(_gain)>> <</if>> <</for>> <<if _availableGains.length > 0>> <<set _gainedTrait = _availableGains[random(0, _availableGains.length - 1)]>> <<set _traitGained = true>> <<if _gainedTrait === "Dominant" || _gainedTrait === "Submissive">> <<if _gainedTrait === "Dominant">> <<set $mentalTraits.delete("Submissive")>> <<else>> <<set $mentalTraits.delete("Dominant")>> <</if>> <<set $mentalTraits.push(_gainedTrait)>> <<elseif _gainedTrait === "Dancing" || _gainedTrait === "High Heels Proficient" || _gainedTrait === "Sexually Skilled" || _gainedTrait === "Serving" || _gainedTrait === "Persuasion">> <<set $skills.push(_gainedTrait)>> <<else>> <<set $mentalTraits.push(_gainedTrait)>> <</if>> <</if>> <</if>> <!-- Advance time --> <<advancetime 60>> <!-- Select random scene --> <<set _sceneNumber = random(1, 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Client Session</h1> <<if _clientGender === "male" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-dressed professional in designer clothes arrives with specific requests. You meet his expectations with growing confidence and skill. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A demanding client in polished shoes pushes your limits. You rise to the challenge, impressing him with your developing technique. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A man wearing a nice watch wants the full experience. You provide professional service with added flair. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A repeat customer specifically asks for you. Your reputation is growing, and it shows in his satisfaction. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-groomed man in business casual wants something memorable. You show him why clients are starting to ask for you by name. </p> </div> <</if>> <</if>> <<if _clientGender === "male" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A confident man in expensive casual wear knows what he wants. You deliver with practiced technique, earning a generous tip. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A demanding client tests your abilities. You prove yourself capable and eager to please, leaving him impressed. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A man in designer cologne expects excellence. You deliver professional intimacy with growing expertise. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A repeat customer becomes a regular. He clearly appreciates your improving technique. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-off client wants something special. You ensure he'll remember this experience and come back for more. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A stylish woman with expensive jewelry wants more than conversation. You provide attentive service, noting her preferences for next time. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A client in designer clothing requests specific roleplay. Your acting skills are improving with each session. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-dressed woman expects quality service. You deliver professional intimacy with added skill. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A repeat customer becomes your regular. She clearly appreciates your growing expertise. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A confident woman in heels wants to relax. You ensure she leaves satisfied and eager to book again. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A poised woman in tailored clothing requests something special. Your developing skills leave her satisfied and eager to return. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A client in expensive perfume wants intimate roleplay. You lose yourself in the performance, impressing her. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-off woman expects perfection. You deliver with practiced sensuality and growing confidence. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A repeat customer becomes your regular. She can't get enough of your improving technique. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A stylish woman wants the full experience. You show her pleasure she won't forget, earning her loyalty. </p> </div> <</if>> <</if>> <!-- Earnings Display --> <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;">💰 Session Complete</h2> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0;">Base Payment: $<<print _basePay>></p> <<if _statMultiplier < 1.0>> <<set _statPenaltyPercent = Math.round((1.0 - _statMultiplier) * 100)>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Charisma Penalty: -<<print _statPenaltyPercent>>% (<<print _totalCharisma>>/35)</p> <</if>> <<if _penaltyPercent > 0>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Negative Traits Penalty: -<<print _penaltyPercent>>%</p> <</if>> <<if _bonusMoney > 0>> <p style="color: #ffc107; font-size: 16px; margin: 0 0 10px 0;">Skill Bonus: +$<<print _bonusMoney>></p> <</if>> <p style="color: #51cf66; font-size: 20px; margin: 0; font-weight: bold;">Total Earned: $<<print _totalPay>></p> </div> <!-- Trait Gained Notification --> <<if _traitGained>> <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: 0; text-align: center;">✨ NEW TRAIT ACQUIRED! ✨</h2> <p style="color: #9b59b6; font-size: 18px; margin: 10px 0 0 0; text-align: center; font-weight: bold;">_gainedTrait</p> <p style="color: #ccc; font-size: 14px; margin: 5px 0 0 0; text-align: center;">Your experiences have shaped you.</p> </div> <</if>> <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);'>Return to Lounge</div>">> <<goto "Brothel">> <</link>> </div> </div> <</nobr>><<nobr>> <!-- Random client gender --> <<set _clientGender = either("male", "female")>> <<set _playerGender = $bodyParts.gender>> <!-- Calculate earnings --> <<set _basePay = random(125, 750)>> <<set _brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _bonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait) || $skills.includes(_trait)>> <<set _bonusMoney += 15>> <</if>> <</for>> <<set _brothelNegativeTraits = ["Ugly", "Scarred", "Plain", "Blemished", "Overweight", "Underweight", "Stubborn", "Paranoid", "Jealous", "Dull", "Immature"]>> <<set _penaltyPercent = 0>> <<for _trait range _brothelNegativeTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait)>> <<set _penaltyPercent += 10>> <</if>> <</for>> <!-- Calculate stat penalty (charisma requirement: 35) --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _statMultiplier = 1.0>> <<if _totalCharisma < 35>> <<set _statMultiplier = _totalCharisma / 35>> <<if _statMultiplier < 0>> <<set _statMultiplier = 0>> <</if>> <</if>> <!-- Apply all multipliers --> <<set _penaltyMultiplier = 1.0 - (_penaltyPercent / 100)>> <<set _totalPay = Math.round(_basePay * _statMultiplier * _penaltyMultiplier) + _bonusMoney>> <<set $money += _totalPay>> <!-- Increment counters --> <<set $brothelClients += 1>> <<set $brothelClientsToday += 1>> <!-- Handle trait gain (15% chance) --> <<set _gainedTrait = "">> <<set _traitGained = false>> <<if random(1, 100) <= 15>> <<set _possibleGains = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _availableGains = []>> <<for _gain range _possibleGains>> <<if !$mentalTraits.includes(_gain) && !$physicalTraits.includes(_gain) && !$skills.includes(_gain)>> <<run _availableGains.push(_gain)>> <</if>> <</for>> <<if _availableGains.length > 0>> <<set _gainedTrait = _availableGains[random(0, _availableGains.length - 1)]>> <<set _traitGained = true>> <<if _gainedTrait === "Dominant" || _gainedTrait === "Submissive">> <<if _gainedTrait === "Dominant">> <<set $mentalTraits.delete("Submissive")>> <<else>> <<set $mentalTraits.delete("Dominant")>> <</if>> <<set $mentalTraits.push(_gainedTrait)>> <<elseif _gainedTrait === "Dancing" || _gainedTrait === "High Heels Proficient" || _gainedTrait === "Sexually Skilled" || _gainedTrait === "Serving" || _gainedTrait === "Persuasion">> <<set $skills.push(_gainedTrait)>> <<else>> <<set $mentalTraits.push(_gainedTrait)>> <</if>> <</if>> <</if>> <!-- Advance time --> <<advancetime 60>> <!-- Select random scene --> <<set _sceneNumber = random(1, 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Client Session</h1> <<if _clientGender === "male" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A man steps out of a luxury car, gold watch gleaming. He's clearly used to the finer things, and you've learned how to deliver them. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A client in tailored clothing arrives with a thick wad of cash. Your reputation has spread, and he wants an extended session. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone well-connected specifically requested you. His expensive tastes are met with your mastered technique. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A demanding client in designer everything tests your limits. You exceed every expectation with skill and confidence. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy regular books you for the night. Your mastery of the craft is evident in every touch. </p> </div> <</if>> <</if>> <<if _clientGender === "male" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A client in an Italian suit arrives with champagne. Your reputation has spread, and he specifically requested you by name. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-off client wants an extended private session. You provide unforgettable pleasure that justifies the premium rate. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone influential arrives in an expensive car. You give him an experience worthy of his status. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A demanding client pushes your abilities. You prove why you're becoming one of the establishment's stars. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy regular reserves you for the entire evening. Your expertise speaks for itself. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: #e91e63; margin: 0;"> A woman dripping in designer labels wants to be in control. You play your part perfectly, understanding the psychology of power. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-connected woman wants elaborate roleplay. Your performance is flawless, and she tips generously. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone with expensive tastes seeks your specific talents. Your reputation has spread through exclusive circles. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A demanding client gets more than she paid for. You're at the peak of your abilities. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy woman becomes addicted to your services. You've perfected your craft. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A stunning woman in haute couture expects excellence. You've mastered your craft well enough to exceed even her high standards. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-off client wants elaborate fantasy fulfillment. You bring her deepest desires to life with practiced skill. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone influential seeks you specifically. Your name is whispered in exclusive circles. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A demanding client is left breathless. You've become irreplaceable to her. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy woman books you exclusively. You've mastered every technique she craves. </p> </div> <</if>> <</if>> <!-- Earnings Display --> <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;">💰 Session Complete</h2> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0;">Base Payment: $<<print _basePay>></p> <<if _statMultiplier < 1.0>> <<set _statPenaltyPercent = Math.round((1.0 - _statMultiplier) * 100)>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Charisma Penalty: -<<print _statPenaltyPercent>>% (<<print _totalCharisma>>/35)</p> <</if>> <<if _penaltyPercent > 0>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Negative Traits Penalty: -<<print _penaltyPercent>>%</p> <</if>> <<if _bonusMoney > 0>> <p style="color: #ffc107; font-size: 16px; margin: 0 0 10px 0;">Skill Bonus: +$<<print _bonusMoney>></p> <</if>> <p style="color: #51cf66; font-size: 20px; margin: 0; font-weight: bold;">Total Earned: $<<print _totalPay>></p> </div> <!-- Trait Gained Notification --> <<if _traitGained>> <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: 0; text-align: center;">✨ NEW TRAIT ACQUIRED! ✨</h2> <p style="color: #9b59b6; font-size: 18px; margin: 10px 0 0 0; text-align: center; font-weight: bold;">_gainedTrait</p> <p style="color: #ccc; font-size: 14px; margin: 5px 0 0 0; text-align: center;">Your experiences have shaped you.</p> </div> <</if>> <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);'>Return to Lounge</div>">> <<goto "Brothel">> <</link>> </div> </div> <</nobr>><<nobr>> <!-- Random client gender --> <<set _clientGender = either("male", "female")>> <<set _playerGender = $bodyParts.gender>> <!-- Calculate earnings --> <<set _basePay = random(250, 1500)>> <<set _brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _bonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait) || $skills.includes(_trait)>> <<set _bonusMoney += 15>> <</if>> <</for>> <<set _brothelNegativeTraits = ["Ugly", "Scarred", "Plain", "Blemished", "Overweight", "Underweight", "Stubborn", "Paranoid", "Jealous", "Dull", "Immature"]>> <<set _penaltyPercent = 0>> <<for _trait range _brothelNegativeTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait)>> <<set _penaltyPercent += 10>> <</if>> <</for>> <!-- Calculate stat penalty (charisma requirement: 35) --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _statMultiplier = 1.0>> <<if _totalCharisma < 35>> <<set _statMultiplier = _totalCharisma / 35>> <<if _statMultiplier < 0>> <<set _statMultiplier = 0>> <</if>> <</if>> <!-- Apply all multipliers --> <<set _penaltyMultiplier = 1.0 - (_penaltyPercent / 100)>> <<set _totalPay = Math.round(_basePay * _statMultiplier * _penaltyMultiplier) + _bonusMoney>> <<set $money += _totalPay>> <!-- Increment counters --> <<set $brothelClients += 1>> <<set $brothelClientsToday += 1>> <!-- Handle trait gain (15% chance) --> <<set _gainedTrait = "">> <<set _traitGained = false>> <<if random(1, 100) <= 15>> <<set _possibleGains = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _availableGains = []>> <<for _gain range _possibleGains>> <<if !$mentalTraits.includes(_gain) && !$physicalTraits.includes(_gain) && !$skills.includes(_gain)>> <<run _availableGains.push(_gain)>> <</if>> <</for>> <<if _availableGains.length > 0>> <<set _gainedTrait = _availableGains[random(0, _availableGains.length - 1)]>> <<set _traitGained = true>> <<if _gainedTrait === "Dominant" || _gainedTrait === "Submissive">> <<if _gainedTrait === "Dominant">> <<set $mentalTraits.delete("Submissive")>> <<else>> <<set $mentalTraits.delete("Dominant")>> <</if>> <<set $mentalTraits.push(_gainedTrait)>> <<elseif _gainedTrait === "Dancing" || _gainedTrait === "High Heels Proficient" || _gainedTrait === "Sexually Skilled" || _gainedTrait === "Serving" || _gainedTrait === "Persuasion">> <<set $skills.push(_gainedTrait)>> <<else>> <<set $mentalTraits.push(_gainedTrait)>> <</if>> <</if>> <</if>> <!-- Advance time --> <<advancetime 60>> <!-- Select random scene --> <<set _sceneNumber = random(1, 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Client Session</h1> <<if _clientGender === "male" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A man flanked by bodyguards arrives in a private vehicle. The expensive cologne, custom suit, and quiet confidence mark him as someone powerful. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone clearly connected offers triple the standard rate for your time. You're one of the establishment's top earners now. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A well-known figure in the city trusts only you with his desires. Your skill and discretion are unmatched. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy client books you for a weekend. Your stamina and skill have become legendary. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An elite regular considers you irreplaceable. You've become his preferred indulgence. </p> </div> <</if>> <</if>> <<if _clientGender === "male" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A client pulls up in a car worth more than most homes. He books you for hours, and your skill keeps him coming back regularly. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone influential offers premium rates to secure your time. You're among the elite now. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A powerful figure trusts only you. Your skill and discretion have made you invaluable. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy client books you for days. You deliver consistent excellence that justifies the premium. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An elite regular calls you his secret addiction. You've perfected every art. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A woman wearing jewelry that could fund a small business arrives. She's accustomed to getting exactly what she wants, and you know how to provide it. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone well-connected becomes your devoted regular. Your talents are incomparable. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A wealthy woman offers obscene amounts for your exclusive services. You've become priceless. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An elite client demands your presence at private events. You're more than a worker—you're a prize. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A powerful woman confesses you've ruined others for her. You've reached the pinnacle. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An elegant woman in couture arrives with an entourage waiting outside. Your reputation in exclusive circles has made you her preferred choice. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone influential begs to keep you exclusive. You've become irreplaceable. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A woman of means seeks your touch. You're known in circles where money is no object. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An elite woman proclaims you the city's finest. Your reputation is unmatched. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A powerful woman admits you've spoiled her for anyone else. You're irreplaceable. </p> </div> <</if>> <</if>> <!-- Earnings Display --> <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;">💰 Session Complete</h2> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0;">Base Payment: $<<print _basePay>></p> <<if _statMultiplier < 1.0>> <<set _statPenaltyPercent = Math.round((1.0 - _statMultiplier) * 100)>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Charisma Penalty: -<<print _statPenaltyPercent>>% (<<print _totalCharisma>>/35)</p> <</if>> <<if _penaltyPercent > 0>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Negative Traits Penalty: -<<print _penaltyPercent>>%</p> <</if>> <<if _bonusMoney > 0>> <p style="color: #ffc107; font-size: 16px; margin: 0 0 10px 0;">Skill Bonus: +$<<print _bonusMoney>></p> <</if>> <p style="color: #51cf66; font-size: 20px; margin: 0; font-weight: bold;">Total Earned: $<<print _totalPay>></p> </div> <!-- Trait Gained Notification --> <<if _traitGained>> <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: 0; text-align: center;">✨ NEW TRAIT ACQUIRED! ✨</h2> <p style="color: #9b59b6; font-size: 18px; margin: 10px 0 0 0; text-align: center; font-weight: bold;">_gainedTrait</p> <p style="color: #ccc; font-size: 14px; margin: 5px 0 0 0; text-align: center;">Your experiences have shaped you.</p> </div> <</if>> <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);'>Return to Lounge</div>">> <<goto "Brothel">> <</link>> </div> </div> <</nobr>><<nobr>> <!-- Random client gender --> <<set _clientGender = either("male", "female")>> <<set _playerGender = $bodyParts.gender>> <!-- Calculate earnings --> <<set _basePay = random(500, 5000)>> <<set _brothelBonusTraits = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _bonusMoney = 0>> <<for _trait range _brothelBonusTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait) || $skills.includes(_trait)>> <<set _bonusMoney += 15>> <</if>> <</for>> <<set _brothelNegativeTraits = ["Ugly", "Scarred", "Plain", "Blemished", "Overweight", "Underweight", "Stubborn", "Paranoid", "Jealous", "Dull", "Immature"]>> <<set _penaltyPercent = 0>> <<for _trait range _brothelNegativeTraits>> <<if $mentalTraits.includes(_trait) || $physicalTraits.includes(_trait)>> <<set _penaltyPercent += 10>> <</if>> <</for>> <!-- Calculate stat penalty (charisma requirement: 35) --> <<set _totalCharisma = setup.getTotalStat("charisma")>> <<set _statMultiplier = 1.0>> <<if _totalCharisma < 35>> <<set _statMultiplier = _totalCharisma / 35>> <<if _statMultiplier < 0>> <<set _statMultiplier = 0>> <</if>> <</if>> <!-- Apply all multipliers --> <<set _penaltyMultiplier = 1.0 - (_penaltyPercent / 100)>> <<set _totalPay = Math.round(_basePay * _statMultiplier * _penaltyMultiplier) + _bonusMoney>> <<set $money += _totalPay>> <!-- Increment counters --> <<set $brothelClients += 1>> <<set $brothelClientsToday += 1>> <!-- Handle trait gain (15% chance) --> <<set _gainedTrait = "">> <<set _traitGained = false>> <<if random(1, 100) <= 15>> <<set _possibleGains = ["Dominant", "Submissive", "Sly", "Hardworking", "Ambitious", "Bitchy", "Arrogant", "Dancing", "High Heels Proficient", "Sexually Skilled", "Serving", "Persuasion"]>> <<set _availableGains = []>> <<for _gain range _possibleGains>> <<if !$mentalTraits.includes(_gain) && !$physicalTraits.includes(_gain) && !$skills.includes(_gain)>> <<run _availableGains.push(_gain)>> <</if>> <</for>> <<if _availableGains.length > 0>> <<set _gainedTrait = _availableGains[random(0, _availableGains.length - 1)]>> <<set _traitGained = true>> <<if _gainedTrait === "Dominant" || _gainedTrait === "Submissive">> <<if _gainedTrait === "Dominant">> <<set $mentalTraits.delete("Submissive")>> <<else>> <<set $mentalTraits.delete("Dominant")>> <</if>> <<set $mentalTraits.push(_gainedTrait)>> <<elseif _gainedTrait === "Dancing" || _gainedTrait === "High Heels Proficient" || _gainedTrait === "Sexually Skilled" || _gainedTrait === "Serving" || _gainedTrait === "Persuasion">> <<set $skills.push(_gainedTrait)>> <<else>> <<set $mentalTraits.push(_gainedTrait)>> <</if>> <</if>> <</if>> <!-- Advance time --> <<advancetime 60>> <!-- Select random scene --> <<set _sceneNumber = random(1, 5)>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #e91e63; text-align: center;">💋 Client Session</h1> <<if _clientGender === "male" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A distinguished man arrives under discreet security. Everything about him—the bespoke tailoring, the subtle authority—screams power and wealth. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone who controls significant parts of the city offers a blank check. Your services have become priceless. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A figure of immense influence seeks your discrete companionship. You're among the city's elite now. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone at the top of the city's power structure begs for your time. Your reputation spans the entire metro. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> The establishment's owner personally ensures your every need. You're the crown jewel of this place. </p> </div> <</if>> <</if>> <<if _clientGender === "male" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone influential enough to have the venue cleared arrives. You're one of the few trusted with clients of this caliber. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone who runs half the city pays anything to secure you. You've become legendary. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A figure of immense power seeks your exclusive services. You're known across the entire city. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone at the pinnacle of the city's hierarchy pleads for your attention. Your mastery is unquestionable. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> The establishment treats you like royalty. You're the ultimate professional. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "male">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A woman who clearly runs something significant enters with absolute confidence. She pays triple the rate without blinking, and you're worth every cent. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone who controls vast wealth offers ownership stakes to keep you exclusive. You're invaluable. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> An influential woman seeks to learn from you. You're a living legend in the city. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A woman at the top declares you the finest in the city. Your reputation is unmatched. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> The establishment offers you partnership. You've conquered the profession completely. </p> </div> <</if>> <</if>> <<if _clientGender === "female" && _playerGender === "female">> <<if _sceneNumber === 1>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A powerful woman whose name you recognize arrives in absolute discretion. You've become legendary enough to serve the city's true elite. </p> </div> <<elseif _sceneNumber === 2>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone who owns half the city begs to keep you. You've become irreplaceable at the highest level. </p> </div> <<elseif _sceneNumber === 3>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> A woman of immense influence seeks your touch. You're legendary across the entire metro. </p> </div> <<elseif _sceneNumber === 4>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> Someone at the pinnacle of power proclaims you the city's finest. You've achieved perfection. </p> </div> <<else>> <div style="padding: 20px; background: linear-gradient(135deg, #e91e63 0%, #c2185b 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #e91e63;"> <p style="color: white; font-size: 18px; margin: 0;"> The establishment offers you ownership. You've conquered the profession completely. </p> </div> <</if>> <</if>> <!-- Earnings Display --> <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;">💰 Session Complete</h2> <p style="color: #ccc; font-size: 16px; margin: 0 0 10px 0;">Base Payment: $<<print _basePay>></p> <<if _statMultiplier < 1.0>> <<set _statPenaltyPercent = Math.round((1.0 - _statMultiplier) * 100)>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Charisma Penalty: -<<print _statPenaltyPercent>>% (<<print _totalCharisma>>/35)</p> <</if>> <<if _penaltyPercent > 0>> <p style="color: #ff6b6b; font-size: 16px; margin: 0 0 10px 0;">Negative Traits Penalty: -<<print _penaltyPercent>>%</p> <</if>> <<if _bonusMoney > 0>> <p style="color: #ffc107; font-size: 16px; margin: 0 0 10px 0;">Skill Bonus: +$<<print _bonusMoney>></p> <</if>> <p style="color: #51cf66; font-size: 20px; margin: 0; font-weight: bold;">Total Earned: $<<print _totalPay>></p> </div> <!-- Trait Gained Notification --> <<if _traitGained>> <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: 0; text-align: center;">✨ NEW TRAIT ACQUIRED! ✨</h2> <p style="color: #9b59b6; font-size: 18px; margin: 10px 0 0 0; text-align: center; font-weight: bold;">_gainedTrait</p> <p style="color: #ccc; font-size: 14px; margin: 5px 0 0 0; text-align: center;">Your experiences have shaped you.</p> </div> <</if>> <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);'>Return to Lounge</div>">> <<goto "Brothel">> <</link>> </div> </div> <</nobr>><<nobr>> <<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 < 0.0001 && !$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 < 0.0001 && !$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">> <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? 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> <p style="color: #aaa; margin: 5px 0 0 0; font-size: 14px;">All services cost $15,000</p> </div> <!-- REMOVE NEGATIVE TRAITS --> <<set _negativeTraits = []>> <<set _purelyNegativeTraits = ["Bitchy", "Cruel", "Jealous", "Lazy", "Arrogant", "Complacent", "Dull", "Cowardly", "Immature", "Impatient", "Foolish", "Plain", "Ugly", "Overweight", "Underweight", "Clumsy", "Weak", "Stiff", "Blemished"]>> <<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.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px;"> <<for _trait range _negativeTraits>> <<capture _trait>> <<if $money >= 15000>> <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 $15,000</div>">> <<set $money -= 15000>> <<if $physicalTraits.includes(_trait)>> <<run $physicalTraits.delete(_trait)>> <<else>> <<run $mentalTraits.delete(_trait)>> <</if>> <<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</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>> <!-- ADD MIXED TRAITS --> <<set _availableMixedTraits = ["Introverted", "Honest", "Submissive", "Shy", "Aggressive", "Passive", "Pessimistic", "Stubborn", "Paranoid"]>> <<set _purchasableTraits = []>> <<for _trait range _availableMixedTraits>> <<if !$mentalTraits.includes(_trait)>> <!-- Check for conflicts --> <<set _conflict = setup.getConflictingTrait(_trait, $mentalTraits)>> <<if !_conflict>> <<run _purchasableTraits.push(_trait)>> <</if>> <</if>> <</for>> <<if _purchasableTraits.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;">➕ Add Personality Traits</h2> <p style="color: #aaa; font-size: 14px; margin-bottom: 15px;">Acquire new personality traits through... unconventional methods.</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 15px;"> <<for _trait range _purchasableTraits>> <<capture _trait>> <<set _traitValue = setup.getTraitValue("mental", _trait)>> <<set _traitColor = _traitValue >= 0 ? "#9b59b6" : "#ff6b6b">> <<if $money >= 15000>> <div style="border: 2px solid _traitColor; border-radius: 10px; padding: 15px; background: #1a1a1a;"> <h3 style="color: _traitColor; margin: 0 0 5px 0; font-size: 18px;">_trait</h3> <p style="color: #aaa; font-size: 13px; margin: 0 0 10px 0;">Value: <<if _traitValue > 0>>+<</if>>_traitValue</p> <<link "<div style='background: _traitColor; color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold;'>Buy for $15,000</div>">> <<set $money -= 15000>> <!-- Remove conflicting trait if exists --> <<set _conflictToRemove = setup.getConflictingTrait(_trait, $mentalTraits)>> <<if _conflictToRemove>> <<if _conflictToRemove === $characterCreationTrait>> <<set $characterCreationTrait = null>> <<else>> <<run $mentalTraits.delete(_conflictToRemove)>> <</if>> <</if>> <<run $mentalTraits.push(_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 5px 0; font-size: 18px;">_trait</h3> <p style="color: #666; font-size: 13px; margin: 0 0 10px 0;">Value: <<if _traitValue > 0>>+<</if>>_traitValue</p> <div style='background: #666; color: #999; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold;'>Can't Afford</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;">➕ Add Personality Traits</h2> <p style="color: #666; font-size: 14px; margin: 0; text-align: center; font-style: italic;">No traits available to purchase (you may already have them or conflicting traits).</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>>Work In Progress <<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>><<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>>Work In Progress <<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>><<nobr>> /* Initialize relationship if this is first meeting */ <<if !$npcRelationships["Fen Ris"]>> <<set $npcRelationships["Fen Ris"] = { level: 1, xp: 0, maxXp: 20, levelName: "Stranger", loverUnlocked: false }>> <</if>> /* Add Fen Ris to met NPCs if not already there */ <<if !$metNPCs.includes("Fen Ris")>> <<run $metNPCs.push("Fen Ris")>> <</if>> <<silently>> /* Get trainer by job instead of by name */ <<set _trainers = setup.getNPCsByJob("Fitness Trainer")>> <<set _trainer = _trainers && _trainers.length > 0 ? _trainers[0] : null>> <<set _canTrainToday = true>> /* Check if player already trained today (track by job, not name) */ <<if $lastFenRisTrainingDay === $dayNumber>> <<set _canTrainToday = false>> <</if>> /* Calculate trainer effectiveness */ <<set _effectiveness = 100>> /* Base effectiveness for Fen Ris */ /* If trainer is not Fen Ris (check original name, not current name after trade), calculate effectiveness */ <<if _trainer>> /* 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>> <</if>> /* Calculate actual stat gains based on effectiveness */ <<set _strengthGain = Math.round(5 * (_effectiveness / 100))>> <<set _dexGain = Math.round(4 * (_effectiveness / 100))>> <<set _charismaGain = Math.round(3 * (_effectiveness / 100))>> <<set _intGain = Math.round(2 * (_effectiveness / 100))>> <</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 with <<= _trainer ? _trainer.name : "Fen Ris">></h2> </div> <<if _trainer>> <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> <<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> <<else>> <p style="color: #e0e0e0; font-size: 16px;"> <<= _trainer.name>> has taken over the personal training services at Opah Fitness. </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 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> <<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 with <<= _trainer.name>> today. Come back tomorrow! </p> </div> <<elseif $money < 100>> <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>> <<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 $money -= 100>> <<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 */ <<run setup.addRelationshipXP(_trainer.name, 2)>> /* Advance time by 4 hours */ <<run advanceTime(240)>> <</link>> <</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> <<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>> </div> <<else>> <div style="background-color: #c92a2a; padding: 20px; border-radius: 8px; border: 2px solid #ff6b6b;"> <p style="color: white; margin: 0; text-align: center;"> The fitness trainer is not available 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; 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: 1, 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)>> <<if _rel.level < 5>> <<set _nextThreshold = [10, 30, 60, 100][_rel.level - 1]>> <<set _currentLevelMin = [0, 10, 30, 60][_rel.level - 1]>> <<set _xpInLevel = _rel.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <<else>> <<set _xpPercent = 100>> <</if>> <<capture _npcName, _relColor, _rel, _xpPercent>> <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;'>Level " + _rel.level + "</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 !$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 to Relationships</div>" "Relationships">> <<set $viewingNPC = null>> <</link>> </div> </div> <<else>> <<set _npc = setup.getNPCByName($viewingNPC)>> <<set _rel = $relationships[$viewingNPC]>> <<set _relColor = setup.getRelationshipColor(_rel.level)>> <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);"><<= $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;">Level <<= _rel.level>></span> <<if _rel.level < 5>> <<set _nextThreshold = [10, 30, 60, 100][_rel.level - 1]>> <<set _currentLevelMin = [0, 10, 30, 60][_rel.level - 1]>> <<set _xpInLevel = _rel.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <span style="color: <<= _relColor>>; font-weight: bold; font-size: 18px;"><<= _xpInLevel>> / <<= _xpNeededForLevel>> XP</span> <<else>> <span style="color: <<= _relColor>>; font-weight: bold; font-size: 18px;">MAX LEVEL</span> <</if>> </div> <<if _rel.level < 5>> <!-- XP Progress Bar --> <div style="background-color: #000; border-radius: 10px; height: 25px; overflow: hidden; border: 2px solid #444; box-shadow: inset 0 2px 4px rgba(0,0,0,0.8);"> <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;"> <<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%); animation: shimmer 2s infinite;"></div> <</if>> </div> </div> <p style="color: #aaa; margin: 10px 0 0 0; font-size: 14px;"> <<= _nextThreshold - _rel.points>> XP 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 --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 15px; color: #e0e0e0; font-size: 15px;"> <div> <strong style="color: #4dabf7;">Job:</strong><br> <<= _npc.jobs && _npc.jobs.length > 0 ? _npc.jobs.join(", ") : "Unemployed">> </div> <div> <strong style="color: #4dabf7;">Gender:</strong><br> <<= _npc.bodyParts.gender.charAt(0).toUpperCase() + _npc.bodyParts.gender.slice(1)>> </div> <div> <strong style="color: #4dabf7;">Age:</strong><br> <<= _npc.appearance.age>> </div> <div> <strong style="color: #4dabf7;">Skin Tone:</strong><br> <<= _npc.appearance.skinTone.charAt(0).toUpperCase() + _npc.appearance.skinTone.slice(1)>> </div> <div> <strong style="color: #4dabf7;">Hair:</strong><br> <<= _npc.appearance.hairLength ? (_npc.appearance.hairLength.charAt(0).toUpperCase() + _npc.appearance.hairLength.slice(1)) : "Unknown">> <<= _npc.appearance.hairColor>> </div> <div> <strong style="color: #4dabf7;">Build:</strong><br> <<= _npc.appearance.physique.charAt(0).toUpperCase() + _npc.appearance.physique.slice(1)>> </div> </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> <<= _npc.stats.strength>> </div> <div> <span style="color: #51cf66;">■</span> <strong>Dexterity:</strong> <<= _npc.stats.dexterity>> </div> <div> <span style="color: #ffd43b;">■</span> <strong>Charisma:</strong> <<= _npc.stats.charisma>> </div> <div> <span style="color: #4dabf7;">■</span> <strong>Intelligence:</strong> <<= _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;"> <<= _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;"> <<= _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;"> <<= _npc.skills[_j]>> </span> <</for>> </div> </div> <</if>> </div> <</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 to Relationships</div>" "Relationships">> <<set $viewingNPC = null>> <</link>> </div> </div> <</if>> <</nobr>> <style> @keyframes shimmer { 0% { transform: translateX(-100%); } 100% { transform: translateX(100%); } } </style><<nobr>> <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>">> <<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! </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 $lastLocation>> <</link>> </div> </div> <</nobr>><<nobr>> <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> <!-- 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> <!-- 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 $lastLocation>> <</link>> </div> </div> <</nobr>><<nobr>> <<if $physicalTraits.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">Current Traits:</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _i = 0; _i < $physicalTraits.length; _i++>> <<if $physicalTraits[_i] !== "Short Hair" && $physicalTraits[_i] !== "Long Hair">> <<capture _i>> <<link "<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; cursor: pointer;'><<= $physicalTraits[_i]>> ✕</span>">> <<run $physicalTraits.deleteAt(_i)>> <<replace "#physicalTraitsSection">><<include "CheatMenuPhysicalTraits">><</replace>> <</link>> <</capture>> <</if>> <</for>> </div> </div> <</if>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #51cf66; margin: 0 0 10px 0;">Add Trait:</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; max-height: 400px; overflow-y: auto; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <<set _physicalTraitList = ["Tall", "Short", "Curvy", "Lean", "Muscular", "Soft", "Sharp Features", "Smooth Skin", "Pierced", "Youthful", "Mature", "Tan Skin", "Dark Skin", "Pale Skin", "Attractive", "Fit", "Graceful", "Strong", "Flexible", "Freckled", "Tattooed", "Athletic Build", "Petite", "Voluptuous", "Broad-shouldered", "Quick", "Sturdy", "High Energy", "Deep Thinker", "Monotone Expression", "Sarcastic", "Artistic", "Relaxed", "Humorous", "Perceptive", "Detail-Oriented", "Customer-Focused", "Punctual", "Scarred", "Plain", "Ugly", "Overweight", "Underweight", "Clumsy", "Weak", "Stiff", "Blemished", "Fashionable", "Quick Reflexes", "Tech Savvy", "Fast", "Slow"]>> <<for _j = 0; _j < _physicalTraitList.length; _j++>> <<set _trait = _physicalTraitList[_j]>> <<set _hasTrait = $physicalTraits.includes(_trait)>> <<set _conflict = setup.getConflictingTrait(_trait, $physicalTraits)>> <<if !_hasTrait>> <<capture _trait, _conflict>> <<if _conflict>> <<link "<div style='background: linear-gradient(135deg, #495057 0%, #343a40 100%); color: #aaa; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'><<= _trait>><br><span style='font-size: 10px; color: #ff6b6b;'>⚠️ Conflicts with <<= _conflict>></span></div>">> <<run $physicalTraits.delete(_conflict)>> <<run $physicalTraits.push(_trait)>> <<replace "#physicalTraitsSection">><<include "CheatMenuPhysicalTraits">><</replace>> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'><<= _trait>></div>">> <<run $physicalTraits.push(_trait)>> <<replace "#physicalTraitsSection">><<include "CheatMenuPhysicalTraits">><</replace>> <</link>> <</if>> <</capture>> <</if>> <</for>> </div> </div> <</nobr>><<nobr>> <<set _currentVoiceTrait = null>> <<for _i = 0; _i < $physicalTraits.length; _i++>> <<if setup.exclusiveTraitGroups.voice.includes($physicalTraits[_i])>> <<set _currentVoiceTrait = $physicalTraits[_i]>> <<break>> <</if>> <</for>> <<if _currentVoiceTrait>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #da77f2; margin: 0 0 10px 0;">Current Voice:</h3> <<link "<span style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #da77f2; padding: 6px 12px; border-radius: 15px; font-size: 13px; border: 1px solid #da77f2; box-shadow: 0 0 5px #da77f244; cursor: pointer;'><<= _currentVoiceTrait>> ✕</span>">> <<run $physicalTraits.delete(_currentVoiceTrait)>> <<replace "#voiceTraitsSection">><<include "CheatMenuVoiceTraits">><</replace>> <</link>> </div> <</if>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #da77f2; margin: 0 0 10px 0;"><<= _currentVoiceTrait ? "Change Voice:" : "Add Voice:">></h3> <p style="color: #ffd43b; font-size: 13px; margin: 0 0 10px 0;">⚠️ Only one voice trait allowed at a time</p> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; max-height: 400px; overflow-y: auto; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <<set _voiceTraitList = ["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", "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", "Shaky Voice"]>> <<for _j = 0; _j < _voiceTraitList.length; _j++>> <<set _trait = _voiceTraitList[_j]>> <<set _hasTrait = $physicalTraits.includes(_trait)>> <<if !_hasTrait>> <<capture _trait>> <<link "<div style='background: linear-gradient(135deg, #da77f2 0%, #cc5de8 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'><<= _trait>></div>">> <<if _currentVoiceTrait>> <<run $physicalTraits.delete(_currentVoiceTrait)>> <</if>> <<run $physicalTraits.push(_trait)>> <<replace "#voiceTraitsSection">><<include "CheatMenuVoiceTraits">><</replace>> <</link>> <</capture>> <</if>> <</for>> </div> </div> <</nobr>><<nobr>> <<if $mentalTraits.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">Current Traits:</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _i = 0; _i < $mentalTraits.length; _i++>> <<capture _i>> <<link "<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; cursor: pointer;'><<= $mentalTraits[_i]>> ✕</span>">> <<run $mentalTraits.deleteAt(_i)>> <<replace "#mentalTraitsSection">><<include "CheatMenuMentalTraits">><</replace>> <</link>> <</capture>> <</for>> </div> </div> <</if>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #9b59b6; margin: 0 0 10px 0;">Add Trait:</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; max-height: 400px; overflow-y: auto; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <<set _mentalTraitList = ["Nonchalant", "Charming", "Diplomatic", "Organized", "Resourceful", "Focused", "Disciplined", "Determined", "Steadfast", "Considerate", "Polite", "Funny", "Reassuring", "Loyal", "Talkative", "Direct", "Efficient", "Negotiator", "Crafty", "Workaholic", "High Stamina", "Flirty", "Seductive", "Alluring", "Warm", "Bookworm", "Lucky", "Nerd", "Geek", "Jock", "Prep", "Tomboy", "Femboy", "Diva", "Goth", "Blunt", "Perfectionist", "Overthinker", "Moody", "Unpredictable", "Risk Taker", "Impulsive", "Cynical", "Quiet", "Awkward", "Tone Deaf", "Tease", "Clingy", "Sensitive", "Corporate Drone", "Forgetful", "Disorganized", "Selfish", "Deceitful", "Erratic", "Obsessive", "Insecure", "Short Tempered", "Rude", "Unreliable", "Slow Learner", "Reckless", "Cold", "Insensitive", "Unskilled", "Unlucky", "Cowardly", "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", "Chill", "Introverted", "Honest", "Submissive", "Shy", "Aggressive", "Passive", "Pessimistic", "Stubborn", "Paranoid", "Bitchy", "Cruel", "Jealous", "Lazy", "Arrogant", "Complacent", "Dull", "Immature", "Impatient", "Foolish"]>> <<for _j = 0; _j < _mentalTraitList.length; _j++>> <<set _trait = _mentalTraitList[_j]>> <<set _hasTrait = $mentalTraits.includes(_trait)>> <<set _conflict = setup.getConflictingTrait(_trait, $mentalTraits)>> <<if !_hasTrait>> <<capture _trait, _conflict>> <<if _conflict>> <<link "<div style='background: linear-gradient(135deg, #495057 0%, #343a40 100%); color: #aaa; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'><<= _trait>><br><span style='font-size: 10px; color: #ff6b6b;'>⚠️ Conflicts with <<= _conflict>></span></div>">> <<run $mentalTraits.delete(_conflict)>> <<run $mentalTraits.push(_trait)>> <<replace "#mentalTraitsSection">><<include "CheatMenuMentalTraits">><</replace>> <</link>> <<else>> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'><<= _trait>></div>">> <<run $mentalTraits.push(_trait)>> <<replace "#mentalTraitsSection">><<include "CheatMenuMentalTraits">><</replace>> <</link>> <</if>> <</capture>> <</if>> <</for>> </div> </div> <</nobr>><<nobr>> <<if $skills.length > 0>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333;"> <h3 style="color: #ff922b; margin: 0 0 10px 0;">Current Skills:</h3> <div style="display: flex; flex-wrap: wrap; gap: 8px;"> <<for _i = 0; _i < $skills.length; _i++>> <<capture _i>> <<link "<span style='background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); color: #ff922b; padding: 6px 12px; border-radius: 15px; font-size: 13px; border: 1px solid #ff922b; box-shadow: 0 0 5px #ff922b44; cursor: pointer;'><<= $skills[_i]>> ✕</span>">> <<run $skills.deleteAt(_i)>> <<replace "#skillsSection">><<include "CheatMenuSkills">><</replace>> <</link>> <</capture>> <</for>> </div> </div> <</if>> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #ff922b; margin: 0 0 10px 0;">Add Skill:</h3> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; max-height: 400px; overflow-y: auto; padding: 10px; background: #0a0a0a; border-radius: 6px;"> <<set _skillList = ["Math Skills", "Coding", "Dancing", "Plumbing", "High Heels Proficient", "Swimmer", "Swimming", "Sexually Skilled", "Modeling", "Makeup", "Cooking", "Photography", "Maid", "Singing", "Serving", "Hair Styling", "Cleaning", "Combat", "Persuasion", "Medicine", "Trading", "Stealth", "Driving", "Lock Picking", "First Aid", "Gardening", "Construction", "Heavy Lifting", "Social Media", "Baking", "Public Speaking", "Writing", "Art", "Painting", "Music", "Guitar", "Piano", "Acting", "Teaching", "Sales", "Management", "Accounting", "Legal Knowledge", "Languages", "Foreign Language", "Martial Arts", "Athletics", "Yoga", "Retail", "Tech-Savvy", "Troubleshooting", "Forklift Certified", "Product Knowledge", "Inventory Management", "Customer Service", "BtestBraitBeesBigBeenore", "Were-Creature", "Sunfish","Occult Expert"]>> <<for _j = 0; _j < _skillList.length; _j++>> <<set _skill = _skillList[_j]>> <<set _hasSkill = $skills.includes(_skill)>> <<if !_hasSkill>> <<capture _skill>> <<link "<div style='background: linear-gradient(135deg, #ff922b 0%, #fd7e14 100%); color: white; padding: 8px; border-radius: 6px; text-align: center; cursor: pointer; font-size: 12px; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'><<= _skill>></div>">> <<run $skills.push(_skill)>> <<replace "#skillsSection">><<include "CheatMenuSkills">><</replace>> <</link>> <</capture>> <</if>> <</for>> </div> </div> <</nobr>><<nobr>> <<set $lastLocation = "StripClubVIP">> <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);">👑 VIP Lounge</h1> </div> <!-- Description --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 20px; border-radius: 12px; border: 3px solid #FFD700; box-shadow: 0 4px 8px rgba(0,0,0,0.4); margin-bottom: 25px;"> <p style="color: #e0e0e0; font-size: 16px; line-height: 1.6; margin: 0;"> The VIP lounge is dimly lit with luxurious velvet seating and ambient purple lighting. Soft music plays in the background as exclusive guests enjoy premium bottle service and private entertainment. Everything here exudes opulence and discretion. </p> </div> <!-- Available Strippers --> <<set _strippers = setup.getNPCsByJob("Stripper")>> <<if _strippers && _strippers.length > 0>> <h2 style="color: #FFD700; margin-bottom: 15px;">💃 Available Performers</h2> <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(auto-fill, minmax(300px, 1fr)); gap: 15px;"> <<for _npc range _strippers>> <<capture _npc>> <div style="border: 3px solid #9D00FF; border-radius: 10px; padding: 15px; background: #1a1a1a; box-shadow: 0 4px 8px rgba(0,0,0,0.4);"> <h3 style="color: #9D00FF; margin: 0 0 10px 0;"><<= _npc.name>></h3> <!-- Service Options --> <div style="background: #0a0a0a; padding: 12px; border-radius: 6px; margin-bottom: 12px; border: 1px solid #444;"> <p style="color: #FFD700; font-size: 16px; font-weight: bold; margin: 0 0 8px 0;">Private Dance: $500</p> <p style="color: #aaa; font-size: 13px; margin: 0; line-height: 1.4;">An intimate, personal performance just for you.</p> </div> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;"> <<if $money >= 500>> <<link "<div style='background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; cursor: pointer; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>💃 Private Dance</div>">> <<set $money -= 500>> <<set $currentVIPStriper = _npc>> <<goto "StripClubVIPService">> <</link>> <<else>> <div style='background: #666; color: #aaa; padding: 10px; border-radius: 6px; text-align: center; font-weight: bold; cursor: not-allowed; font-size: 13px;'>💃 Private Dance</div> <</if>> <<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; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>💬 Chat</div>">> <<set $tradingWithNPC = _npc>> <<goto "NPCInteraction">> <</link>> </div> </div> <</capture>> <</for>> </div> </div> <<else>> <h2 style="color: #FFD700; margin-bottom: 15px;">💃 Available Performers</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 performers are available right now. Check 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 to Main Floor</div>" "StripClub">><</link>> </div> </div> <</nobr>><<nobr>> <!-- NPC List --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #333; max-height: 500px; overflow-y: auto;"> <<if Object.keys($relationships).length === 0>> <p style="color: #999; font-style: italic; margin: 0; text-align: center; padding: 20px;">No NPC relationships initialized yet</p> <<else>> <<set _hasMetNPCs = false>> <<for _npcName, _rel range $relationships>> <<if $metNPCs.includes(_npcName)>> <<set _hasMetNPCs = true>> <<capture _npcName, _rel>> <<set _relColor = setup.getRelationshipColor(_rel.level)>> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 15px; border-radius: 8px; margin-bottom: 12px; border: 2px solid <<= _relColor>>; box-shadow: 0 2px 4px rgba(0,0,0,0.3);"> <!-- NPC Header --> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px;"> <strong style="color: <<= _relColor>>; font-size: 18px;"><<= _npcName>></strong> <span style="color: #fff; font-size: 14px; background: #0a0a0a; padding: 6px 12px; border-radius: 6px; border: 1px solid <<= _relColor>>;"> Level <<= _rel.level>> (<<= _rel.points>> points) </span> </div> <!-- XP Progress Bar --> <div style="margin-bottom: 12px;"> <<if _rel.level < 5>> <<set _nextThreshold = [10, 30, 60, 100][_rel.level - 1]>> <<set _currentLevelMin = [0, 10, 30, 60][_rel.level - 1]>> <<set _xpInLevel = _rel.points - _currentLevelMin>> <<set _xpNeededForLevel = _nextThreshold - _currentLevelMin>> <<set _xpPercent = Math.floor((_xpInLevel / _xpNeededForLevel) * 100)>> <div style="display: flex; justify-content: space-between; font-size: 13px; color: #e0e0e0; margin-bottom: 6px; font-weight: bold;"> <span>Experience: <<= _xpInLevel>> / <<= _xpNeededForLevel>></span> <span><<= _xpPercent>>%</span> </div> <div style="background: #0a0a0a; border-radius: 6px; height: 12px; overflow: hidden; border: 1px solid #444;"> <div style="background: <<= _relColor>>; height: 100%; width: <<= _xpPercent>>%; transition: width 0.3s;"></div> </div> <<else>> <div style="text-align: center; font-size: 14px; color: #51cf66; font-weight: bold;"> MAX LEVEL REACHED </div> <</if>> </div> <!-- Points Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-bottom: 8px;"> <<link "<div style='background: linear-gradient(135deg, #51cf66 0%, #40c057 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>+10 Points</div>">> <<run setup.addRelationshipPoints(_npcName, 10)>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ffd43b 0%, #fab005 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>+50 Points</div>">> <<run setup.addRelationshipPoints(_npcName, 50)>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #4dabf7 0%, #339af0 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Max Level</div>">> <<run setup.addRelationshipPoints(_npcName, 1000)>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> </div> <!-- Control Buttons --> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px;"> <<link "<div style='background: linear-gradient(135deg, #9b59b6 0%, #8e44ad 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Reset to Level 1</div>">> <<set $relationships[_npcName] = { level: 1, points: 0 }>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 100%); color: white; padding: 10px; border-radius: 6px; text-align: center; font-size: 13px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3);'>Complete Reset</div>">> <<set $relationships[_npcName] = { level: 1, points: 0 }>> <<run $metNPCs.delete(_npcName)>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> </div> </div> <</capture>> <</if>> <</for>> <<if !_hasMetNPCs>> <p style="color: #999; font-style: italic; margin: 0; text-align: center; padding: 20px;">No NPCs met yet. Explore the world to meet characters!</p> <</if>> <</if>> </div> <!-- Global Relationship Controls --> <div style="background-color: #1a1a1a; padding: 15px; border-radius: 8px; border: 1px solid #333;"> <h3 style="color: #e91e63; margin: 0 0 12px 0;">Global Controls</h3> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;"> <<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);'>✨ Max All Relationships</div>">> <<for _npcName, _rel range $relationships>> <<if $metNPCs.includes(_npcName)>> <<run setup.addRelationshipPoints(_npcName, 1000)>> <</if>> <</for>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #fa5252 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);'>🔄 Reset All Relationships</div>">> <<for _npcName, _rel range $relationships>> <<set $relationships[_npcName] = { level: 1, points: 0 }>> <</for>> <<set $metNPCs = []>> <<set $dailyConversations = {}>> <<replace "#relationshipsSection">><<include "CheatMenuRelationships">><</replace>> <</link>> </div> </div> <</nobr>><<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <!-- Header --> <div style="padding: 20px; background: linear-gradient(135deg, #9D00FF 0%, #6A00B3 100%); border-radius: 15px; margin-bottom: 25px; border: 2px solid #9D00FF; box-shadow: 0 0 20px #9D00FF66;"> <h1 style="color: white; text-align: center; margin: 0; text-shadow: 0 2px 4px rgba(0,0,0,0.5);">💃 Private Dance</h1> </div> <!-- Service Description --> <div style="background: linear-gradient(135deg, #2d2d2d 0%, #1a1a1a 100%); padding: 30px; border-radius: 12px; border: 3px solid #9D00FF; 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: #9D00FF; margin: 0 0 15px 0;"><<= $currentVIPStriper.name>> provides an unforgettable experience</h2> <p style="color: #e0e0e0; font-size: 18px; line-height: 1.6; max-width: 600px; margin: 0 auto 20px auto;"> In the privacy of the VIP lounge, <<= $currentVIPStriper.name>> performs an intimate and captivating dance just for you. The music pulses, the lights dim, and for these moments, you're the only person in the world. </p> <p style="color: #FFD700; font-size: 20px; font-weight: bold; margin: 0;"> ✨ An experience worth every dollar ✨ </p> </div> <!-- Relationship Gain --> <<run setup.addRelationshipXP($currentVIPStriper.name, 15)>> <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;"> 💕 Your relationship with <<= $currentVIPStriper.name>> has improved! (+15 XP) </p> </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;'>← Back to VIP Lounge</div>">> <<run advanceTime(30)>> <<set $currentVIPStriper = null>> <<goto "StripClubVIP">> <</link>> </div> </div> <</nobr>><<nobr>> <!-- Initialize dance progress if needed --> <<if !$danceProgress>> <<set $danceProgress = 0>> <</if>> <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>> <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>> <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> </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;">🖼️ Image Settings</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;"> Customize how images are displayed in your game. You can disable default images and upload your own custom images for a personalized experience. </p> </div> <!-- Image Toggle Section --> <div style="background: #2a2a2a; 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);"> <h2 style="color: <<if $imageSettings.imagesEnabled>>#51cf66<<else>>#ff6b6b<</if>>; margin: 0 0 15px 0;"> 📷 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;"> <<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);'>✓ Enable Default Images</div>">> <<set $imageSettings.imagesEnabled = true>> <<goto "ImageSettings">> <</link>> <<link "<div style='background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 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);'>✗ Disable Default Images</div>">> <<set $imageSettings.imagesEnabled = false>> <<goto "ImageSettings">> <</link>> </div> </div> <!-- Custom Image Upload Section --> <<if !$imageSettings.imagesEnabled>> <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;">📤 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: #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; text-align: center; font-style: italic; margin: 0;"> Custom image uploads are only available when default images are disabled. </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</div>">> <<goto $lastLocation>> <</link>> </div> </div> <</nobr>><<nobr>> <<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.getNPCsByJob("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>> <<set $lastLocation = "Casino">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">🎰 Slot Machines</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;"> Rows of colorful slot machines line the casino floor, each one flashing and chiming to attract players. Digital screens show tantalizing jackpots while the mechanical whir of spinning reels fills the air. </p> </div> <div style="border: 3px solid #666; border-radius: 10px; padding: 30px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6; text-align: center;"> <h2 style="color: #666; margin-bottom: 20px;">🚧 Under Construction 🚧</h2> <p style="color: #888; font-size: 18px; margin-bottom: 10px;">Slot machine gameplay is currently being developed.</p> <p style="color: #666; font-size: 14px;">Check back soon for exciting gambling action!</p> </div> <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>> <<set $lastLocation = "Casino">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #ffd700; text-align: center;">🎡 Roulette</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;"> The elegant roulette wheel sits at the center of a green felt table, its alternating red and black pockets gleaming under the casino lights. Players cluster around, placing chips on numbers and colors, waiting for the dealer's practiced spin to determine their fate. </p> </div> <div style="border: 3px solid #666; border-radius: 10px; padding: 30px; background: #2a2a2a; box-shadow: 0 4px 8px rgba(0,0,0,0.4); opacity: 0.6; text-align: center;"> <h2 style="color: #666; margin-bottom: 20px;">🚧 Under Construction 🚧</h2> <p style="color: #888; font-size: 18px; margin-bottom: 10px;">Roulette gameplay is currently being developed.</p> <p style="color: #666; font-size: 14px;">Check back soon for the thrill of the wheel!</p> </div> <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>> <<set $lastLocation = "SeabassPark">> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #4a7c2c; text-align: center;">🌳 Seabass Park</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;"> 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> </div> </div> <</nobr>><<nobr>> <<set $lastLocation = "LampreyTomes">> <!-- Check if inventory needs to be refreshed (at noon) --> <<if !$lampreyInventory || setup.shouldRefreshLampreyInventory()>> <<set $lampreyInventory = setup.generateLampreyInventory()>> <<set $lampreyLastRefreshDay = $dayNumber>> <</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> <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>> <!-- NPC Interaction --> <<set _revna = setup.findNPCByName("Revna McKraken")>> <<if _revna && setup.isNPCAvailable(_revna.name)>> <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;"> <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>> <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 _discount > 0 && _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>> <<if 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>> <<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>> <<set $lastLocation = "Outskirts">> <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;">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> <!-- 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> <!-- 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>> </div> </div> <</nobr>><<silently>> <<set setup.lampreyTraits to { common: { price: 500, chance: 0.90, traits: [ "Broad-shouldered", "Freckled", "Tattooed", "Deep voice", "Emotionless tone", "Grim Tone", "Risk Taker", "Overthinker", "Quiet", "Clingy", "Impulsive", "Disorganized", "Forgetful", "Cowardly", "Insecure", "Brave", "Witty", "Passive", "Stubborn", "Paranoid", "Bitchy", "Foolish" ] }, uncommon: { price: 2000, chance: 0.20, traits: ["Articulate Speech", "Submissive", "Sturdy", "Artistic"] }, rare: { price: 5000, chance: 0.05, traits: ["Youthful", "Attractive", "Sly", "Curvy", "Voluptuous", "Perceptive"] }, aethereal: { price: 10000, chance: 0.01, traits: [ "Giant Chest", "Giant Butt", "Goth", "Nerd", "Jock", "Prep", "Dominant" ] }, legendary: { price: 50000, chance: 0.001, traits: ["Were-Creature", "Lucky", "Occult Expert"] } }>> <<set setup.getLampreyDiscount = function() { var relationship = State.variables.relationships["Revna McKraken"] || {level: 1, points: 0}; var discounts = { 1: 0, // Stranger - no discount 2: 0.03, // Acquaintance - 3% discount 3: 0.07, // Friend - 7% discount 4: 0.12, // Close Friend - 12% discount 5: 0.20 // Lover - 20% discount }; return discounts[relationship.level] || 0; }>> <<set setup.calculateLampreyPrice = function(basePrice) { var discount = setup.getLampreyDiscount(); return Math.floor(basePrice * (1 - discount)); }>> <<set setup.generateLampreyInventory to function() { var inventory = []; var guaranteedCommon = setup.lampreyTraits.common.traits.random(); inventory.push({ trait: guaranteedCommon, rarity: 'common', price: setup.lampreyTraits.common.price }); for (var i = 0; i < 3; i++) { var selectedRarity = null; var roll = Math.random(); if (roll < setup.lampreyTraits.legendary.chance) { selectedRarity = 'legendary'; } else if (roll < setup.lampreyTraits.aethereal.chance) { selectedRarity = 'aethereal'; } else if (roll < setup.lampreyTraits.rare.chance) { selectedRarity = 'rare'; } else if (roll < setup.lampreyTraits.uncommon.chance) { selectedRarity = 'uncommon'; } else { selectedRarity = 'common'; } var rarityData = setup.lampreyTraits[selectedRarity]; var trait = rarityData.traits.random(); if (!inventory.some(function(item) { return item.trait === trait; })) { inventory.push({ trait: trait, rarity: selectedRarity, price: rarityData.price }); } else { i--; } } return inventory; }>> <<set setup.shouldRefreshLampreyInventory to function() { var currentDay = State.variables.dayNumber; var lastRefreshDay = State.variables.lampreyLastRefreshDay || -1; var currentHour = Math.floor(State.variables.timeInMinutes / 60) % 24; if (currentDay > lastRefreshDay && currentHour >= 12) { return true; } return false; }>> <<set setup.getRarityColor to function(rarity) { var colors = { common: '#aaa', uncommon: '#51cf66', rare: '#339af0', aethereal: '#b19cd9', legendary: '#ffd700' }; return colors[rarity] || '#aaa'; }>> <<set setup.getRarityName to function(rarity) { var names = { common: 'Common', uncommon: 'Uncommon', rare: 'Rare', aethereal: 'Aethereal', legendary: 'Legendary' }; return names[rarity] || 'Unknown'; }>> <</silently>><<nobr>> <div style="background: #1a1a1a; min-height: 100vh; padding: 20px;"> <h1 style="color: #b19cd9; text-align: center;">📚 Lamprey Tomes</h1> <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 20px rgba(139,0,255,0.3);"> <p style="color: #b19cd9; font-size: 20px; margin: 0 0 20px 0; text-align: center; font-style: italic;"> "<<print $lampreyLastPurchaseDialogue>>" </p> <p style="color: white; 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: #8b00ff; color: white; padding: 15px 30px; border-radius: 8px; display: inline-block; cursor: pointer; font-weight: bold; font-size: 16px;'>Continue Shopping</div>">> <<goto "LampreyTomes">> <</link>> </div> </div> <</nobr>>A thank you to my patrons for your custom NPCs! Cerberus: Fen Ris, The Flying Duckman: Revna McKraken,