User prompt
ensure the potion bottle graphic is loading and displaying in front of the background and cauldron layers. ensure that the reset button resets the game. When a player clicks "empty" display empty text for for 2 seconds, then return to the original patient text that was being displayed
User prompt
Fix for journal: Track previous entries as history When nextEntry() is called, push the current page onto the history stack: self.nextEntry = function () { var entries = self.journalData[self.currentSection]; // Save current state before moving forward self.viewHistory.push({ view: 'section', section: self.currentSection, index: self.currentIndex }); if (self.currentIndex < entries.length - 1) { self.currentIndex++; } else { self.currentIndex = 0; // Loop back to first } self.updateSectionContent(); };
User prompt
Move cauldron graphic and the empty button graphic down by 150 pixels. move the tea base, hebrs, and journal buttons down by 200 pixels.
User prompt
tile the behind counter graphic to the left and right so that it extends past the edge of the screen. ensure that the symptom indicator loads in front of it and not behind
User prompt
remove countertop asset from game. change text font to times new roman replace the serve button and text with the serveButton graphic adjust the behind counter graphic so that it is not streched across the screen
User prompt
To replace with your new graphic: Register the new graphic as an asset in your init section (where all the LK.init.image(...) calls are). LK.init.image('patientCommentBox', {width: 800, height: 200, id:'textbox.png'}); Swap the asset in the hintBox definition: var hintBox = game.attachAsset('patientCommentBox', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1050 }); Keep the text (patientStatusText) as is. It’s a separate Text2 element layered on top, so the new rectangle graphic will act as a background.
User prompt
Adjust scaling instead of stretching for cauldron:var cauldron = game.attachAsset('cauldronZone', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1500 // omit width/height so it uses the asset’s natural size }); Then control its size with a uniform scaleX / scaleY (so proportions stay intact). replace the reset button and text with the resetButton graphic.
User prompt
expand the cauldron space to encompass the entire cauldron graphic so it doesn't get cut off on the sides
User prompt
remove original text for tea base, herbs, journal and empty UI so that just the graphical assets are visisble
User prompt
remove the old visual UI for the herbs, tea bases, journal, and empty buttons and replace them with the new graphics herbButton, teabaseButton, journalButton, emptyButton
User prompt
Please fix the bug: 'teaBasesButton is not defined' in or related to this line: 'teaBasesButton.down = function (x, y, obj) {' Line Number: 1918
User prompt
Please fix the bug: 'herbsButton is not defined' in or related to this line: 'herbsButton.down = function (x, y, obj) {' Line Number: 1942
User prompt
Please fix the bug: 'teaBasesButton is not defined' in or related to this line: 'teaBasesButton.down = function (x, y, obj) {' Line Number: 1918
User prompt
Search your file for game.attachAsset('teabaseButton', herbsButton, journalButton, and emptyButton. Comment out or delete those lines so they never get added in the first place.
User prompt
use the herbsButton graphic for the herbs button graphic. use the teaBaseButton graphic for the tea bases button use the journalButton graphic for the journal button use the emptyButton graphic for the empty button
User prompt
for Journal Buttons: ✅ Fix: Remove the else { self.showContents(); }. That way the back button will only ever use your history stack. 2. Spacing out the Table of Contents buttons✅ Fix: Add more vertical spacing, e.g. set them 250px apart: herbsContentButton.y = 950; basesContentButton.y = 1200; // was 1100 illnessesContentButton.y = 1450; // was 1250 3. Make close [X] button 50% larger ✅ Fix: Increase both by 1.5×: width: 90, height: 90, ... var closeButtonText = new Text2('✕', { size: 60, // instead of 40 fill: 0xFFFFFF }); Make the PLAY button font color white
User prompt
stop the thermometer frame from changing color: Simply delete or comment out that line: "self.setSymptom = function (type) self.symptomType = type; var illness = ILLNESS_DATA[type]; if (illness) { // ❌ remove this line so thermometer/symptomIndicator no longer changes color // 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;"
User prompt
define thermometerFrame before mercury fill
User prompt
Right now your thermometer always looks full because: mercuryFill.y = 100 is fixed, and with anchorY: 1 the bottom isn’t aligned to the actual bottom of the frame. So when height increases, it pushes into the glass regardless of targetHeight. setThermometer is only defined, but not called properly when a patient spawns — so it might not be updating at all. Let’s fix both: ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'spawnNewPatient is not defined' in or related to this line: 'var oldSpawnNewPatient = spawnNewPatient;' Line Number: 1147
User prompt
The effect you’re describing (red mercury always anchored at the bottom bulb, growing upward or shrinking down from the top) is exactly what anchorY: 1 is for. Here’s the refined version: /**** * Thermometer Fill Logic ****/ function setThermometer(temp) { var maxHeight = thermometerFrame.height - 40; // subtract a little so it doesn’t spill over top of the glass var targetHeight = 0; if (temp === "Cold") { targetHeight = maxHeight * 0.25; // low fill } else if (temp === "Normal") { targetHeight = maxHeight * 0.55; // mid fill } else if (temp === "Hot") { targetHeight = maxHeight * 0.95; // almost full } // Animate mercury height; bottom stays fixed because anchorY = 1 tween(mercuryFill, { height: targetHeight }, { duration: 600, easing: tween.easeOut }); } // Hook into patient spawn var oldSpawnNewPatient = spawnNewPatient; spawnNewPatient = function () { oldSpawnNewPatient(); if (currentPatient) { var illness = ILLNESS_DATA[currentPatient]; if (illness && illness.temperature) { setThermometer(illness.temperature); } } }; Why this works: anchorY: 1 makes the rectangle’s bottom edge stay “glued” to its y coordinate. Changing height only stretches/shrinks upward. The maxHeight is based on the thermometer graphic, so “Cold,” “Normal,” and “Hot” map to fractions of the full glass. 👉 Now the thermometer will always rise from the bulb and never float off the bottom. remove other code for coloring of the symptom indicator based on illness from the game ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
move the thermometer graphic so that it's layered below the symptom indicator in layer but is directly behind it. in other words, the symptom indicator lays on top of the thermometer graphic
User prompt
implement the new thermometer system:One asset is the thermometer frame (your new graphic with transparent center). The second is a simple red fill line/rectangle that will be drawn behind it and adjusted dynamically. Create a container for thermometer Position it on the screen where you want it (say left-center). Attach the red fill bar first (behind). Attach the thermometer graphic on top. Link thermometer state to patient Each illness already has a temperature property ("Cold", "Normal", "Hot") in ILLNESS_DATA/**** * Thermometer System ****/ // Container for thermometer var thermometer = new Container(); thermometer.x = 200; // position on screen thermometer.y = 1200; // adjust as needed game.addChild(thermometer); // Red mercury fill (rectangle) var mercuryFill = thermometer.attachAsset('craftButton', { anchorX: 0.5, anchorY: 1, // grows upward x: 0, y: 100, // bottom of thermometer width: 40, // thickness of the red line height: 0, // start empty tint: 0xFF0000 }); // Thermometer frame graphic (with transparent center) var thermometerFrame = thermometer.attachAsset('thermometerGraphic', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Function to set thermometer level based on patient temperature function setThermometer(temp) { var targetHeight = 0; if (temp === "Cold") { targetHeight = 30; // low mercury } else if (temp === "Normal") { targetHeight = 80; // mid mercury } else if (temp === "Hot") { targetHeight = 140; // high mercury } // Animate mercury height tween(mercuryFill, { height: targetHeight }, { duration: 500 }); } // Hook into patient spawn var oldSpawnNewPatient = spawnNewPatient; spawnNewPatient = function () { oldSpawnNewPatient(); if (currentPatient) { var illness = ILLNESS_DATA[currentPatient]; if (illness && illness.temperature) { setThermometer(illness.temperature); } } }; What this does: Draws a red bar (mercuryFill) behind the thermometer image. Adjusts its height depending on whether the patient is "Cold", "Normal", or "Hot". Animates smoothly using the tween plugin already in your project. 👉 You’ll just need to register the thermometer graphic asset at the top of your file like: LK.init.image('thermometerGraphic', { width:200, height:600, id:'your_new_asset_id' }); ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
- You attach .down callbacks to buttons (e.g. resetButton.down = function(...) {...}) - But you never call obj.down(x,y,obj) inside your global game.down. - As a result, clicks hit game.down, your custom hit-testing runs (via hitRect), and the engine never falls back to each object’s own .down method. Rely purely on per-button handlers: teaBasesButton.down = function(x,y,obj) { popupMenu.showMenu('TEA BASES - 50 Gold Each', baseItems, teaBaseColors); }; herbsButton.down = function(x,y,obj) { popupMenu.showMenu('HERBS - 50 Gold Each', herbItems, herbColors); }; serveButton.down = function(x,y,obj) { craftPotion(); }; // etc.Then delete the corresponding if (hitRect(...)) blocks from your global game.down so the engine’s built-in hit testing drives everything. var btn = game.attachAsset('craftButton', ...); var txt = new Text2('SERVE', ...); game.addChild(txt); - wrap both the graphic and label in a single Container, and attach .down to that container.
User prompt
ensure tea bases and herbs buttons are easily clickable by player. 👉 Change it to use the dimensions you actually set when creating them: hw = (it.hitW || 200) / 2; hh = (it.hitH || 120) / 2;
/**** * 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: 650, // Increased width height: 180, // Increased height tint: 0x222222 // Dark background for contrast }); var herbsContentText = new Text2('Herbs & Fungi', { size: 72, // 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: 650, // Increased width height: 180, // Increased height tint: 0x222222 // Dark background for contrast }); var basesContentText = new Text2('Tea Bases', { size: 72, // 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: 650, // Increased width height: 180, // Increased height tint: 0x222222 // Dark background for contrast }); var illnessesContentText = new Text2('Illnesses', { size: 72, // 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: 84, // larger fill: 0x006400 // dark green }); sectionType.anchor.set(0.5, 0.5); sectionType.x = 1024; sectionType.y = 950; self.addChild(sectionType); var sectionElement = new Text2('', { size: 84, fill: 0x000000 // darker, readable }); sectionElement.anchor.set(0.5, 0.5); sectionElement.x = 1024; sectionElement.y = 1100; self.addChild(sectionElement); var sectionDescription = new Text2('', { size: 75, // substantially larger fill: 0x000000, // darker align: 'center' }); sectionDescription.anchor.set(0.5, 0); sectionDescription.x = 1024; sectionDescription.y = 1300; 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.viewHistory = []; // Track navigation history for back button 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) { // Save current state to history before changing if (self.currentView === 'contents') { self.viewHistory.push({ view: 'contents' }); } else if (self.currentView === 'section') { self.viewHistory.push({ view: 'section', section: self.currentSection, index: self.currentIndex }); } 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, 40)); } 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.", 40)); } 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, 40)); } }; 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.viewHistory = []; // Clear history when opening journal fresh 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) { // Go back to previous view in history if (self.viewHistory.length > 0) { var previousState = self.viewHistory.pop(); if (previousState.view === 'contents') { self.showContents(); } else if (previousState.view === 'section') { self.currentView = 'section'; self.currentSection = previousState.section; self.currentIndex = previousState.index; // 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(); } } else { // No history, go to contents 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); // Randomize patient graphic var patientGraphics = ['patient', 'patient1', 'patient2']; var randomGraphic = patientGraphics[Math.floor(Math.random() * patientGraphics.length)]; var patientBody = self.attachAsset(randomGraphic, { 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: 72, // 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: 48, // Increased from 36 to 48 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 = 15; // smoother tap vs drag // helper: rectangular hit test function hitRect(x, y, cx, cy, halfW, halfH) { return Math.abs(x - cx) <= halfW && Math.abs(y - cy) <= halfH; } // Helper function for exact, order-agnostic set matching function containsAll(required, brewed) { for (var i = 0; i < required.length; i++) { if (brewed.indexOf(required[i]) === -1) { return false; } } return true; } 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: 0xFFD700, // bright gold highlight when grabbed alpha: 0.9, 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; // stronger pop so it feels more obvious tween(ghost, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100 }); 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 / BOTTOM LEFT LAYER - Reputation Meter var meterBackground = new Container(); meterBackground.x = 120; meterBackground.y = -120; LK.gui.bottomLeft.addChild(meterBackground); // Meter background bar var meterBg = meterBackground.attachAsset('craftButton', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 600, height: 80, tint: 0x444444 }); // Meter fill bar var meterFill = meterBackground.attachAsset('craftButton', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 600, height: 80, tint: 0x00FF00 }); // Reputation label var reputationLabel = new Text2('Reputation', { size: 64, fill: 0xFFFFFF }); reputationLabel.anchor.set(0, 1); reputationLabel.x = 120; reputationLabel.y = -130; LK.gui.bottomLeft.addChild(reputationLabel); // Reputation value text var reputationText = new Text2(reputation.toString(), { size: 56, fill: 0xFFFFFF }); reputationText.anchor.set(0.5, 0.5); reputationText.x = 420; reputationText.y = -90; LK.gui.bottomLeft.addChild(reputationText); // CENTER LAYER - Patient + Cauldron + Dialogue var patient = game.addChild(new Patient()); patient.x = 1024; patient.y = 600; // Moved down by 100px /**** * Thermometer System ****/ // Container for thermometer var thermometer = new Container(); thermometer.x = 200; // position on screen thermometer.y = 700; // position directly behind symptom indicator game.addChild(thermometer); // Thermometer frame graphic (with transparent center) var thermometerFrame = thermometer.attachAsset('thermometerGraphic', { anchorX: 0.5, anchorY: 0.5, x: 0, y: 0 }); // Red mercury fill (rectangle) var mercuryFill = thermometer.attachAsset('craftButton', { anchorX: 0.5, anchorY: 1, // grows upward x: 0, y: thermometerFrame.height / 2, // bottom of thermometer frame width: 40, // thickness of the red line height: 0, // start empty tint: 0xFF0000 }); // Function to set thermometer level based on patient temperature function setThermometer(temp) { var maxHeight = thermometerFrame.height - 40; // subtract a little so it doesn't spill over top of the glass var targetHeight = 0; if (temp === "Cold") { targetHeight = maxHeight * 0.25; // low fill } else if (temp === "Normal") { targetHeight = maxHeight * 0.55; // mid fill } else if (temp === "Hot") { targetHeight = maxHeight * 0.95; // almost full } // Animate mercury height; bottom stays fixed because anchorY = 1 tween(mercuryFill, { height: targetHeight }, { duration: 600, easing: tween.easeOut }); } // 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; } // Define spawnNewPatient function 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(); // Set thermometer based on patient temperature - call it properly setThermometer(illness.temperature); } //{8T} {8U} {8V} {8W} else { patientStatusText.setText('A new patient has arrived!'); updateHintBox(); // Set default temperature for unknown illnesses setThermometer("Normal"); } 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; // Use contains-all matching - brew must contain at least all required elements var cureOK = containsAll(required, brewed); 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(); LK.getSound('failure').play(); patientStatusText.setText("Invalid brew! -" + Math.abs(repChange) + " reputation"); updateHintBox(); isProcessingTreatment = false; // allow retry } reputation += repChange; currentScore += Math.max(0, repChange); // Update reputation meter var maxReputation = 200; // Maximum reputation for meter scaling var meterWidth = Math.max(0, Math.min(600, reputation / maxReputation * 600)); // Animate meter fill width change tween(meterFill, { width: meterWidth }, { duration: 500, easing: tween.easeOut }); // Update meter color based on reputation level var meterColor = 0x00FF00; // Green if (reputation < 50) { meterColor = 0xFF0000; // Red } else if (reputation < 100) { meterColor = 0xFFFF00; // Yellow } tween(meterFill, { tint: meterColor }, { duration: 300 }); // Update reputation text value reputationText.setText(reputation.toString()); cauldron.ingredients = []; updateCauldronDisplay(); } var heldItem = null; var dragGhost = null; game.down = function (x, y, obj) { // Check main game buttons first with proper hit boxes // 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]; // Use full button dimensions for tea bases var hw, hh; if (it.children[0] && it.children[0].tint === 0x1a237e) { // Tea base button - use full dimensions hw = 400; // full buttonWidth from tea base creation hh = 60; // full buttonHeight/2 from tea base creation } else { // Regular herb button hw = 200; // full buttonWidth/2 from herb creation hh = 60; // full buttonHeight/2 from herb creation } 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 = 200; // full width/2 var hh = 60; // full height/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 } } else { // Herb button hover effect var originalColor = 0x8B4513; // Default herb button color if (isHovering) { it.children[0].tint = 0x666666; // lighter shade on hover } else { it.children[0].tint = originalColor; // return to original color } } } } // 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 -> add directly to cauldron if space available if (downItemCandidate && !heldItem) { var moved = Math.sqrt((x - downStartX) * (x - downStartX) + (y - downStartY) * (y - downStartY)); if (moved <= DRAG_THRESHOLD * 2) { // This is a tap, not a drag if (cauldron.ingredients.length < 3) { cauldron.ingredients.push(downItemCandidate.name); updateCauldronDisplay(); tween(cauldron, { tint: 0x44FF44 }, { duration: 200, onFinish: function onFinish() { tween(cauldron, { tint: 0xFFFFFF }, { duration: 200 }); } }); } else { // Cauldron is full tween(cauldron, { tint: 0xFF4444 }, { duration: 200, onFinish: function onFinish() { tween(cauldron, { tint: 0xFFFFFF }, { duration: 200 }); } }); } } 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: 2450, 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 = 2450; game.addChild(serveButtonText); serveButton.down = function (x, y, obj) { craftPotion(); }; // Serve button handler now handled in main game down event // 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: 56, fill: 0x000000, fontWeight: 'bold' }); 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 = 420; var buttonHeight = 150; var buttonSpacing = 80; var totalWidth = buttonWidth * 3 + buttonSpacing * 2; // 3 buttons with 2 spacings var startX = (2048 - totalWidth) / 2 + buttonWidth / 2; var teaBasesButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: startX, y: 2050, width: 420, height: 150, tint: 0x20B2AA }); var teaBasesButtonText = new Text2('TEA BASES', { size: 58, fill: 0xFFFFFF }); teaBasesButtonText.anchor.set(0.5, 0.5); teaBasesButtonText.x = startX; teaBasesButtonText.y = 2050; game.addChild(teaBasesButtonText); 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); }; var herbsButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: startX + (buttonWidth + buttonSpacing), y: 2050, width: 420, height: 150, tint: 0xADFF2F }); var herbsButtonText = new Text2('HERBS', { size: 58, fill: 0xFFFFFF }); herbsButtonText.anchor.set(0.5, 0.5); herbsButtonText.x = startX + (buttonWidth + buttonSpacing); herbsButtonText.y = 2050; game.addChild(herbsButtonText); 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); }; // 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: 360, // Decreased by 50% height: 120, // Decreased by 50% tint: 0x444444 // Darker for better contrast }); var resetButtonText = new Text2('RESET', { size: 48, // Decreased by 50% 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 // Empty button for tea mixture reset - positioned at bottom of cauldron var startOverButton = game.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1750, width: 400, height: 120, tint: 0xFF8C00 }); var startOverButtonText = new Text2('EMPTY', { size: 72, fill: 0xFFFFFF }); startOverButtonText.anchor.set(0.5, 0.5); startOverButtonText.x = 1024; startOverButtonText.y = 1750; game.addChild(startOverButtonText); startOverButton.down = function (x, y, obj) { cauldron.ingredients = []; updateCauldronDisplay(); patientStatusText.setText('Tea mixture cleared. Start fresh!'); updateHintBox(); }; // Empty button event handler now handled in main game down event // Create a top-level overlay container var overlayLayer = new Container(); game.addChild(overlayLayer); // Create popup menu inside overlay var popupMenu = overlayLayer.addChild(new PopupMenu()); // Create herb details popup inside overlay var herbPopup = overlayLayer.addChild(new HerbPopup()); // Category button event handlers now handled in main game down event // Reset button handler is now attached directly to the button above // Create journal popup inside overlay var journalPopup = overlayLayer.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: 420, height: 150, tint: 0x444444 // Darker for better contrast }); var journalButtonText = new Text2('JOURNAL', { size: 58, fill: 0xFFFFFF, fontWeight: 'bold' }); journalButtonText.anchor.set(0.5, 0.5); journalButtonText.x = startX + (buttonWidth + buttonSpacing) * 2; journalButtonText.y = 2050; game.addChild(journalButtonText); journalButton.down = function (x, y, obj) { journalPopup.showJournal(); }; // Journal button event handler now handled in main game down event // Ensure overlay layer is always on top after creating all other elements game.removeChild(overlayLayer); game.addChild(overlayLayer); // ensure overlay & popups are above HUD buttons // Function to refresh HUD visibility based on popup states function refreshHUD() { var anyPopupOpen = popupMenu.isVisible || herbPopup.isVisible || journalPopup.isVisible; journalButton.visible = !anyPopupOpen; journalButtonText.visible = !anyPopupOpen; } // Wrap popup menu methods to hide/show journal button 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(); }; // Wrap herb popup methods to hide/show journal button var _showPopup = herbPopup.showPopup; herbPopup.showPopup = function (herbName, x, y) { _showPopup.call(herbPopup, herbName, x, y); refreshHUD(); }; var _hidePopup = herbPopup.hidePopup; herbPopup.hidePopup = function () { _hidePopup.call(herbPopup); refreshHUD(); }; // Wrap journal popup methods to hide/show journal button var _showJournal = journalPopup.showJournal; journalPopup.showJournal = function () { _showJournal.call(journalPopup); refreshHUD(); }; var _hideJournal = journalPopup.hideJournal; journalPopup.hideJournal = function () { _hideJournal.call(journalPopup); refreshHUD(); }; // Game state management var gameStarted = false; // How-to card overlay var howtoOverlay = new Container(); game.addChild(howtoOverlay); // Semi-transparent background var howtoBackground = howtoOverlay.attachAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0, width: 2048, height: 2732, alpha: 0.8, tint: 0x000000 }); // How-to card var howtoCard = howtoOverlay.attachAsset('howto_card', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1200, width: 1536 // 75% of screen width (2048 * 0.75) to preserve aspect ratio }); // PLAY button var playButton = howtoOverlay.attachAsset('craftButton', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 2000, width: 400, height: 120, tint: 0xFFFF00 }); var playButtonText = new Text2('PLAY', { size: 64, fill: 0x000000 }); playButtonText.anchor.set(0.5, 0.5); playButtonText.x = 1024; playButtonText.y = 2000; howtoOverlay.addChild(playButtonText); playButton.down = function (x, y, obj) { gameStarted = true; howtoOverlay.visible = false; LK.playMusic('BackgroundMusic'); spawnNewPatient(); }; // PLAY button handler now handled in main game down event // Initially show how-to card howtoOverlay.visible = true;
===================================================================
--- original.js
+++ change.js
@@ -516,9 +516,9 @@
self.setSymptom = function (type) {
self.symptomType = type;
var illness = ILLNESS_DATA[type];
if (illness) {
- if (self.symptomGlow) self.symptomGlow.tint = illness.symptom_color;
+ // 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;