User prompt
1. Enlarge the clickable hit areas. 👉 Change these to match the full button dimensions you set when creating them. 2. Lower the drag threshold var DRAG_THRESHOLD = 15; // smoother tap vs drag 3. Make tap-to-add more forgiving. Right now, a tap only adds to the cauldron if you hit the button exactly. You can soften this by always treating a quick tap as a “select” (within threshold), even if the pointer shifts slightly. 4. Visual feedback on hover/press You already tint tea base buttons on hover, which is great. Do the same for herb buttons so players know they’re clickable. For example, inside game.move: if (isHovering) { it.children[0].tint = 0x666666; // lighter shade } else { it.children[0].tint = itemColors[i] || 0x8B4513; } ✅ With those changes: Players can tap anywhere on the button to select. Dragging feels smoother (less accidental). There’s clear feedback when hovering/pressing.
User prompt
1. Enlarge the clickable hit areas 👉 Change these to match the full button dimensions you set when creating them:hw = (it.hitW || 400) / 2; // full width hh = (it.hitH || 120) / 2; // full height 2. Lower the drag threshold Currently you require a mouse/touch move of 8 pixels before a drag starts. 👉 Try raising it slightly, e.g.:var DRAG_THRESHOLD = 15; // smoother tap vs drag 3. Make tap-to-add more forgiving Right now, a tap only adds to the cauldron if you hit the button exactly. You can soften this by always treating a quick tap as a “select” (within threshold), even if the pointer shifts slightly:if (moved <= DRAG_THRESHOLD * 2) { // treat as tap } 4. Visual feedback on hover/press You already tint tea base buttons on hover, which is great. Do the same for herb buttons so players know they’re clickable. For example, inside game.move: if (isHovering) { it.children[0].tint = 0x666666; // lighter shade } else { it.children[0].tint = itemColors[i] || 0x8B4513; }
User prompt
expand the hit boxes for all buttons to be the entire size of the buttons. Allow tea base choices to be both clicked to select or dragged make the back button in the journal return to the last "page" and not back to the table of contents.
User prompt
make it easier to click and drag herbs and bases into the cauldron. allow player to simply click on an herb or element to select it for the cauldron. increase size of font that shows what has been added to the cauldron, make the font black and bold. increase size of font and boxes of buttons for tea bases, herbs, and illnesses,
User prompt
scale the how to card to cover 75% of the screen when displayed. Change the color of the PLAY button to bright yellow and the test color to black
User prompt
for the how to card, Preserve aspect ratio automatically Don’t set both width and height manually. Instead, just set one dimension and let the engine keep proportions: var howtoCard = howtoOverlay.attachAsset('howto_card', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, width: 1000 // pick one dimension // no height → keeps aspect ratio });
User prompt
when a new game starts, display the howto_card graphic with a button below that says PLAY to begin the game
User prompt
✅ Fixes 1. Table of Contents Buttons 👉 Fix: scale button height + width up to match textwidth: 650, // +30% width height: 180, // instead of 120 That way the text doesn’t look squished. Apply this to herbsContentButton, basesContentButton, illnessesContentButton. 2. Journal Section Descriptions (Herbs, Illnesses, Tea Bases) 👉 Fix: shorten wrap width. For 75px text, use about 40 characters:sectionDescription.setText(wrapTextByWords(desc, 40)); 3. Spacing Between Title / Type / Element / Description ncrease Y spacing:sectionTitle.y = 750; // keep sectionType.y = 950; // was 880 → push down sectionElement.y = 1100; // was 1000 → push down sectionDescription.y = 1300; // was 1150 → push way down Background Padding If you want descriptions to never touch the edges, shrink the effective text area by adding a container or background margin. For example, you can offset sectionDescription.x and give it a maxWidth (if Text2 supports it), or simply adjust wrapTextByWords. 📌 Summary of Fixes Buttons: Make them 650x180 instead of 500x120. Descriptions: Wrap at 40 characters per line (instead of 60). Spacing: Push down Y-positions so text doesn’t overlap. (Optional) add margins so description text doesn’t hit the edges.
User prompt
🔎 1. Tea Bases (Popup Window) Inside PopupMenu.showMenu (special layout for Tea Bases): 👉 Change 48 → 72 (+50%) 🔎 2. Tea Bases (Journal Section) Inside JournalPopup.updateSectionContent:sectionType.setText("Tea Base"); sectionElement.setText("Element: " + baseData.element...); sectionDescription.setText(...); The actual Text2 objects are defined earlier for example var sectionType = new Text2('', { size: 56, ... }); var sectionElement = new Text2('', { size: 56, ... }); var sectionDescription = new Text2('', { size: 50, ... }); 👉 Increase them by 50%: 56 → 84 50 → 75 🔎 3. Herb & Fungi Descriptions (Journal) These also use sectionDescription (above). Since we’re scaling that, herbs, fungi, and bases all benefit. ✅ 🔎 5. Table of Contents Buttons & Text Inside JournalPopup:👉 Change 48 → 72 Also update the buttons themselves (they’re 500x120). To keep balance, scale height too:height: 120 → 180 ✅ Consolidated Edits Tea Base Popup (window): size: 72 Journal Section Texts: sectionType → 84 sectionElement → 84 sectionDescription → 75 Table of Contents texts: size: 72 Table of Contents button height: 120 → 180
User prompt
✅ Fix: Allow herbs to “add” to the cure rather than block it Instead of exact set matching, we should check whether the brew contains at least all the required elements. function containsAll(required, brewed) { for (var i = 0; i < required.length; i++) { if (brewed.indexOf(required[i]) === -1) { return false; } } return true; } var cureOK = containsAll(required, brewed); Example required = ["fire"] brewed = ["fire","earth"] containsAll → true ✅
User prompt
Use a bright highlight tint (e.g. 0xFFD700 gold or 0x00FF00 green). Add a stronger “grab pop” animation so it feels more obvious. var bg = ghost.attachAsset('craftButton', { ... tint: 0xFFD700, // bright gold highlight when grabbed alpha: 0.9 }); and pump the grab animation a little more: tween(ghost, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100 }); The drag doesn’t start until the player moves 22 pixels (DRAG_THRESHOLD = 22). That’s a large threshold, so sometimes clicks don’t cross it and it feels like the item won’t pick up. 👉 Fix: Lower the threshold to make drag detection more sensitive: var DRAG_THRESHOLD = 8; // instead of 22 ✅ Suggested changes Highlight color: Make grabbed ghost use gold/green and higher alpha. Animation: Stronger scaling so it “pops” into the hand. Sensitivity: Reduce DRAG_THRESHOLD from 22 → 8. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
when player fails to cure and reputation points are lost, play failure sfx
User prompt
decrease RESET button by 50% Randomize the patient graphics between patient, patient1, and patient2 When player successfully cures patient, play success sfx
User prompt
move the patient graphics down by 100px enlarge the EMPTY button for the cauldron by 100% Enlarge the REPUTATION meter text and meter by 100% Enlarge the RESET button by 200% ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
2) Journal button visible on wrong layers Make overlay always sit on top Right after you create the journal button, bump the overlay to the front: // after creating `journalButton` game.removeChild(overlayLayer); game.addChild(overlayLayer); // ensure overlay & popups are above HUD buttons Hide the journal button whenever any popup is open // Keep originals var _showMenu = popupMenu.showMenu; popupMenu.showMenu = function(title, items, colors) { _showMenu.call(popupMenu, title, items, colors); refreshHUD(); }; var _hideMenu = popupMenu.hideMenu; popupMenu.hideMenu = function() { _hideMenu.call(popupMenu); refreshHUD(); }; Do the same for the herb details popup and journal popup (their constructors live in the same overlay block as showMenu/hideMenu) so any overlayed UI hides the journal button until closed
User prompt
1) Fix wrong herb/base combos “working” Change it to an exact, order-agnostic set match: // put this helper once (above craftPotion is fine) function arraysSameSet(a, b) { if (!Array.isArray(a) || !Array.isArray(b)) return false; if (a.length !== b.length) return false; var seen = Object.create(null); for (var i = 0; i < a.length; i++) seen[a[i]] = 1; for (var j = 0; j < b.length; j++) if (!seen[b[j]]) return false; return true; } Then, in each copy of craftPotion(): var cureOK = arraysSameSet(required, brewed);
User prompt
change the reputation score to a horizontal meter that fills and/or depletes as the score changes ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
change the name of the start over button to EMPTY and move it to the bottom part of the cauldron graphic. it should sit in front of the the cauldron graphic
User prompt
✅ Fix: Increase Herb List Font Size Let’s bump that font size up (say 48) so it’s consistent with your Tea Bases text and easier to read: // Create centered button text - larger for better visibility var buttonText = new Text2(items[i], { size: 48, // was 36 fill: 0xFFFFFF }); always guarantee popups (journal, herb popup, etc.) appear above other UI, you can create a UI overlay layer and add them there: // Create a top-level overlay container var overlayLayer = new Container(); game.addChild(overlayLayer); // Create journal popup inside overlay var journalPopup = overlayLayer.addChild(new JournalPopup()); var herbPopup = overlayLayer.addChild(new HerbPopup()); Move the reputation score from the top left corner to the bottom left corner move the SERVE button above the START OVER button and ensure they do not overlap
User prompt
play associated success sfx when patient is cured, and play associated fail sfx when the tea served fails to cure the patient
User prompt
2. Replace with your new sound files Instead of the placeholder success / failure sounds, we’ll initialize your custom MP3s. Change the sound init section: LK.init.sound('success', { id: 'fantasy_game_success_notification___sound_effects_hd__no_copyright_sound_.mp3' }); LK.init.sound('failure', { id: 'fantasy_failure_sound_effect.mp3' }); ⚠️ Make sure those MP3 files are in your assets/sounds folder (or wherever LK expects them). The {id: '...'} should match the filename without path if your loader knows the asset folder, or full path if not. 3. Keep existing play logic ✅ After this change: When a patient is cured → "fantasy_game_success_notification..." plays. When cure fails → "fantasy_failure_sound_effect.mp3" plays.
User prompt
center the TEA BASES, HERBS, AND JOURNAL buttons all horizontally
User prompt
✅ Fix: Clear and respawn a patient You want the reset button to: Reset reputation + score. Clear any existing patient. Immediately spawn a new patient. Here’s the corrected reset logic: resetButton.down = function (x, y, obj) { reputation = 100; currentScore = 0; reputationText.setText('Reputation: ' + reputation); // ✅ Clear current patient currentPatient = null; isProcessingTreatment = false; // ✅ Force a new patient immediately spawnNewPatient(); }; 2. Fix asymmetry (center all 3 horizontally) Instead of 2 buttons left and 1 button way off right, we’ll arrange them in a row centered at the bottom (same y as TEA BASES and HERBS). Then: TEA BASES → x = startX HERBS → x = startX + (buttonWidth + buttonSpacing) JOURNAL → x = startX + 2 * (buttonWidth + buttonSpacing) And make JOURNAL button same size as the others:var journalButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: startX + 2 * (buttonWidth + buttonSpacing), y: buttonY, width: buttonWidth, height: buttonHeight, tint: 0x444444 }); var journalButtonText = new Text2('JOURNAL', { size: 48, // match others fill: 0xFFFFFF }); journalButtonText.anchor.set(0.5, 0.5); journalButtonText.x = startX + 2 * (buttonWidth + buttonSpacing); journalButtonText.y = buttonY; game.addChild(journalButtonText); This ensures all 3 are in the same layer (bottom ingredient layer), side by side, centered. ✅ var patientStatusText = new Text2('Welcome! A patient awaits...', { size: 70, // increased from 42 fill: 0xFFFFFF, align: 'center' });
User prompt
✅ Fix When the player fails, we should: Deduct reputation (already done). Clear out the patient. Start a cooldown before the next patient spawns (same way you handle success). Corrected failure block Replace your failure case with this: else { // ❌ Wrong tea → penalty, patient leaves repChange = -20; tween(patient, { tint: 0xFF6666 }, { duration: 1000 }); LK.getSound('failure').play(); patientStatusText.setText("That didn't work... -" + Math.abs(repChange) + " reputation"); // ✅ Remove patient and start timer for next one currentPatient = null; treatmentTimer = LK.ticks + 120; // delay before next patient } Why this works currentPatient = null; → signals that the slot is free. treatmentTimer is already handled in your game.update loop:if (isProcessingTreatment && LK.ticks >= treatmentTimer) { isProcessingTreatment = false; currentPatient = null; patientStatusText.setText('Next patient incoming...'); patientTimer = 0; } So the system will automatically queue the next patient after a short wait, same as success.
User prompt
make the hint box resize itself every time the text changes. ✅ Fix: Auto-resize the box Define a helper function so you don’t have to repeat the logic everywhere: function updateHintBox() { // Resize width and height based on text size hintBox.width = patientStatusText.width + 80; // padding left/right hintBox.height = patientStatusText.height + 40; // padding top/bottom // Keep box centered with the text hintBox.x = patientStatusText.x; hintBox.y = patientStatusText.y; } Where to call it In spawnNewPatient(), right after: patientStatusText.setText(symptom); updateHintBox(); In craftPotion(), after every line where you do: patientStatusText.setText("Patient cured! +" + repChange + " reputation"); updateHintBox(); patientStatusText.setText("That didn't work... -" + Math.abs(repChange) + " reputation"); updateHintBox(); patientStatusText.setText("Invalid brew! -" + Math.abs(repChange) + " reputation"); updateHintBox(); Also after resets, like in the Start Over button: patientStatusText.setText('Tea mixture cleared. Start fresh!'); updateHintBox(); Result Now the black box (hintBox) will grow or shrink to perfectly fit the text, instead of cutting off long statements or leaving excess space for short ones.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var HerbPopup = Container.expand(function () { var self = Container.call(this); // Semi-transparent background overlay var overlay = self.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, alpha: 0.8, tint: 0x000000 }); // Main popup window - larger and centered var popupWindow = self.attachAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: 1600, height: 1000, tint: 0x8B4513 }); // Close button (X) - larger var closeButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1700, y: 950, width: 120, height: 120, tint: 0xFF0000 }); var closeButtonText = new Text2('X', { size: 80, fill: 0xFFFFFF }); closeButtonText.anchor.set(0.5, 0.5); closeButtonText.x = 1700; closeButtonText.y = 950; self.addChild(closeButtonText); // Herb name title - much larger var nameText = new Text2('', { size: 72, fill: 0xFFFFFF }); nameText.anchor.set(0.5, 0.5); nameText.x = 1024; nameText.y = 1050; self.addChild(nameText); // Type text (Plant/Fungus) var typeText = new Text2('', { size: 48, fill: 0xFFD700 }); typeText.anchor.set(0.5, 0.5); typeText.x = 1024; typeText.y = 1150; self.addChild(typeText); // Element text - larger var elementText = new Text2('', { size: 52, fill: 0xFFFFFF }); elementText.anchor.set(0.5, 0.5); elementText.x = 1024; elementText.y = 1250; self.addChild(elementText); // Description text - much larger and wrapped var descriptionText = new Text2('', { size: 40, fill: 0xFFFFFF }); descriptionText.anchor.set(0.5, 0.5); descriptionText.x = 1024; descriptionText.y = 1500; self.addChild(descriptionText); self.isVisible = false; self.showPopup = function (herbName, x, y) { var herbData = HERB_DATA[herbName]; if (!herbData) return; nameText.setText(herbName); typeText.setText(herbData.type); elementText.setText('Element: ' + herbData.alignment); // Wrap long descriptions var wrappedDesc = wrapTextByWords(herbData.description, 50); descriptionText.setText(wrappedDesc); // Color the element text based on alignment var color = colorForAlignment(herbData.alignment); elementText.tint = color; self.visible = true; self.isVisible = true; }; self.hidePopup = function () { self.visible = false; self.isVisible = false; }; // Close button handler closeButton.down = function (x, y, obj) { self.hidePopup(); }; // Overlay click to close overlay.down = function (x, y, obj) { self.hidePopup(); }; // Start hidden self.visible = false; return self; }); // Shop button event handler removed per requirements // === Herbalist's Journal with Table of Contents === var JournalPopup = Container.expand(function () { var self = Container.call(this); // Semi-transparent background overlay var overlay = self.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, alpha: 0.8, tint: 0x000000 }); // Main journal window - 75% of screen var journalWindow = self.attachAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: 1536, // 75% of 2048 height: 2050, // 75% of 2732 tint: 0xfdf6e3 }); // Close button (X) var closeButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1700, y: 500, width: 60, height: 60, tint: 0xFF0000 }); var closeButtonText = new Text2('✕', { size: 40, fill: 0xFFFFFF }); closeButtonText.anchor.set(0.5, 0.5); closeButtonText.x = 1700; closeButtonText.y = 500; self.addChild(closeButtonText); // Table of Contents View var contentsTitle = new Text2('Herbalist\'s Journal', { size: 64, fill: 0x000000 }); contentsTitle.anchor.set(0.5, 0.5); contentsTitle.x = 1024; contentsTitle.y = 650; self.addChild(contentsTitle); var contentsSubtitle = new Text2('Contents', { size: 48, fill: 0x444444 }); contentsSubtitle.anchor.set(0.5, 0.5); contentsSubtitle.x = 1024; contentsSubtitle.y = 750; self.addChild(contentsSubtitle); // Content section buttons - improved styling var herbsContentButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 950, width: 500, // Increased width height: 120, // Increased height tint: 0x222222 // Dark background for contrast }); var herbsContentText = new Text2('Herbs & Fungi', { size: 48, // Increased from 40 fill: 0xFFFFFF // White text for contrast }); herbsContentText.anchor.set(0.5, 0.5); herbsContentText.x = 1024; herbsContentText.y = 950; self.addChild(herbsContentText); var basesContentButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1100, width: 500, // Increased width height: 120, // Increased height tint: 0x222222 // Dark background for contrast }); var basesContentText = new Text2('Tea Bases', { size: 48, // Increased from 40 fill: 0xFFFFFF // White text for contrast }); basesContentText.anchor.set(0.5, 0.5); basesContentText.x = 1024; basesContentText.y = 1100; self.addChild(basesContentText); var illnessesContentButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1250, width: 500, // Increased width height: 120, // Increased height tint: 0x222222 // Dark background for contrast }); var illnessesContentText = new Text2('Illnesses', { size: 48, // Increased from 40 fill: 0xFFFFFF // White text for contrast }); illnessesContentText.anchor.set(0.5, 0.5); illnessesContentText.x = 1024; illnessesContentText.y = 1250; self.addChild(illnessesContentText); // Section View Elements (hidden initially) var sectionTitle = new Text2('', { size: 80, // larger fill: 0x000000, // darker fontWeight: 'bold' }); sectionTitle.anchor.set(0.5, 0.5); sectionTitle.x = 1024; sectionTitle.y = 750; self.addChild(sectionTitle); var sectionType = new Text2('', { size: 56, // larger fill: 0x006400 // dark green }); sectionType.anchor.set(0.5, 0.5); sectionType.x = 1024; sectionType.y = 880; self.addChild(sectionType); var sectionElement = new Text2('', { size: 56, fill: 0x000000 // darker, readable }); sectionElement.anchor.set(0.5, 0.5); sectionElement.x = 1024; sectionElement.y = 1000; self.addChild(sectionElement); var sectionDescription = new Text2('', { size: 50, // substantially larger fill: 0x000000, // darker align: 'center' }); sectionDescription.anchor.set(0.5, 0); sectionDescription.x = 1024; sectionDescription.y = 1150; self.addChild(sectionDescription); // Navigation buttons for sections var backToContentsButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 750, y: 2200, width: 300, height: 100, tint: 0x222222 }); var backToContentsText = new Text2('⬅ Back', { size: 42, fill: 0xFFFFFF }); backToContentsText.anchor.set(0.5, 0.5); backToContentsText.x = 750; backToContentsText.y = 2200; self.addChild(backToContentsText); var nextEntryButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1300, y: 2200, width: 300, height: 100, tint: 0x222222 }); var nextEntryText = new Text2('Next ➡', { size: 42, fill: 0xFFFFFF }); nextEntryText.anchor.set(0.5, 0.5); nextEntryText.x = 1300; nextEntryText.y = 2200; self.addChild(nextEntryText); // State management self.currentView = 'contents'; // 'contents' or 'section' self.currentSection = ''; self.currentIndex = 0; self.journalData = { herbs: Object.keys(HERB_DATA), teaBases: Object.keys(teaBases), illnesses: Object.keys(ILLNESS_DATA) }; self.isVisible = false; // Show/hide content elements self.showContents = function () { self.currentView = 'contents'; // Show contents elements contentsTitle.visible = true; contentsSubtitle.visible = true; herbsContentButton.visible = true; herbsContentText.visible = true; basesContentButton.visible = true; basesContentText.visible = true; illnessesContentButton.visible = true; illnessesContentText.visible = true; // Hide section elements sectionTitle.visible = false; sectionType.visible = false; sectionElement.visible = false; sectionDescription.visible = false; backToContentsButton.visible = false; backToContentsText.visible = false; nextEntryButton.visible = false; nextEntryText.visible = false; }; self.showSection = function (section) { self.currentView = 'section'; self.currentSection = section; self.currentIndex = 0; // Hide contents elements contentsTitle.visible = false; contentsSubtitle.visible = false; herbsContentButton.visible = false; herbsContentText.visible = false; basesContentButton.visible = false; basesContentText.visible = false; illnessesContentButton.visible = false; illnessesContentText.visible = false; // Show section elements sectionTitle.visible = true; sectionType.visible = true; sectionElement.visible = true; sectionDescription.visible = true; backToContentsButton.visible = true; backToContentsText.visible = true; nextEntryButton.visible = true; nextEntryText.visible = true; self.updateSectionContent(); }; self.updateSectionContent = function () { var entries = self.journalData[self.currentSection]; var entry = entries[self.currentIndex]; if (self.currentSection === 'herbs') { var herbData = HERB_DATA[entry]; sectionTitle.setText(entry.toUpperCase()); sectionType.setText(herbData.type); sectionElement.setText("Element: " + herbData.alignment); sectionDescription.setText(wrapTextByWords(herbData.description, 60)); } else if (self.currentSection === 'teaBases') { var baseData = teaBases[entry]; sectionTitle.setText(entry.toUpperCase()); sectionType.setText("Tea Base"); sectionElement.setText("Element: " + baseData.element.charAt(0).toUpperCase() + baseData.element.slice(1)); sectionDescription.setText(wrapTextByWords("A light base for brewing teas, often combined with matching herbs.", 60)); } else if (self.currentSection === 'illnesses') { var illnessData = ILLNESS_DATA[entry]; sectionTitle.setText(illnessData.name.toUpperCase()); sectionType.setText("Illness"); var elementText = "Element: "; for (var i = 0; i < illnessData.element_imbalance.length; i++) { if (i > 0) elementText += " + "; elementText += illnessData.element_imbalance[i].charAt(0).toUpperCase() + illnessData.element_imbalance[i].slice(1); } sectionElement.setText(elementText); var cureText = "Cure: Use "; for (var i = 0; i < illnessData.element_imbalance.length; i++) { if (i > 0) cureText += " + "; cureText += illnessData.element_imbalance[i]; } cureText += " base with herbs."; var desc = "Description: " + illnessData.description + "\n\n" + cureText; sectionDescription.setText(wrapTextByWords(desc, 60)); } }; self.nextEntry = function () { var entries = self.journalData[self.currentSection]; if (self.currentIndex < entries.length - 1) { self.currentIndex++; } else { self.currentIndex = 0; // Loop back to first } self.updateSectionContent(); }; self.showJournal = function () { self.visible = true; self.isVisible = true; self.showContents(); }; self.hideJournal = function () { self.visible = false; self.isVisible = false; }; // Button handlers herbsContentButton.down = function (x, y, obj) { self.showSection('herbs'); }; basesContentButton.down = function (x, y, obj) { self.showSection('teaBases'); }; illnessesContentButton.down = function (x, y, obj) { self.showSection('illnesses'); }; backToContentsButton.down = function (x, y, obj) { self.showContents(); }; nextEntryButton.down = function (x, y, obj) { self.nextEntry(); }; // Close button handler closeButton.down = function (x, y, obj) { self.hideJournal(); }; // Overlay click to close overlay.down = function (x, y, obj) { self.hideJournal(); }; // Start hidden self.visible = false; return self; }); // Create journal popup var Patient = Container.expand(function () { var self = Container.call(this); var patientBody = self.attachAsset('patient', { anchorX: 0.5, anchorY: 0.5 }); // symptomGlow moved to main game - reference will be set externally self.symptomGlow = null; self.symptomType = ''; self.requiredBase = ''; self.requiredElement = ''; self.requiredHerb = ''; self.goldReward = 0; self.setSymptom = function (type) { self.symptomType = type; var illness = ILLNESS_DATA[type]; if (illness) { if (self.symptomGlow) self.symptomGlow.tint = illness.symptom_color; self.element_imbalance = illness.element_imbalance; self.goldReward = illness.gold_reward; self.illnessName = illness.name; self.description = illness.description; } }; // reactToPotion method removed - cure logic now handled in craftPotion function return self; }); var PopupMenu = Container.expand(function () { var self = Container.call(this); // Semi-transparent background overlay var overlay = self.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, alpha: 0.7, tint: 0x000000 }); // Main popup window - 75% of screen size var popupWindow = self.attachAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, width: 1536, // 75% of 2048 height: 2050, // 75% of 2732 tint: 0x8B4513 }); // Close button (X) var closeButton = self.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1600, y: 600, width: 80, height: 80, tint: 0xFF0000 }); var closeButtonText = new Text2('X', { size: 40, fill: 0xFFFFFF }); closeButtonText.anchor.set(0.5, 0.5); closeButtonText.x = 1600; closeButtonText.y = 600; self.addChild(closeButtonText); // Title text - larger for better visibility var titleText = new Text2('', { size: 72, // Increased from 50 to 72 fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 700; self.addChild(titleText); self.menuItems = []; self.isVisible = false; self.showMenu = function (title, items, itemColors) { titleText.setText(title); self.visible = true; self.isVisible = true; // Clear existing menu items for (var i = 0; i < self.menuItems.length; i++) { game.removeChild(self.menuItems[i]); } self.menuItems = []; // Special layout for Tea Bases (centered vertical stack) if (title.indexOf('TEA BASES') !== -1) { var buttonWidth = 800; // 60% of screen width (1536 * 0.6) var buttonHeight = 120; var buttonSpacing = 40; var startY = 1000; for (var i = 0; i < items.length; i++) { var y = startY + i * (buttonHeight + buttonSpacing); // Create button-style container var menuItem = new Container(); menuItem.x = 1024; // Center horizontally menuItem.y = y; game.addChild(menuItem); // Create button background var buttonBg = menuItem.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, width: buttonWidth, height: buttonHeight, tint: 0x1a237e // Deep blue for tea bases }); // Create centered button text var buttonText = new Text2(items[i], { size: 48, // Larger text for tea bases fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 0; buttonText.y = 0; menuItem.addChild(buttonText); menuItem.name = items[i]; menuItem.draggable = true; menuItem.type = 'ingredient'; menuItem.isDragging = false; menuItem.originalX = 1024; menuItem.originalY = y; menuItem.isMenuPurchase = true; menuItem.cost = 50; self.menuItems.push(menuItem); } } else { // Regular grid layout for other items (herbs, etc.) var itemsPerRow = 3; var buttonWidth = 400; var buttonHeight = 120; var buttonSpacing = 60; var totalRowWidth = itemsPerRow * buttonWidth + (itemsPerRow - 1) * buttonSpacing; var startX = 1024 - totalRowWidth / 2 + buttonWidth / 2; var startY = 1050; var rowSpacing = 150; for (var i = 0; i < items.length; i++) { var row = Math.floor(i / itemsPerRow); var col = i % itemsPerRow; var x = startX + col * (buttonWidth + buttonSpacing); var y = startY + row * rowSpacing; // Create button-style container var menuItem = new Container(); menuItem.x = x; menuItem.y = y; game.addChild(menuItem); // Create button background var buttonBg = menuItem.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, width: buttonWidth, height: buttonHeight, tint: itemColors[i] || 0x8B4513 }); // Create centered button text - larger for better visibility var buttonText = new Text2(items[i], { size: 36, // Increased from 28 to 36 fill: 0xFFFFFF }); buttonText.anchor.set(0.5, 0.5); buttonText.x = 0; buttonText.y = 0; menuItem.addChild(buttonText); menuItem.name = items[i]; menuItem.draggable = true; menuItem.type = 'ingredient'; menuItem.isDragging = false; menuItem.originalX = x; menuItem.originalY = y; menuItem.isMenuPurchase = true; menuItem.cost = 50; // Cost to purchase from menu self.menuItems.push(menuItem); } } }; self.hideMenu = function () { self.visible = false; self.isVisible = false; // Remove menu items for (var i = 0; i < self.menuItems.length; i++) { game.removeChild(self.menuItems[i]); } self.menuItems = []; }; self.showDetails = function (itemName) { if (HERB_DATA[itemName]) { herbPopup.showPopup(itemName, 0, 0); } }; // Close button handler closeButton.down = function (x, y, obj) { self.hideMenu(); }; // Overlay click to close overlay.down = function (x, y, obj) { self.hideMenu(); }; // Start hidden self.visible = false; return self; }); var PotionBottle = Container.expand(function () { var self = Container.call(this); var bottle = self.attachAsset('potionBottle', { anchorX: 0.5, anchorY: 0.5 }); self.setColor = function (base, element, herb) { var color = 0x87CEEB; if (element === 'fire') color = 0xFF6B6B;else if (element === 'water') color = 0x6BB6FF;else if (element === 'earth') color = 0x8B4513;else if (element === 'wind') color = 0xE6E6FA; bottle.tint = color; tween(bottle, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, onFinish: function onFinish() { tween(bottle, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2F4F2F }); /**** * Game Code ****/ // Add global button styling var buttonStyle = { fontSize: 20, padding: "12px 24px", borderRadius: 10, backgroundColor: "#444", color: "white", cursor: "pointer" }; var gameBackground = game.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); // === Tap vs Drag state === var downItemCandidate = null; var downStartX = 0, downStartY = 0; var DRAG_THRESHOLD = 22; // px movement to start dragging // helper: rectangular hit test function hitRect(x, y, cx, cy, halfW, halfH) { return Math.abs(x - cx) <= halfW && Math.abs(y - cy) <= halfH; } function createDragGhostFromMenu(name, color, cost, startX, startY) { var ghost = new Container(); ghost.x = startX; ghost.y = startY; game.addChild(ghost); var bg = ghost.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, tint: color, width: 220, height: 100 }); var txt = new Text2(name, { size: 44, fill: 0xFFFFFF }); txt.anchor.set(0.5, 0.5); txt.x = 0; txt.y = 0; ghost.addChild(txt); ghost.name = name; ghost.isDragging = true; ghost.isMenuPurchase = true; ghost.cost = 0; ghost.dragOffsetX = 0; ghost.dragOffsetY = 0; // subtle pop so it feels grabbed tween(ghost, { scaleX: 1.08, scaleY: 1.08 }, { duration: 120 }); return ghost; } var reputation = 100; var currentScore = 0; var currentPatient = null; var isProcessingTreatment = false; // Menu buttons are already implemented at the top of the screen: // - Instructions button (blue) at x=400, y=100 // - New Game button (red) at x=1024, y=100 // - Shop button (green) at x=1648, y=100 // All buttons have proper styling, text labels, and event handlers // HUD / TOP BAR LAYER var reputationText = new Text2('Reputation: ' + reputation, { size: 60, fill: 0xFFD700 }); reputationText.anchor.set(0, 0); reputationText.x = 120; reputationText.y = 50; LK.gui.topLeft.addChild(reputationText); // CENTER LAYER - Patient + Cauldron + Dialogue var patient = game.addChild(new Patient()); patient.x = 1024; patient.y = 500; // Moved up to create space for hint text below // Create symptom indicator positioned near patient var symptomIndicator = game.attachAsset('symptomIndicator', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 700 }); // Link symptom indicator to patient patient.symptomGlow = symptomIndicator; // Patient status text with background - positioned below patient portrait var hintBox = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1050, width: 800, height: 120, tint: 0x222222, alpha: 0.9 }); // Hint text var patientStatusText = new Text2('Welcome! A patient awaits...', { size: 70, // increased from 42 fill: 0xFFFFFF, align: 'center' }); patientStatusText.anchor.set(0.5, 0.5); patientStatusText.x = 1024; patientStatusText.y = 1050; game.addChild(patientStatusText); // Potion Bottle positioned near cauldron var potionBottle = game.addChild(new PotionBottle()); potionBottle.x = 1024; potionBottle.y = 1100; potionBottle.visible = false; // Start hidden // BOTTOM LAYER - Ingredient Buttons + Craft Button (craft button moved after counter layer) // Wheel labels and selection display removed // Illness definitions with element imbalances and cure rules var ILLNESS_DATA = { "hollowshiver": { id: "hollowshiver", name: "Hollowshiver", description: "A creeping cold that settles in the bones, no matter how many blankets are piled on. Common after wandering too long near mushroom circles or in moonlit glades. Warming the body will help.", temperature: "Cold", causes: ["Getting too cold", "Too many water herbs", "Swimming in cold waters"], cure: "Brew fire-aligned broth with Kitty Mitten, Sommeral, or Brindleroot", symptoms: ["I took a swim, but the water was so cold…", "I feel a cold damp in my bones…"], element_imbalance: ["fire"], symptom_color: 0x4444FF, gold_reward: 120 }, "driftlimb": { id: "driftlimb", name: "Driftlimb", description: "A peculiar tiredness that makes even teacups feel too heavy. Believed to come from skipping too many meals or carrying burdens not your own. A wind-based approach will help uplift the body.", temperature: "Normal", causes: ["Working too hard", "Being ill for a long time"], cure: "Brew wind-aligned tea with Fuzzy Peeper, Demeter's Arrow or Pipeweed", symptoms: ["I've been working so hard lately, my arms feel so heavy…", "I feel like I have no muscles in my legs…"], element_imbalance: ["wind"], symptom_color: 0xFFFF44, gold_reward: 130 }, "greyheart": { id: "greyheart", name: "Greyheart", description: "A sadness with no clear shape. Often spoken of in hushed tones as the malaise of quiet souls or lonely seasons. To heal Greyheart, one must nourish the body, warm the limbs, and lift the spirit at the same time.", temperature: "Normal", causes: ["Tragedy of the heart", "Ennui"], cure: "Earthy Tea Base with Kitty Mitten and Demeter's Arrow", symptoms: ["I feel so low. As if I'm haunted somehow by the troubles of my past…", "This weather has been hard for me… I feel so… I don't know.", "I feel as if I've been flattened or hollowed out. Something is missing and I don't know what…"], element_imbalance: ["earth"], symptom_color: 0x888888, gold_reward: 140 }, "the_wilt": { id: "the_wilt", name: "The Wilt", description: "When one's spirit feels dim and steps feel cloud-soft. A common complaint after long travels or encounters with annoying relatives. The wilt requires a wind based tea.", temperature: "Normal", causes: ["Not sleeping enough", "Over excitement"], cure: "Uplifting Tea Base with Demeter's Arrow and Fuzzy Peeper", symptoms: ["I'm so tired no matter how much I sleep."], element_imbalance: ["wind"], symptom_color: 0xAAAAFF, gold_reward: 110 }, "wretching_waters": { id: "wretching_waters", name: "Wretching Waters", description: "A twisting in the gut, often after eating something wild or questionably cooked. One needs a strong, nourishing broth.", temperature: "Hot", causes: ["Rotten food", "Ingesting poisonous fungi"], cure: "Earthy Tea Base with Sheep's Bane and Common Snupe", symptoms: ["I've been in the bathroom all morning!", "My stomach…. uurrgghhh…"], element_imbalance: ["earth"], symptom_color: 0x44FF44, gold_reward: 150 }, "unmovable_phlegm": { id: "unmovable_phlegm", name: "Unmovable Phlegm", description: "More irritating than dangerous, this thick muck often makes sleep difficult. A combination of heat and wind is necessary to clear it.", temperature: "Normal", causes: ["Pollen exposure", "Allergies to animals"], cure: "Spicy Tea Base with Demeter's Arrow and Fuzzy Peeper", symptoms: ["I can't stop sneezing since I went to that petting zoo!", "I feel like I can't breathe, especially at night.", "This dust in the air is making me feel awful!"], element_imbalance: ["fire", "wind"], symptom_color: 0xFFCC44, gold_reward: 125 }, "dagger_hex": { id: "dagger_hex", name: "Dagger Hex", description: "A stiffness that clings to joints and limbs like thistleburs. Believed to follow poor posture or sleeping under cursed trees. Heat and nourish the body to encourage healing.", temperature: "Normal", causes: ["Overexertion"], cure: "Spicy Tea Base with Sheep's Bane and Common Snupe", symptoms: ["I've got this pain in my back!", "Ack! My neck is killing me. I've been working too hard…"], element_imbalance: ["fire"], symptom_color: 0xFF8844, gold_reward: 135 }, "witchrattle": { id: "witchrattle", name: "Witchrattle", description: "A dry, scratchy cough that echoes oddly through the throat. Caught mostly in deep winter and under cold moons. The treatment must warm the body but cool the throat.", temperature: "Cold", causes: ["Getting too cold", "Contact with sick people"], cure: "Spicy Tea Base with Frogwick and Geneva's Dewdrop or River Leek", symptoms: ["Hack hack! Excuse my cough!", "These frosty evenings have been so hard on my lungs…"], element_imbalance: ["fire"], symptom_color: 0x99CCFF, gold_reward: 120 }, "twiddlecurse": { id: "twiddlecurse", name: "Twiddlecurse", description: "A jittery, jumpy itch in the fingers and feet. Common among those plagued by tragedies or nightmares. A cooling tea is required.", temperature: "Normal", causes: ["Stress", "Too many wind-aligned herbs"], cure: "Cooling Tea Base with Geneva's Dewdrop and Frogwick", symptoms: ["Demeter's Arrow is so good but I think I had too many…", "I'm so restless lately, I can't stop fidgeting!"], element_imbalance: ["water"], symptom_color: 0x66CCFF, gold_reward: 115 }, "purging_rot": { id: "purging_rot", name: "Purging Rot", description: "A slow-burning ailment marked by greenish skin and sweating. Often follows the consumption of misidentified mushrooms or cursed teas. Expel the rot but make sure to also nourish the body.", temperature: "Hot", causes: ["Poisonous mushrooms", "Cursed teas"], cure: "Uplifting Tea Base with Sheep's Bane and Common Snupe", symptoms: ["I must have eaten something that went bad…", "Purple mushrooms are safe to eat… right?"], element_imbalance: ["wind"], symptom_color: 0x77DD77, gold_reward: 160 } }; var symptoms = Object.keys(ILLNESS_DATA); var patientTimer = 0; var treatmentTimer = 0; function updateHintBox() { // Resize width and height based on text size hintBox.width = patientStatusText.width + 80; // padding left/right hintBox.height = patientStatusText.height + 40; // padding top/bottom // Keep box centered with the text hintBox.x = patientStatusText.x; hintBox.y = patientStatusText.y; } function spawnNewPatient() { if (currentPatient) return; var randomSymptom = symptoms[Math.floor(Math.random() * symptoms.length)]; patient.setSymptom(randomSymptom); currentPatient = randomSymptom; var illness = ILLNESS_DATA[randomSymptom]; if (illness) { var symptom = illness.symptoms[Math.floor(Math.random() * illness.symptoms.length)]; patientStatusText.setText(symptom); updateHintBox(); } else { patientStatusText.setText('A new patient has arrived!'); updateHintBox(); } tween(patient, { scaleX: 1.1, scaleY: 1.1 }, { duration: 500, onFinish: function onFinish() { tween(patient, { scaleX: 1, scaleY: 1 }, { duration: 500 }); } }); } // updateSelectionDisplay function removed function brewTea(baseName, herb1Name, herb2Name) { if (!teaBases[baseName]) return null; var base = teaBases[baseName]; var herb1 = HERB_DATA[herb1Name]; var herb2 = HERB_DATA[herb2Name]; if (!herb1 || !herb2 || herb1Name === herb2Name) return null; // Gather all elements in the mix var elements = [base.element, herb1.element, herb2.element]; // Pure tea (all the same element) if (herb1.element === herb2.element && herb1.element === base.element) { return { name: base.name + " + " + herb1Name + " + " + herb2Name, elements: [base.element] }; } // Hybrid tea (mixed elements) var uniqueElements = []; for (var i = 0; i < elements.length; i++) { if (uniqueElements.indexOf(elements[i]) === -1) { uniqueElements.push(elements[i]); } } return { name: base.name + " + " + herb1Name + " + " + herb2Name, elements: uniqueElements }; } function craftPotion() { if (!currentPatient || isProcessingTreatment || cauldron.ingredients.length !== 3) { return; } isProcessingTreatment = true; var baseName = cauldron.ingredients[0]; var herb1Name = cauldron.ingredients[1]; var herb2Name = cauldron.ingredients[2]; var brewedTea = brewTea(baseName, herb1Name, herb2Name); var repChange = 0; if (brewedTea) { var illness = ILLNESS_DATA[currentPatient]; if (illness) { var required = illness.element_imbalance; // always an array var brewed = brewedTea.elements; // ✅ NEW: check arrays using every method var cureOK = required.every(function (element) { return brewed.indexOf(element) !== -1; }); if (cureOK) { repChange = illness.gold_reward; tween(patient, { tint: 0x90EE90 }, { duration: 1000 }); LK.getSound('success').play(); // ✅ patient is cured → clear them currentPatient = null; patientStatusText.setText("Patient cured! +" + repChange + " reputation"); updateHintBox(); treatmentTimer = LK.ticks + 120; // delay before next patient } else { // ❌ Wrong tea → penalty, patient leaves repChange = -20; tween(patient, { tint: 0xFF6666 }, { duration: 1000 }); LK.getSound('failure').play(); patientStatusText.setText("That didn't work... -" + Math.abs(repChange) + " reputation"); updateHintBox(); // ✅ Remove patient and start timer for next one currentPatient = null; treatmentTimer = LK.ticks + 120; // delay before next patient } } } else { // Invalid tea combination (not a real brew) repChange = -10; // smaller penalty tween(patient, { tint: 0xFF6666 }, { duration: 1000 }); LK.getSound('failure').play(); patientStatusText.setText("Invalid brew! -" + Math.abs(repChange) + " reputation"); updateHintBox(); isProcessingTreatment = false; // allow retry } reputation += repChange; currentScore += Math.max(0, repChange); reputationText.setText('Reputation: ' + reputation); cauldron.ingredients = []; updateCauldronDisplay(); } var heldItem = null; var dragGhost = null; game.down = function (x, y, obj) { // If popup visible, prefer its items if (popupMenu.isVisible) { downItemCandidate = null; for (var i = popupMenu.menuItems.length - 1; i >= 0; i--) { var it = popupMenu.menuItems[i]; // rectangular hit for reliability var hw = (it.hitW || 120) / 2; var hh = (it.hitH || 120) / 2; if (hitRect(x, y, it.x, it.y, hw, hh)) { downItemCandidate = it; break; } } downStartX = x; downStartY = y; return; // wait to see if this becomes a tap or a drag } // Regular inventory items (unchanged) for (var i = inventoryItems.length - 1; i >= 0; i--) { var item = inventoryItems[i]; var dx = x - item.x, dy = y - item.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 50) { heldItem = item; item.isDragging = true; item.dragOffsetX = x - item.x; item.dragOffsetY = y - item.y; break; } } }; game.move = function (x, y, obj) { // Handle hover effects for tea base buttons if (popupMenu.isVisible && !heldItem && !downItemCandidate) { for (var i = popupMenu.menuItems.length - 1; i >= 0; i--) { var it = popupMenu.menuItems[i]; var hw = (it.hitW || 120) / 2; var hh = (it.hitH || 120) / 2; var isHovering = hitRect(x, y, it.x, it.y, hw, hh); // Apply hover effect for tea base buttons if (it.children[0] && it.children[0].tint === 0x1a237e) { // Tea base button if (isHovering && it.children[0].tint !== 0x3949ab) { it.children[0].tint = 0x3949ab; // Lighter blue on hover } else if (!isHovering && it.children[0].tint === 0x3949ab) { it.children[0].tint = 0x1a237e; // Return to original deep blue } } } } // If we have a candidate from popup and movement crosses threshold, start drag with a visible ghost if (downItemCandidate && !heldItem) { var moved = Math.sqrt((x - downStartX) * (x - downStartX) + (y - downStartY) * (y - downStartY)); if (moved > DRAG_THRESHOLD) { // Create infinite drag ghost (no cost check needed) var tint = downItemCandidate.children[0] ? downItemCandidate.children[0].tint : 0x1565C0; heldItem = dragGhost = createDragGhostFromMenu(downItemCandidate.name, tint, 0, x, y); heldItem.dragOffsetX = 0; heldItem.dragOffsetY = 0; } } // Move the active drag item (ghost or regular) if (heldItem && heldItem.isDragging) { heldItem.x = x - (heldItem.dragOffsetX || 0); heldItem.y = y - (heldItem.dragOffsetY || 0); } }; function createDragGhost(item) { if (dragGhost) { game.removeChild(dragGhost); } dragGhost = new Container(); dragGhost.x = item.x; dragGhost.y = item.y; game.addChild(dragGhost); // Ghost background with transparency var ghostBg = dragGhost.attachAsset('background', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, width: 150, height: 150, alpha: 0.7, tint: 0x444444 }); // Ghost text var ghostText = new Text2(item.name, { size: 28, fill: 0xFFFFFF }); ghostText.anchor.set(0.5, 0.5); ghostText.x = 0; ghostText.y = 0; dragGhost.addChild(ghostText); } function removeDragGhost() { if (dragGhost) { game.removeChild(dragGhost); dragGhost = null; } } game.up = function (x, y, obj) { // TAP on popup item -> show details (no drag started) if (downItemCandidate && !heldItem) { if (HERB_DATA[downItemCandidate.name]) { herbPopup.showPopup(downItemCandidate.name, x, y); } downItemCandidate = null; return; } downItemCandidate = null; // DROP logic (ghost from menu or regular inventory) if (heldItem) { heldItem.isDragging = false; // Calculate distance to cauldron var dx = heldItem.x - cauldron.x; var dy = heldItem.y - cauldron.y; var distance = Math.sqrt(dx * dx + dy * dy); // Menu purchase ghost dropped on cauldron if (heldItem.isMenuPurchase) { if (distance < 200 && cauldron.ingredients.length < 3) { cauldron.ingredients.push(heldItem.name); updateCauldronDisplay(); tween(cauldron, { tint: 0x44FF44 }, { duration: 200, onFinish: function onFinish() { tween(cauldron, { tint: 0xFFFFFF }, { duration: 200 }); } }); // remove ghost, keep popup open for multiple adds game.removeChild(heldItem); } else { // Not dropped in valid area -> cancel purchase, remove ghost game.removeChild(heldItem); } heldItem = null; dragGhost = null; return; } // Regular inventory item drop (unchanged) if (distance < 200 && cauldron.ingredients.length < 3) { cauldron.ingredients.push(heldItem.name); updateCauldronDisplay(); tween(cauldron, { tint: 0x44FF44 }, { duration: 200, onFinish: function onFinish() { tween(cauldron, { tint: 0xFFFFFF }, { duration: 200 }); } }); var itemIndex = inventoryItems.indexOf(heldItem); if (itemIndex > -1) { game.removeChild(heldItem); inventoryItems.splice(itemIndex, 1); } } else { tween(cauldron, { tint: 0xFF4444 }, { duration: 200, onFinish: function onFinish() { tween(cauldron, { tint: 0xFFFFFF }, { duration: 200 }); } }); resetItem(heldItem); } heldItem = null; } }; game.update = function () { patientTimer++; // Spawn new patient every 8 seconds if none exists if (!currentPatient && patientTimer % 480 === 0) { spawnNewPatient(); } // Clear patient after treatment if (isProcessingTreatment && LK.ticks >= treatmentTimer) { isProcessingTreatment = false; currentPatient = null; patientStatusText.setText('Next patient incoming...'); updateHintBox(); patientTimer = 0; } // Selection display update removed // Check for game over condition (reputation too low) if (reputation <= 0) { LK.showGameOver(); } // Check for win condition (high score) if (currentScore >= 2000) { LK.showYouWin(); } }; // Create draggable inventory items function createInventoryItem(name, x, y, color, isMenuItem) { var container = new Container(); container.x = x; container.y = y; game.addChild(container); // Use big rounded rectangles for menu items; bottles for inventory var assetType = isMenuItem ? 'craftButton' : 'potionBottle'; var item = container.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0, tint: color }); if (isMenuItem) { item.width = 220; item.height = 100; } else { // inventory representation can stay as-is } var label = new Text2(name, { size: isMenuItem ? 44 : 25, // bigger menu text - minimum 25px fill: 0xFFFFFF }); label.anchor.set(0.5, 0.5); label.x = 0; label.y = 0; container.addChild(label); // attach metadata (if this is a herb, we have more info) container.name = name; container.meta = HERB_DATA[name] || null; container.draggable = true; container.type = 'ingredient'; container.isDragging = false; container.originalX = x; container.originalY = y; // for rectangular hit test container.hitW = isMenuItem ? item.width : 120; container.hitH = isMenuItem ? item.height : 120; return container; } // Inventory labels removed - ingredients now accessed through category buttons var inventoryItems = []; // Tea Bases - each has an element alignment var teaBases = { "Uplifting Tea Base": { name: "Uplifting Tea Base", element: "wind" }, "Earthy Tea Base": { name: "Earthy Tea Base", element: "earth" }, "Cooling Tea Base": { name: "Cooling Tea Base", element: "water" }, "Spicy Tea Base": { name: "Spicy Tea Base", element: "fire" } }; var baseItems = Object.keys(teaBases); /**** * Herb Data & Helpers ****/ var HERB_DATA = { "Sheep Bane": { type: "Plant", alignment: "Earth", element: "earth", description: "A nourishing plant with small white flowers found in lush meadows with plenty of sunshine." }, "Fuzzy Peeper": { type: "Plant", alignment: "Wind", element: "wind", description: "A pale puffball perched on a long stem; it turns gently to face any breeze, no matter how faint." }, "Sommeral": { type: "Plant", alignment: "Fire", element: "fire", description: "A spiny red blossom that thrives in sun-scorched fields; its petals crackle faintly when crushed." }, "Common Snupe": { type: "Plant", alignment: "Earth", element: "earth", description: "A squat, stubby herb with ridged leaves and a sharp nutty scent—grows best near compost heaps and pig pens." }, "Geneva's Dewdrop": { type: "Plant", alignment: "Water", element: "water", description: "Delicate blue bulbs that drip a perpetual cool dew; said to be first planted by a weeping maiden." }, "Brindleroot": { type: "Plant", alignment: "Fire", element: "fire", description: "A twisted root that glows faintly from within—often brewed to stoke warmth into cold limbs." }, "Frogwick": { type: "Plant", alignment: "Water", element: "water", description: "Rubbery, semi-aquatic herb found near marshes—tastes awful but soothes the throat like magic." }, "Demeter's Arrow": { type: "Plant", alignment: "Wind", element: "wind", description: "Thin silvery leaves that grow in spirals. When burned, they produce a vapor that clears the lungs and bowels." }, "River Leek": { type: "Plant", alignment: "Water", element: "water", description: "A long, fragrant stalk that grows in riverside soil; its boiled leaves soothe fevers and dampen restlessness." }, "Pipeweed": { type: "Plant", alignment: "Wind", element: "wind", description: "Fragrant and slightly numbing, this herb is often smoked by hill witches and daydreaming farmhands." }, "Kitty Mitten": { type: "Plant", alignment: "Fire", element: "fire", description: "Soft red-orange fuzz covers these leaves, which are pleasantly warm to the touch. Cats love to nap on them." }, "Malicious Bule": { type: "Fungus", alignment: "Wind", element: "wind", description: "A pale fungus with twisting gills and a sweet, spoiled smell. It's said to whisper when the wind passes through a grove." }, "False Dunny Cap": { type: "Fungus", alignment: "Earth", element: "earth", description: "Often mistaken for its edible cousin, this fungus has a thick gray stalk and a damp cellar scent. Caution advised." }, "Callum's Perch": { type: "Fungus", alignment: "Earth", element: "earth", description: "Named for the druid who first brewed it into a sleep tonic, this squat, mossy mushroom grows on dead stumps in shadow." }, "Pinwort": { type: "Fungus", alignment: "Water", element: "water", description: "Soft and glossy with lilac-speckled caps, these fungi flourish in damp caves and give off a faint minty aroma." }, "Devil's Lantern": { type: "Fungus", alignment: "Fire", element: "fire", description: "This bioluminescent red fungus pulses with warmth. It grows in deep caverns and is rumored to attract fire spirits." }, "Lady's Teacup": { type: "Fungus", alignment: "Water", element: "water", description: "Shaped like a delicate bowl, often found filled with morning dew. Some fae insist it must only be harvested under moonlight." }, "Dead Man's Toe": { type: "Fungus", alignment: "Earth", element: "earth", description: "Black and bulbous, it pushes up from graveyard soil and smells of rust. Disturbing in appearance, yet grounding when dried." }, "Agarium": { type: "Fungus", alignment: "Earth", element: "earth", description: "Smooth and tan, with a satisfying snap when broken. This dependable fungus is a staple in many earthy decoctions." }, "Thimbliss": { type: "Fungus", alignment: "Wind", element: "wind", description: "Tiny, translucent caps that grow in clusters beneath bird nests. Harmless alone, but intensify the effects of other herbs." }, "Lesser Bluecap": { type: "Fungus", alignment: "Water", element: "water", description: "Short and stubby with a dusty blue top, this unassuming mushroom has mild cooling properties and is common in boggy woods." } }; // ordered list for the Herbs popup var herbItems = Object.keys(HERB_DATA); function colorForAlignment(align) { if (align === "Fire") return 0xFF6B6B; if (align === "Water") return 0x6BB6FF; if (align === "Earth") return 0x8B8F6B; if (align === "Wind") return 0xBEE3F8; return 0xADFF2F; } function wrapTextByWords(str, maxLen) { var words = str.split(' '); var lines = []; var current = ''; for (var i = 0; i < words.length; i++) { var tryLine = current.length ? current + ' ' + words[i] : words[i]; if (tryLine.length > maxLen) { if (current.length) lines.push(current); current = words[i]; } else { current = tryLine; } } if (current.length) lines.push(current); return lines.join('\n'); } // Keep backward compatibility with old herbs object var herbs = {}; for (var herbName in HERB_DATA) { if (HERB_DATA.hasOwnProperty(herbName)) { herbs[herbName] = { element: HERB_DATA[herbName].element, type: HERB_DATA[herbName].type, description: HERB_DATA[herbName].description }; } } // --- COUNTER LAYER --- var behindCounter = game.attachAsset('behind_Counter', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2100, width: 2048, height: 1400 // make it fill the bottom half }); var counter = game.attachAsset('counterTop', { anchorX: 0.5, anchorY: 1, x: 1024, y: 1850 }); // --- SERVE BUTTON (placed after counter so it's visible) --- var serveButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2650, width: 450, height: 120, tint: 0x661caa // optional: tint to make sure it's visible }); var serveButtonText = new Text2('SERVE', { size: 48, fill: 0xFFFFFF }); serveButtonText.anchor.set(0.5, 0.5); serveButtonText.x = 1024; serveButtonText.y = 2650; game.addChild(serveButtonText); // Click handler serveButton.down = function (x, y, obj) { craftPotion(); }; // Cauldron in center layer (depth 3, positioned lower on counter) var cauldron = game.attachAsset('cauldronZone', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1500 // Moved down to create space above }); cauldron.ingredients = []; // Cauldron ingredients display var cauldronLabel = new Text2('', { size: 35, fill: 0xFFFFFF }); cauldronLabel.anchor.set(0.5, 0.5); cauldronLabel.x = 1024; cauldronLabel.y = 950; game.addChild(cauldronLabel); function updateCauldronDisplay() { if (cauldron.ingredients.length === 0) { cauldronLabel.setText(''); } else { cauldronLabel.setText('Added: ' + cauldron.ingredients.join(', ')); } // Show/hide potion bottle based on ingredient count if (cauldron.ingredients.length === 3) { potionBottle.visible = true; } else { potionBottle.visible = false; } } function resetItem(item) { tween(item, { x: item.originalX, y: item.originalY }, { duration: 300 }); } // Inventory items are now only created through menu purchases // No default items in main play area // Ingredient category buttons in bottom layer - positioned below counter // Larger buttons with better spacing, centered horizontally var buttonWidth = 350; var buttonHeight = 120; var buttonSpacing = 80; var totalWidth = buttonWidth * 2 + buttonSpacing * 1; var startX = (2048 - totalWidth) / 2 + buttonWidth / 2; var teaBasesButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: startX, y: 2050, width: buttonWidth, height: buttonHeight, tint: 0x20B2AA }); var teaBasesButtonText = new Text2('TEA BASES', { size: 48, fill: 0xFFFFFF }); teaBasesButtonText.anchor.set(0.5, 0.5); teaBasesButtonText.x = startX; teaBasesButtonText.y = 2050; game.addChild(teaBasesButtonText); var herbsButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: startX + buttonWidth + buttonSpacing, y: 2050, width: buttonWidth, height: buttonHeight, tint: 0xADFF2F }); var herbsButtonText = new Text2('HERBS', { size: 48, fill: 0xFFFFFF }); herbsButtonText.anchor.set(0.5, 0.5); herbsButtonText.x = startX + buttonWidth + buttonSpacing; herbsButtonText.y = 2050; game.addChild(herbsButtonText); // Menu buttons in HUD layer - RESET and JOURNAL moved to right side, stacked vertically var resetButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1750, y: 150, width: 240, // Increased from 180 height: 80, // Increased from 60 tint: 0x444444 // Darker for better contrast }); var resetButtonText = new Text2('RESET', { size: 32, // Increased from 24 fill: 0xFFFFFF, fontWeight: 'bold' }); resetButtonText.anchor.set(0.5, 0.5); resetButtonText.x = 1750; resetButtonText.y = 150; game.addChild(resetButtonText); // Shop button removed per requirements // Start Over button for tea mixture reset var startOverButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2550, width: 330, height: 90, tint: 0xFF8C00 }); var startOverButtonText = new Text2('START OVER', { size: 39, fill: 0xFFFFFF }); startOverButtonText.anchor.set(0.5, 0.5); startOverButtonText.x = 1024; startOverButtonText.y = 2550; game.addChild(startOverButtonText); // Start Over button event handler startOverButton.down = function (x, y, obj) { cauldron.ingredients = []; updateCauldronDisplay(); patientStatusText.setText('Tea mixture cleared. Start fresh!'); updateHintBox(); }; // Create popup menu var popupMenu = game.addChild(new PopupMenu()); // Create herb details popup var herbPopup = game.addChild(new HerbPopup()); // Category button event handlers teaBasesButton.down = function (x, y, obj) { var teaBaseColors = []; for (var i = 0; i < baseItems.length; i++) { teaBaseColors.push(0x20B2AA); } popupMenu.showMenu('TEA BASES - 50 Gold Each', baseItems, teaBaseColors); }; herbsButton.down = function (x, y, obj) { var herbColors = []; for (var i = 0; i < herbItems.length; i++) { herbColors.push(0xADFF2F); } popupMenu.showMenu('HERBS - 50 Gold Each', herbItems, herbColors); }; // Button event handlers resetButton.down = function (x, y, obj) { reputation = 100; currentScore = 0; reputationText.setText('Reputation: ' + reputation); // ✅ Clear current patient currentPatient = null; isProcessingTreatment = false; // ✅ Force a new patient immediately spawnNewPatient(); }; // Create journal popup var journalPopup = game.addChild(new JournalPopup()); // Journal button aligned with TEA BASES and HERBS buttons var journalButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: startX + (buttonWidth + buttonSpacing) * 2, y: 2050, width: 350, height: 120, tint: 0x444444 // Darker for better contrast }); var journalButtonText = new Text2('JOURNAL', { size: 48, fill: 0xFFFFFF, fontWeight: 'bold' }); journalButtonText.anchor.set(0.5, 0.5); journalButtonText.x = startX + (buttonWidth + buttonSpacing) * 2; journalButtonText.y = 2050; game.addChild(journalButtonText); // Journal button event handler journalButton.down = function (x, y, obj) { journalPopup.showJournal(); }; // Play background music LK.playMusic('BackgroundMusic'); // Initialize first patient spawnNewPatient();
===================================================================
--- original.js
+++ change.js
@@ -805,9 +805,10 @@
alpha: 0.9
});
// Hint text
var patientStatusText = new Text2('Welcome! A patient awaits...', {
- size: 42,
+ size: 70,
+ // increased from 42
fill: 0xFFFFFF,
align: 'center'
});
patientStatusText.anchor.set(0.5, 0.5);
@@ -1713,10 +1714,13 @@
resetButton.down = function (x, y, obj) {
reputation = 100;
currentScore = 0;
reputationText.setText('Reputation: ' + reputation);
- patientStatusText.setText('Game Reset! Build your reputation again!');
- updateHintBox();
+ // ✅ Clear current patient
+ currentPatient = null;
+ isProcessingTreatment = false;
+ // ✅ Force a new patient immediately
+ spawnNewPatient();
};
// Create journal popup
var journalPopup = game.addChild(new JournalPopup());
// Journal button aligned with TEA BASES and HERBS buttons