/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // OptionButton: For displaying a choice var OptionButton = Container.expand(function () { var self = Container.call(this); self.bg = self.attachAsset('option_btn', { anchorX: 0.5, anchorY: 0.5 }); self.text = null; self.callback = null; self.setText = function (str) { if (self.text) self.removeChild(self.text); self.text = new Text2(str, { size: 54, fill: '#222222' }); self.text.anchor.set(0.5, 0.5); self.text.x = 0; self.text.y = 0; self.addChild(self.text); }; self.setCallback = function (cb) { self.callback = cb; }; self.down = function (x, y, obj) { if (self.callback) self.callback(); }; return self; }); // Passive background object base class var PassiveBgObject = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.assetId = ''; self.asset = null; self.setAsset = function (assetId) { if (self.asset) self.removeChild(self.asset); self.assetId = assetId; self.asset = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); }; self.resetPosition = function () { // Start just outside right edge, random Y self.x = 2048 + (self.asset ? self.asset.width : 100) / 2 + Math.random() * 200; self.y = 200 + Math.random() * 2100; }; self.update = function () { if (typeof self.lastX === "undefined") self.lastX = self.x; self.x -= self.speed; // If off screen to the left, reset if (self.lastX >= -200 && self.x < -200) { self.resetPosition(); } self.lastX = self.x; }; return self; }); // Motorcycle var BgMotorcycle = PassiveBgObject.expand(function () { var self = PassiveBgObject.call(this); self.setAsset('bg_motorcycle'); self.speed = 4.0 + Math.random() * 1.5; self.resetPosition(); return self; }); // Heart var BgHeart = PassiveBgObject.expand(function () { var self = PassiveBgObject.call(this); self.setAsset('bg_heart'); self.speed = 2.7 + Math.random() * 1.2; self.resetPosition(); return self; }); // Football var BgFootball = PassiveBgObject.expand(function () { var self = PassiveBgObject.call(this); self.setAsset('bg_football'); self.speed = 2.5 + Math.random() * 1.2; self.resetPosition(); return self; }); // Car var BgCar = PassiveBgObject.expand(function () { var self = PassiveBgObject.call(this); self.setAsset('bg_car'); self.speed = 3.2 + Math.random() * 1.5; self.resetPosition(); return self; }); // Briefcase var BgBriefcase = PassiveBgObject.expand(function () { var self = PassiveBgObject.call(this); self.setAsset('bg_briefcase'); self.speed = 2.2 + Math.random() * 1.2; self.resetPosition(); return self; }); // RelationshipBar: For displaying and updating a bar (happiness, honesty, lust, betrayal) var RelationshipBar = Container.expand(function () { var self = Container.call(this); self.bg = self.attachAsset('bar_bg', { anchorX: 0, anchorY: 0 }); self.fill = null; self.label = null; self.value = 100; // 0-100 self.maxWidth = 400; self.type = 'happy'; // 'happy', 'honest', 'lust', 'betray' self.setType = function (type) { self.type = type; var fillId = 'bar_fill_happy'; if (type === 'honest') fillId = 'bar_fill_honest'; if (type === 'lust') fillId = 'bar_fill_lust'; if (type === 'betray') fillId = 'bar_fill_betray'; if (self.fill) self.removeChild(self.fill); self.fill = self.attachAsset(fillId, { anchorX: 0, anchorY: 0 }); self.fill.x = 0; self.fill.y = 0; self.fill.width = self.maxWidth; self.fill.height = 40; self.fill.zIndex = 1; self.bg.zIndex = 0; self.setValue(self.value); }; self.setValue = function (val) { self.value = Math.max(0, Math.min(100, val)); if (self.fill) { self.fill.width = self.maxWidth * (self.value / 100); } if (self.label) { self.label.setText(self.value + '%'); } }; self.setLabel = function (text) { if (self.label) self.removeChild(self.label); self.label = new Text2(text, { size: 36, fill: '#ffffff' }); self.label.anchor.set(1, 0.5); self.label.x = self.maxWidth + 20; self.label.y = 20; self.addChild(self.label); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Animate passive background objects // Sağdan sola giden araba // Sağdan sola giden iş çantası // Sağdan sola giden ateşli kalp // Sağdan sola giden futbol topu // Sağdan sola giden motor // --- Shop/Store assets (right side) --- // Example id, replace with real if (typeof bgObjects !== "undefined") { for (var i = 0; i < bgObjects.length; i++) { if (bgObjects[i] && typeof bgObjects[i].update === "function") { bgObjects[i].update(); } } } // No per-frame logic needed // Not: 'background' asseti image olarak tanımlanmalı, ör: LK.init.image('background', {width:2048, height:2732, id:'YOUR_IMAGE_ID'}) var backgroundNode = LK.getAsset('background', { anchorX: 0, anchorY: 0 }); backgroundNode.width = 2048; backgroundNode.height = 2732; backgroundNode.x = 0; backgroundNode.y = 0; backgroundNode.zIndex = -100; // Her şeyin arkasında dursun game.addChild(backgroundNode); // --- Passive background objects (car, briefcase, heart, football, motorcycle) --- var bgObjects = []; function spawnBgObjects() { // Remove old ones if any for (var i = 0; i < bgObjects.length; i++) { if (bgObjects[i] && bgObjects[i].parent) { game.removeChild(bgObjects[i]); } } bgObjects = []; // Add 2 of each for variety for (var i = 0; i < 2; i++) { var car = new BgCar(); var briefcase = new BgBriefcase(); var heart = new BgHeart(); var football = new BgFootball(); var motorcycle = new BgMotorcycle(); game.addChild(car); game.addChild(briefcase); game.addChild(heart); game.addChild(football); game.addChild(motorcycle); bgObjects.push(car, briefcase, heart, football, motorcycle); } } spawnBgObjects(); // Çarpıcı seçimler: her 4-6 sahnede bir, yüksek risk/ödül, animasyonlu, barları büyük oranda etkiler // --- Dramatic Choice (Çarpıcı Seçim) System --- var dramaticChoices = [{ id: "rebecca_room", text: "Rebecca ile iş gezisindesiniz. Aynı odada mı kalacaksınız, farklı mı?", portrait: "rebecca", speaker: "Rebecca", dramatic: true, options: [{ text: "Aynı odada kal", effects: { rebecca: 15, lust: 15, betray: 15 }, meta: { memoryLabel: "rebecca_room_same" } }, { text: "Farklı odada kal", effects: { honest: 10, rebecca: -5 }, meta: { memoryLabel: "rebecca_room_diff" } }] }, { id: "lisa_warns_alex", text: "Lisa seni, iş yerinde Alex ile fazla yakın görünmen konusunda uyarıyor. Tepkin ne olur?", portrait: "lisa", speaker: "Lisa", dramatic: true, options: [{ text: "Anlar ve saygı gösterirsin", effects: { lisa: 20, honest: 15 }, meta: { memoryLabel: "lisa_warns_respect" } }, { text: "Umursamaz davranırsın", effects: { lisa: -20, betray: 15 }, meta: { memoryLabel: "lisa_warns_ignore" } }] }, { id: "alex_secret", text: "Alex senden gizli bir bilgi istiyor. Paylaşacak mısın?", portrait: "alex", speaker: "Alex", dramatic: true, options: [{ text: "Paylaş", effects: { betray: 20, alex: 10 }, meta: { memoryLabel: "alex_secret_share" } }, { text: "Sakla", effects: { honest: 20, alex: -10 }, meta: { memoryLabel: "alex_secret_hide" } }] }, { id: "peter_lisa_fears", text: "Peter sana, Lisa ile ilgili endişelerini paylaşıyor. Ona inanacak mısın?", portrait: "peter", speaker: "Peter", dramatic: true, options: [{ text: "Evet", effects: { peter: 15, honest: 10 }, meta: { memoryLabel: "peter_lisa_believe" } }, { text: "Hayır", effects: { peter: -15, betray: 10 }, meta: { memoryLabel: "peter_lisa_deny" } }] }, { id: "rebecca_night", text: "Rebecca gece seni evine davet ediyor. Gidiyor musun?", portrait: "rebecca", speaker: "Rebecca", dramatic: true, options: [{ text: "Evet", effects: { rebecca: 20, lust: 15, betray: 20 }, meta: { memoryLabel: "rebecca_night_yes" } }, { text: "Hayır", effects: { honest: 15 }, meta: { memoryLabel: "rebecca_night_no" } }] }, { id: "lisa_serious_talk", text: "Lisa, seninle ciddi bir konuşma yapmak istiyor. Onu dinleyecek misin?", portrait: "lisa", speaker: "Lisa", dramatic: true, options: [{ text: "Dinle", effects: { lisa: 20, honest: 10 }, meta: { memoryLabel: "lisa_serious_listen" } }, { text: "Dinleme", effects: { lisa: -20, happy: -15 }, meta: { memoryLabel: "lisa_serious_ignore" } }] }, { id: "alex_secret_deal", text: "Alex ile gizli bir anlaşma teklif ediyor. Kabul edecek misin?", portrait: "alex", speaker: "Alex", dramatic: true, options: [{ text: "Evet", effects: { alex: 20, betray: 20 }, meta: { memoryLabel: "alex_deal_yes" } }, { text: "Hayır", effects: { honest: 20, alex: -15 }, meta: { memoryLabel: "alex_deal_no" } }] }, { id: "peter_big_secret", text: "Peter, seni büyük bir sırrı hakkında uyarıyor. Güveniyor musun?", portrait: "peter", speaker: "Peter", dramatic: true, options: [{ text: "Evet", effects: { peter: 20, honest: 10 }, meta: { memoryLabel: "peter_secret_trust" } }, { text: "Hayır", effects: { peter: -20, betray: 15 }, meta: { memoryLabel: "peter_secret_distrust" } }] }, { id: "rebecca_club", text: "Rebecca ile bir gece kulübünde dans ediyorsun. Daha yakın davranacak mısın?", portrait: "rebecca", speaker: "Rebecca", dramatic: true, options: [{ text: "Evet", effects: { rebecca: 15, lust: 15, betray: 10 }, meta: { memoryLabel: "rebecca_club_yes" } }, { text: "Hayır", effects: { honest: 10 }, meta: { memoryLabel: "rebecca_club_no" } }] }, { id: "lisa_gossip", text: "Lisa seni iş arkadaşlarınla ilgili dedikodulara karışmakla suçluyor. Savunacak mısın?", portrait: "lisa", speaker: "Lisa", dramatic: true, options: [{ text: "Savun", effects: { lisa: 10, honest: 15 }, meta: { memoryLabel: "lisa_gossip_defend" } }, { text: "Kabullen", effects: { lisa: -15, betray: 10 }, meta: { memoryLabel: "lisa_gossip_admit" } }] }, { id: "alex_promotion", text: "Alex, seni iş yerinde terfi ile ödüllendiriyor ama bir karşılık bekliyor. Kabul edecek misin?", portrait: "alex", speaker: "Alex", dramatic: true, options: [{ text: "Evet", effects: { alex: 25, betray: 25 }, meta: { memoryLabel: "alex_promotion_yes" } }, { text: "Hayır", effects: { honest: 20 }, meta: { memoryLabel: "alex_promotion_no" } }] }, { id: "peter_sacrifice", text: "Peter’in sana yardım etmek için büyük bir fedakarlık yapması gerekiyor. Kabul edecek misin?", portrait: "peter", speaker: "Peter", dramatic: true, options: [{ text: "Evet", effects: { peter: 25, happy: 15 }, meta: { memoryLabel: "peter_sacrifice_yes" } }, { text: "Hayır", effects: { peter: -20, betray: 10 }, meta: { memoryLabel: "peter_sacrifice_no" } }] }, { id: "rebecca_restaurant", text: "Rebecca, iş seyahatinde seni bir restoranda yalnız bırakıyor. Tek başına kalacak mısın yoksa kalabalığa mı karışacaksın?", portrait: "rebecca", speaker: "Rebecca", dramatic: true, options: [{ text: "Tek başına", effects: { rebecca: 10, lust: 10 }, meta: { memoryLabel: "rebecca_restaurant_alone" } }, { text: "Kalabalık", effects: { honest: 10 }, meta: { memoryLabel: "rebecca_restaurant_crowd" } }] }, { id: "lisa_memory", text: "Lisa sana eski bir anısını anlatıyor ve senden destek bekliyor. Onun yanında olacak mısın?", portrait: "lisa", speaker: "Lisa", dramatic: true, options: [{ text: "Evet", effects: { lisa: 20, happy: 15 }, meta: { memoryLabel: "lisa_memory_yes" } }, { text: "Hayır", effects: { lisa: -15 }, meta: { memoryLabel: "lisa_memory_no" } }] }, { id: "alex_ethics", text: "Alex’in zorlayıcı teklifine karşılık verirken etik dışı bir şey yapman isteniyor. Kabul mü?", portrait: "alex", speaker: "Alex", dramatic: true, options: [{ text: "Evet", effects: { alex: 20, betray: 25 }, meta: { memoryLabel: "alex_ethics_yes" } }, { text: "Hayır", effects: { honest: 20 }, meta: { memoryLabel: "alex_ethics_no" } }] }, { id: "peter_secret_share", text: "Peter seni beklenmedik bir şekilde büyük bir sırrını açıklıyor. Tepkin ne olur?", portrait: "peter", speaker: "Peter", dramatic: true, options: [{ text: "Sırlarınızı paylaşmaya devam edersin", effects: { peter: 20, honest: 15 }, meta: { memoryLabel: "peter_secret_share_yes" } }, { text: "Mesafeli olursun", effects: { peter: -15, betray: 10 }, meta: { memoryLabel: "peter_secret_share_no" } }] }, { id: "rebecca_bar_lisa", text: "Rebecca ile iş sonrası bara gittiniz. Lisa ile yüzleşmeye hazır mısın?", portrait: "rebecca", speaker: "Rebecca", dramatic: true, options: [{ text: "Evet", effects: { betray: 20, lust: 15, rebecca: 10 }, meta: { memoryLabel: "rebecca_bar_lisa_yes" } }, { text: "Hayır", effects: { honest: 15, lisa: 10 }, meta: { memoryLabel: "rebecca_bar_lisa_no" } }] }, { id: "lisa_crisis", text: "Lisa sana, evlilikte bir kriz yaşıyor ve profesyonel yardım almak istiyor. Destek verir misin?", portrait: "lisa", speaker: "Lisa", dramatic: true, options: [{ text: "Evet", effects: { lisa: 25, happy: 20 }, meta: { memoryLabel: "lisa_crisis_yes" } }, { text: "Hayır", effects: { lisa: -25 }, meta: { memoryLabel: "lisa_crisis_no" } }] }, { id: "alex_risk", text: "Alex, kariyerin için büyük bir tehlike barındıran bir riski göze almana izin veriyor. Kabul mü?", portrait: "alex", speaker: "Alex", dramatic: true, options: [{ text: "Evet", effects: { alex: 30, betray: 30 }, meta: { memoryLabel: "alex_risk_yes" } }, { text: "Hayır", effects: { honest: 20 }, meta: { memoryLabel: "alex_risk_no" } }] }, { id: "peter_conflict", text: "Peter ile aranızda aniden büyük bir anlaşmazlık çıkıyor. Özür dileyecek misin?", portrait: "peter", speaker: "Peter", dramatic: true, options: [{ text: "Evet", effects: { peter: 20, happy: 15 }, meta: { memoryLabel: "peter_conflict_yes" } }, { text: "Hayır", effects: { peter: -20, betray: 15 }, meta: { memoryLabel: "peter_conflict_no" } }] }]; // Dramatic choice frequency: every 4-6 turns, randomize var nextDramaticTurn = 4 + Math.floor(Math.random() * 3); var dramaticHistory = []; // Helper: get a random dramatic choice not recently shown function getDramaticChoice() { var available = []; for (var i = 0; i < dramaticChoices.length; i++) { if (dramaticHistory.indexOf(dramaticChoices[i].id) === -1) { available.push(dramaticChoices[i]); } } // If all have been shown, reset history if (available.length === 0) { dramaticHistory = []; available = dramaticChoices.slice(); } var idx = Math.floor(Math.random() * available.length); return available[idx]; } // Show a dramatic choice with animation, music pause, and shadow overlay function showDramaticChoice() { // Remove old option buttons for (var i = 0; i < optionButtons.length; i++) { game.removeChild(optionButtons[i]); } optionButtons = []; // Pick a dramatic choice var node = getDramaticChoice(); dramaticHistory.push(node.id); // Pause music (if any) if (typeof LK.stopMusic === "function") LK.stopMusic(); // Shadow overlay if (!game._dramaticShadow) { var shadow = LK.getAsset('bar_bg', { anchorX: 0, anchorY: 0 }); shadow.width = 2048; shadow.height = 2732; shadow.x = 0; shadow.y = 0; shadow.alpha = 0.0; // Start fully transparent shadow.zIndex = 99; game.addChild(shadow); game._dramaticShadow = shadow; // Animate shadow fade-in tween(shadow, { alpha: 0.7 }, { duration: 220, easing: tween.easeOut }); } else { // If already present, ensure it's visible and interactive game._dramaticShadow.alpha = 0.7; game._dramaticShadow.zIndex = 99; } // Portrait if (portraitNode && node.portrait && LK.getAsset(node.portrait, {})) { portraitNode.texture = LK.getAsset(node.portrait, {}).texture; portraitNode.tint = 0xffffff; } // Speaker if (speakerText) speakerText.setText(node.speaker ? node.speaker : ''); // Story text if (storyText) { storyText.setText(node.text); storyText.alpha = 1.0; // No animation } // Dramatic option buttons: ensure visible, enabled, and selectable for (var i = 0; i < node.options.length; i++) { (function (opt, idx) { var btn = new OptionButton(); btn.setText(opt.text); // Büyük ve dikkat çekici: butonları daha büyük yap btn.scale.x = 1.35; btn.scale.y = 1.35; // Ekranda tamamen görünür ve aralıklı olacak şekilde ayarla // Yüksekliğe göre ortala, iki seçenek için yukarıdan ve aşağıdan eşit boşluk bırak var totalBtnHeight = 2 * (btn.bg.height * btn.scale.y) + 120; var startY = 1800 - totalBtnHeight / 2; btn.x = 2048 / 2; btn.y = startY + idx * (btn.bg.height * btn.scale.y + 120); btn.alpha = 1.0; btn.bg.tint = 0x000000; if (btn.text && btn.text.style) btn.text.style.fill = '#ffffff'; btn.zIndex = 100; btn.interactive = true; btn.buttonMode = true; // Make sure button is enabled and not grayed out btn.bg.tint = 0x000000; if (btn.text && btn.text.style) btn.text.style.fill = '#ffffff'; // Remove any previous disabled state btn.alpha = 1.0; btn.visible = true; btn.setCallback(function () { // Seçim sırasında iki butonu da büyüt ve animasyon ekle for (var j = 0; j < optionButtons.length; j++) { var b = optionButtons[j]; // Seçilen buton daha fazla büyüsün, diğeri de büyüsün ama biraz az var targetScale = b === btn ? 1.55 : 1.25; tween(b.scale, { x: targetScale, y: targetScale }, { duration: 220, easing: tween.easeOut }); tween(b, { alpha: 1 }, { duration: 220, easing: tween.easeOut }); } // Seçimden kısa süre sonra butonları ve gölgeyi kaldır LK.setTimeout(function () { // Remove shadow overlay with fade out if (game._dramaticShadow) { tween(game._dramaticShadow, { alpha: 0 }, { duration: 180, easing: tween.easeIn, onFinish: function onFinish() { if (game._dramaticShadow) { game.removeChild(game._dramaticShadow); game._dramaticShadow = null; } } }); } // Remove buttons instantly for (var j = 0; j < optionButtons.length; j++) { (function (b) { game.removeChild(b); })(optionButtons[j]); } optionButtons = []; // Apply effects (dramatic: +10~+30 or -30) applyDramaticEffects(opt.effects, opt.meta); // Resume music (if any) if (typeof LK.playMusic === "function") LK.playMusic('musicId'); // Next dramatic turn: 4-6 turns later nextDramaticTurn = turnCount + 4 + Math.floor(Math.random() * 3); // Continue with normal story LK.setTimeout(function () { var nextIdx = getNextNode(); currentNode = nextIdx; showStoryNode(currentNode); }, 600); }, 260); }); game.addChild(btn); optionButtons.push(btn); })(node.options[i], i); } } // Apply dramatic effects: bar changes are much larger function applyDramaticEffects(effects, meta) { if (!effects) return; // Record memory if (meta && meta.memoryLabel) pastChoices.push(meta.memoryLabel); // Dramatic: apply full effect value (not just +1/-1) if (typeof effects.lisa === 'number') rel_lisa = Math.max(0, Math.min(100, rel_lisa + effects.lisa)); if (typeof effects.rebecca === 'number') rel_rebecca = Math.max(0, Math.min(100, rel_rebecca + effects.rebecca)); if (typeof effects.peter === 'number') rel_peter = Math.max(0, Math.min(100, rel_peter + effects.peter)); if (typeof effects.alex === 'number') rel_alex = Math.max(0, Math.min(100, rel_alex + effects.alex)); if (typeof effects.happy === 'number') bar_happy = Math.max(0, Math.min(100, bar_happy + effects.happy)); if (typeof effects.honest === 'number') bar_honest = Math.max(0, Math.min(100, bar_honest + effects.honest)); if (typeof effects.lust === 'number') bar_lust = Math.max(0, Math.min(100, bar_lust + effects.lust)); if (typeof effects.betray === 'number') bar_betray = Math.max(0, Math.min(100, bar_betray + effects.betray)); // Shadow bar: dramatic choices have bigger impact if (typeof effects.betray === 'number' && effects.betray > 0) bar_shadow = Math.max(0, Math.min(100, bar_shadow + 10)); if (typeof effects.honest === 'number' && effects.honest > 0) bar_shadow = Math.max(0, bar_shadow - 5); updateBars(); turnCount++; // Cross effects applyCrossEffects(effects, meta); // Check for ending if (bar_happy <= 0) { showEnding('Mutluluk sıfırlandı. Mike depresyona girdi.'); return; } if (bar_honest <= 0) { showEnding('Dürüstlük sıfırlandı. Mike yalanlarla dolu bir hayata saplandı.'); return; } if (bar_lust <= 0) { showEnding('Şehvet sıfırlandı. Mike hayattan keyif alamıyor.'); return; } if (bar_betray >= 100) { showEnding('İhanet %100 oldu. Mike ilişkilerini kaybetti.'); return; } } // Each story node: { text, options: [ {text, effects, next} ], portrait, speaker } // --- Story Data --- // Character portraits (simple colored boxes for now) // Bar backgrounds and fills // Option buttons // --- Whiskey'e özel sorular (yalnızca satın alındıysa gösterilecek) --- var whiskeyQuestions = [{ id: "whiskey_intro", text: "Whiskey: 'Hav hav! Mike, parka gidelim mi?'", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Whiskey'i parka götür.", effects: { happy: 5 } }, { text: "Bugün evde kalalım.", effects: { happy: -2 } }] }, { id: "whiskey_walk", text: "Whiskey kapının önünde heyecanla bekliyor. Dışarı çıkarmak ister misin?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Whiskey ile uzun yürüyüş yap.", effects: { happy: 5 } }, { text: "Kısa bir yürüyüş yap.", effects: { happy: 2 } }, { text: "Yürüyüşe çıkma.", effects: { happy: -3 } }] }, { id: "whiskey_vet", text: "Whiskey biraz halsiz görünüyor. Veterinere götürecek misin?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Veterinere götür. ($200 harca)", effects: { happy: 5 }, meta: { type: "whiskey_spend", money: -200 } }, { text: "Evde dinlensin.", effects: { happy: -2 } }] }, { id: "whiskey_toy", text: "Whiskey yeni bir oyuncak istiyor.", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Oyuncak al. ($50 harca)", effects: { happy: 3 }, meta: { type: "whiskey_spend", money: -50 } }, { text: "Oyuncak alma.", effects: { happy: -2 } }] }, { id: "whiskey_bath", text: "Whiskey çamura bulandı! Yıkayacak mısın?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Whiskey'i yıka.", effects: { happy: 2 } }, { text: "Yıkamadan bırak.", effects: { happy: -3 } }] }, { id: "whiskey_trick", text: "Whiskey yeni bir numara öğrenmek istiyor. Öğretecek misin?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Yeni numara öğret.", effects: { happy: 4 } }, { text: "Vakit ayırma.", effects: { happy: -2 } }] }, { id: "whiskey_vacation", text: "Tatile çıkacaksınız. Whiskey'i de götürecek misin?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Whiskey'i de götür. ($300 harca)", effects: { happy: 5 }, meta: { type: "whiskey_spend", money: -300 } }, { text: "Whiskey'i pansiyona bırak. ($150 harca)", effects: { happy: 2 }, meta: { type: "whiskey_spend", money: -150 } }] }, { id: "whiskey_birthday", text: "Whiskey'in doğum günü! Ona özel bir şey yapmak ister misin?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Köpek pastası al. ($80 harca)", effects: { happy: 4 }, meta: { type: "whiskey_spend", money: -80 } }, { text: "Sadece sarıl.", effects: { happy: 2 } }] }, { id: "whiskey_lost", text: "Whiskey bahçede kayboldu! Arayacak mısın?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Bahçede ara.", effects: { happy: 3 } }, { text: "Kendi gelir diye bekle.", effects: { happy: -3 } }] }, { id: "whiskey_vet2", text: "Whiskey aşı zamanı geldi. Aşı yaptıracak mısın?", portrait: "whiskey", speaker: "Whiskey", options: [{ text: "Aşı yaptır. ($120 harca)", effects: { happy: 3 }, meta: { type: "whiskey_spend", money: -120 } }, { text: "Aşıyı ertele.", effects: { happy: -2 } }] }]; // --- Villa'ya davet eventleri ve özel sorular (her karakter için 2'şer tane) --- var villaInviteEvents = [{ id: "villa_invite_lisa", text: "Artık bir villan var! Lisa'yı eve davet etmek ister misin?", portrait: "lisa", speaker: "Lisa", options: [{ text: "Lisa'yı villaya davet et.", effects: { lisa: 15, happy: 5 }, meta: { type: "villa_invite", character: "lisa" } }, { text: "Davet etme.", effects: { lisa: -2 } }] }, { id: "villa_invite_rebecca", text: "Artık bir villan var! Rebecca'yı eve davet etmek ister misin?", portrait: "rebecca", speaker: "Rebecca", options: [{ text: "Rebecca'yı villaya davet et.", effects: { rebecca: 15, happy: 5 }, meta: { type: "villa_invite", character: "rebecca" } }, { text: "Davet etme.", effects: { rebecca: -2 } }] }, { id: "villa_invite_peter", text: "Artık bir villan var! Peter'ı eve davet etmek ister misin?", portrait: "peter", speaker: "Peter", options: [{ text: "Peter'ı villaya davet et.", effects: { peter: 15, happy: 5 }, meta: { type: "villa_invite", character: "peter" } }, { text: "Davet etme.", effects: { peter: -2 } }] }, { id: "villa_invite_alex", text: "Artık bir villan var! Alex'i eve davet etmek ister misin?", portrait: "alex", speaker: "Alex", options: [{ text: "Alex'i villaya davet et.", effects: { alex: 15, happy: 5 }, meta: { type: "villa_invite", character: "alex" } }, { text: "Davet etme.", effects: { alex: -2 } }] }]; var villaSpecialQuestions = [ // Lisa { id: "villa_lisa_1", text: "Lisa: 'Bu evde birlikte yeni anılar biriktirelim mi?'", portrait: "lisa", speaker: "Lisa", options: [{ text: "Evet, birlikte çok güzel anılarımız olacak.", effects: { lisa: 10, happy: 5 } }, { text: "Ev güzel ama önemli olan sensin.", effects: { lisa: 7, honest: 3 } }] }, { id: "villa_lisa_2", text: "Lisa: 'Villada bir parti verelim mi?'", portrait: "lisa", speaker: "Lisa", options: [{ text: "Harika fikir, parti verelim.", effects: { lisa: 8, happy: 4 } }, { text: "Parti istemiyorum.", effects: { lisa: -3 } }] }, // Rebecca { id: "villa_rebecca_1", text: "Rebecca: 'Villanın havuzunda gece yüzmek ister misin?'", portrait: "rebecca", speaker: "Rebecca", options: [{ text: "Tabii, birlikte yüzmek harika olur.", effects: { rebecca: 10, lust: 5 } }, { text: "Yorgunum, başka zaman.", effects: { rebecca: -2 } }] }, { id: "villa_rebecca_2", text: "Rebecca: 'Villada baş başa bir akşam geçirelim mi?'", portrait: "rebecca", speaker: "Rebecca", options: [{ text: "Evet, baş başa kalmak güzel olur.", effects: { rebecca: 8, happy: 3 } }, { text: "Bugün olmaz.", effects: { rebecca: -2 } }] }, // Peter { id: "villa_peter_1", text: "Peter: 'Bahçede mangal yapalım mı?'", portrait: "peter", speaker: "Peter", options: [{ text: "Mangal harika olur!", effects: { peter: 10, happy: 4 } }, { text: "Başka zaman.", effects: { peter: -2 } }] }, { id: "villa_peter_2", text: "Peter: 'Villada birlikte film gecesi yapalım mı?'", portrait: "peter", speaker: "Peter", options: [{ text: "Evet, film gecesi yapalım.", effects: { peter: 8, happy: 3 } }, { text: "İstemiyorum.", effects: { peter: -2 } }] }, // Alex { id: "villa_alex_1", text: "Alex: 'Bu villada iş toplantısı yapmak isterim.'", portrait: "alex", speaker: "Alex", options: [{ text: "Tabii, toplantı yapabiliriz.", effects: { alex: 10, happy: 2 } }, { text: "Evde iş konuşmak istemiyorum.", effects: { alex: -2 } }] }, { id: "villa_alex_2", text: "Alex: 'Villanın manzarası harika, burada çalışmak isterim.'", portrait: "alex", speaker: "Alex", options: [{ text: "İstediğin zaman gelebilirsin.", effects: { alex: 8, honest: 2 } }, { text: "Evde yalnız kalmak istiyorum.", effects: { alex: -2 } }] }]; // --- Giselle'e özel sorular (yalnızca satın alındıysa gösterilecek) --- var giselleQuestions = [{ id: "giselle_intro", text: "Giselle: 'Mike, yeni bir çanta almak istiyorum. Bütçemiz yeterli mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Tabii, hemen alalım. ($500 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -500 } }, { text: "Şu an alamayız, bütçemiz kısıtlı.", effects: { happy: -5, honest: 5 }, meta: { type: "truth" } }] }, { id: "giselle_shopping", text: "Giselle: 'Alışverişe çıkalım mı? Birkaç şey almak istiyorum.'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Giselle'e para ver. ($300 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -300 } }, { text: "Bugün alışveriş yok.", effects: { happy: -5 } }] }, { id: "giselle_dinner", text: "Giselle: 'Bu akşam dışarıda yemek yiyelim mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Lüks restorana git. ($400 harca)", effects: { happy: 10, lust: 5 }, meta: { type: "giselle_spend", money: -400 } }, { text: "Evde yemek yapalım.", effects: { happy: -5 } }] }, { id: "giselle_gift", text: "Giselle: 'Bana hediye alır mısın?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Pahalı bir kolye al. ($1000 harca)", effects: { happy: 10, lust: 5 }, meta: { type: "giselle_spend", money: -1000 } }, { text: "Küçük bir hediye al. ($100 harca)", effects: { happy: 3 }, meta: { type: "giselle_spend", money: -100 } }, { text: "Hediye almayacağım.", effects: { happy: -10 } }] }, { id: "giselle_jealous", text: "Giselle: 'Lisa ile çok vakit geçiriyorsun, kıskanıyorum.'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Giselle'e güven ver.", effects: { happy: 5, honest: 5 } }, { text: "Lisa ile görüşmeyi azalt.", effects: { happy: 2, lust: -2 } }] }, { id: "giselle_party", text: "Giselle: 'Hafta sonu partiye gidelim mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Partiye git. ($200 harca)", effects: { happy: 5, lust: 5 }, meta: { type: "giselle_spend", money: -200 } }, { text: "Evde kalalım.", effects: { happy: -3 } }] }, { id: "giselle_baby", text: "Giselle: 'Bir bebek sahibi olmayı düşünür müsün?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Evet, isterim.", effects: { happy: 10, lust: 5 }, meta: { type: "giselle_baby" } }, { text: "Henüz hazır değilim.", effects: { happy: -5 } }] }, { id: "giselle_trip", text: "Giselle: 'Birlikte tatile çıkalım mı?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Tatile çık. ($1500 harca)", effects: { happy: 10, lust: 5 }, meta: { type: "giselle_spend", money: -1500 } }, { text: "Tatil için paramız yok.", effects: { happy: -5 } }] }, { id: "giselle_friends", text: "Giselle: 'Arkadaşlarımı davet edebilir miyim?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Tabii, davet et.", effects: { happy: 5 } }, { text: "Hayır, bu akşam yalnız kalalım.", effects: { happy: -3 } }] }, { id: "giselle_shoes", text: "Giselle: 'Yeni ayakkabılar almak istiyorum.'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Ayakkabı al. ($250 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -250 } }, { text: "Şu an alamayız.", effects: { happy: -3 } }] }, { id: "giselle_movie", text: "Giselle: 'Bu akşam sinemaya gidelim mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Sinemaya git. ($100 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -100 } }, { text: "Evde film izleyelim.", effects: { happy: 2 } }] }, { id: "giselle_dress", text: "Giselle: 'Yeni bir elbise almak istiyorum.'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Elbise al. ($350 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -350 } }, { text: "Şu an alamayız.", effects: { happy: -3 } }] }, { id: "giselle_jewelry", text: "Giselle: 'Takı mağazasına gidelim mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Takı al. ($200 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -200 } }, { text: "Takı almayalım.", effects: { happy: -2 } }] }, { id: "giselle_spa", text: "Giselle: 'Birlikte spa'ya gidelim mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Spa'ya git. ($400 harca)", effects: { happy: 7 }, meta: { type: "giselle_spend", money: -400 } }, { text: "Evde dinlenelim.", effects: { happy: 2 } }] }, { id: "giselle_phone", text: "Giselle: 'Yeni bir telefon almak istiyorum.'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Telefon al. ($1200 harca)", effects: { happy: 10 }, meta: { type: "giselle_spend", money: -1200 } }, { text: "Şu an alamayız.", effects: { happy: -5 } }] }, { id: "giselle_bag", text: "Giselle: 'Çantam eskidi, yenisini alabilir miyiz?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Çanta al. ($300 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -300 } }, { text: "Şu an alamayız.", effects: { happy: -3 } }] }, { id: "giselle_makeup", text: "Giselle: 'Kozmetik alışverişi yapalım mı?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Kozmetik al. ($150 harca)", effects: { happy: 3 }, meta: { type: "giselle_spend", money: -150 } }, { text: "Hayır, gerek yok.", effects: { happy: -2 } }] }, { id: "giselle_jacket", text: "Giselle: 'Yeni bir ceket almak istiyorum.'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Ceket al. ($400 harca)", effects: { happy: 5 }, meta: { type: "giselle_spend", money: -400 } }, { text: "Şu an alamayız.", effects: { happy: -3 } }] }, { id: "giselle_ring", text: "Giselle: 'Yüzük bakmaya gidelim mi?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Yüzük al. ($800 harca)", effects: { happy: 8 }, meta: { type: "giselle_spend", money: -800 } }, { text: "Yüzük almayalım.", effects: { happy: -3 } }] }, { id: "giselle_baby2", text: "Giselle: 'Bebek sahibi olmayı hâlâ düşünüyor musun?'", portrait: "giselle", speaker: "Giselle", options: [{ text: "Evet, isterim.", effects: { happy: 10, lust: 5 }, meta: { type: "giselle_baby" } }, { text: "Henüz hazır değilim.", effects: { happy: -5 } }] }]; // --- Ana story havuzu --- var story = [ // Lisa kahvaltı - düşük ilişki { id: "lisa_breakfast_low", text: "Lisa sabah kahvaltı hazırlamış ama aranız biraz soğuk. Mike ne der?", portrait: 'lisa', speaker: 'Lisa', mood: "sad", barCheck: { key: "lisa", max: 40 }, options: [{ text: "Yine mi aynı şey, biraz değişiklik yap.", effects: { lisa: -10, happy: -5 }, meta: { type: "truth" }, next: null }, { text: "Teşekkür etmeden geçiştir.", effects: { lisa: -5 }, meta: { type: "lie" }, next: null }] }, // Lisa kahvaltı - orta ilişki { id: "lisa_breakfast_mid", text: "Lisa sabah kahvaltı hazırlamış. Mike ne der?", portrait: 'lisa', speaker: 'Lisa', mood: "neutral", barCheck: { key: "lisa", min: 41, max: 80 }, regretTrigger: "lied", options: [{ text: "Çok güzel olmuş, teşekkür ederim.", effects: { lisa: 10, happy: 5 }, next: null }, { text: "Yine mi aynı şey, biraz değişiklik yap.", effects: { lisa: -10, happy: -5 }, meta: { type: "lie" }, next: null }] }, // Lisa kahvaltı - yüksek ilişki { id: "lisa_breakfast_high", text: "Lisa sabah kahvaltı hazırlamış, aranız çok iyi. Mike ne der?", portrait: 'lisa', speaker: 'Lisa', mood: "happy", barCheck: { key: "lisa", min: 81 }, options: [{ text: "Sana her gün teşekkür etsem az, harikasın.", effects: { lisa: 10, happy: 10 }, next: null }, { text: "Bugün de seninle kahvaltı yapmak çok güzel.", effects: { lisa: 5, happy: 5 }, next: null }] }, // Rebecca sabah mesaj - düşük ilişki { id: "rebecca_morning_low", text: "Rebecca sabah mesaj atıyor ama aranız biraz soğuk: 'Günaydın, öğle arasında buluşalım mı?'", portrait: 'rebecca', speaker: 'Rebecca', mood: "sad", barCheck: { key: "rebecca", max: 40 }, options: [{ text: "Şu an yoğunum, sonra konuşuruz.", effects: { rebecca: -5, honest: 5 }, meta: { type: "truth" }, next: null }, { text: "Kısa cevap ver.", effects: { rebecca: -5 }, meta: { type: "lie" }, next: null }] }, // Rebecca sabah mesaj - orta ilişki { id: "rebecca_morning_mid", text: "Rebecca sabah mesaj atıyor: 'Günaydın, öğle arasında buluşalım mı?'", portrait: 'rebecca', speaker: 'Rebecca', mood: "neutral", barCheck: { key: "rebecca", min: 41, max: 80 }, options: [{ text: "Tabii, öğle arasında buluşalım.", effects: { rebecca: 10, lust: 5, betray: 5 }, next: null }, { text: "Şu an yoğunum, sonra konuşuruz.", effects: { rebecca: -5, honest: 5 }, next: null }] }, // Rebecca sabah mesaj - yüksek ilişki { id: "rebecca_morning_high", text: "Rebecca sabah mesaj atıyor, aranız çok iyi: 'Günaydın yakışıklı, öğle arasında buluşalım mı?'", portrait: 'rebecca', speaker: 'Rebecca', mood: "happy", barCheck: { key: "rebecca", min: 81 }, options: [{ text: "Seni görmek için sabırsızlanıyorum.", effects: { rebecca: 10, lust: 10, betray: 10 }, next: null }, { text: "Bugün işim var ama akşam konuşalım.", effects: { rebecca: 5, honest: 5 }, next: null }] }, // ... (diğer orijinal story node'lar buraya eklenebilir, örnek olarak ilk iki olay çoğaltıldı) // 3 { text: "Patronun Alex seni sert bir şekilde eleştiriyor. Ne yaparsın?", portrait: 'alex', speaker: 'Alex', mood: "angry", options: [{ text: "Haklısınız, daha dikkatli olacağım.", effects: { alex: 10, honest: 5, happy: -5 }, next: null }, { text: "Bana fazla yükleniyorsunuz, adil değil.", effects: { alex: -10, happy: -5 }, next: null }] }, // --- Ava: New story questions for more variety --- { text: "Lisa ile alışverişe çıktınız. Lisa yeni bir elbise almak istiyor.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Elbise almasına destek ol.", effects: { lisa: 10, happy: 5 } }, { text: "Bütçemiz kısıtlı, başka zaman alalım.", effects: { lisa: -5, honest: 5 } }] }, { text: "Rebecca iş yerinde sana bir sır veriyor.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Sırrını sakla.", effects: { rebecca: 10, honest: 5 } }, { text: "Sırrı başkasına anlat.", effects: { rebecca: -10, betray: 10 } }] }, { text: "Peter ile futbol maçı izliyorsunuz.", portrait: 'peter', speaker: 'Peter', options: [{ text: "Beraber tezahürat yap.", effects: { peter: 10, happy: 5 } }, { text: "Maçtan sıkıldığını söyle.", effects: { peter: -5 } }] }, { text: "Alex yeni bir iş fırsatı sunuyor.", portrait: 'alex', speaker: 'Alex', options: [{ text: "Fırsatı kabul et.", effects: { alex: 10, happy: 5 } }, { text: "Reddet, mevcut işinden memnunsun.", effects: { alex: -5, honest: 5 } }] }, { text: "Lisa ile tartıştınız. Lisa üzgün.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Özür dile.", effects: { lisa: 10, honest: 5 } }, { text: "Haklı olduğunu savun.", effects: { lisa: -10 } }] }, { text: "Rebecca ile sinemaya gitme planı yapıyorsun.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Romantik bir film seç.", effects: { rebecca: 10, lust: 5 } }, { text: "Aksiyon filmi seç.", effects: { rebecca: 5 } }] }, { text: "Peter sana bir kitap öneriyor.", portrait: 'peter', speaker: 'Peter', options: [{ text: "Kitabı oku ve yorum yap.", effects: { peter: 10, honest: 5 } }, { text: "Kitabı okumadığını itiraf et.", effects: { peter: -5, honest: 5 } }] }, { text: "Alex ile iş seyahatine çıkıyorsun.", portrait: 'alex', speaker: 'Alex', options: [{ text: "Alex ile yakınlaş.", effects: { alex: 10, betray: 5 } }, { text: "Mesafeni koru.", effects: { alex: 5, honest: 5 } }] }, { text: "Lisa sana sürpriz bir doğum günü partisi hazırlıyor.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Çok mutlu ol ve teşekkür et.", effects: { lisa: 10, happy: 10 } }, { text: "Sürprizleri sevmediğini söyle.", effects: { lisa: -5, honest: 5 } }] }, { text: "Rebecca ile bir tartışma yaşıyorsun.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Barışmak için adım at.", effects: { rebecca: 10 } }, { text: "Tartışmayı uzat.", effects: { rebecca: -10 } }] }, { text: "Peter ile eski bir fotoğraf albümüne bakıyorsun.", portrait: 'peter', speaker: 'Peter', options: [{ text: "Güzel anıları hatırla.", effects: { peter: 10, happy: 5 } }, { text: "Geçmişi konuşmak istemediğini söyle.", effects: { peter: -5 } }] }, { text: "Alex iş yerinde seni övüyor.", portrait: 'alex', speaker: 'Alex', options: [{ text: "Teşekkür et.", effects: { alex: 10, happy: 5 } }, { text: "Mütevazı davran.", effects: { alex: 5 } }] }, { text: "Lisa ile birlikte yemek yapıyorsun.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Birlikte eğlenerek yemek yap.", effects: { lisa: 10, happy: 5 } }, { text: "Yemek yapmayı sevmediğini söyle.", effects: { lisa: -5 } }] }, { text: "Rebecca yeni bir hobiye başlamak istiyor.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Onu destekle.", effects: { rebecca: 10 } }, { text: "Hobisini gereksiz bul.", effects: { rebecca: -5 } }] }, { text: "Peter ile bir iş projesinde çalışıyorsun.", portrait: 'peter', speaker: 'Peter', options: [{ text: "Peter'ın fikirlerine değer ver.", effects: { peter: 10 } }, { text: "Kendi bildiğini yap.", effects: { peter: -5 } }] }, { text: "Alex ile bir anlaşmazlık yaşıyorsun.", portrait: 'alex', speaker: 'Alex', options: [{ text: "Uzlaşmacı ol.", effects: { alex: 10 } }, { text: "Kendi fikrinde ısrar et.", effects: { alex: -5 } }] }, // 3 { text: "Patronun Alex seni sert bir şekilde eleştiriyor. Ne yaparsın?", portrait: 'alex', speaker: 'Alex', mood: "angry", options: [{ text: "Haklısınız, daha dikkatli olacağım.", effects: { alex: 10, honest: 5, happy: -5 }, next: null }, { text: "Bana fazla yükleniyorsunuz, adil değil.", effects: { alex: -10, happy: -5 }, next: null }] }, // 4 { text: "Peter zor durumda olduğunu söylüyor. Ne yaparsın?", portrait: 'peter', speaker: 'Peter', mood: "sad", options: [{ text: "Yanındayım, neye ihtiyacın varsa söyle.", effects: { peter: 10, happy: 5 }, next: null }, { text: "Kendi işimle meşgulüm, üzgünüm.", effects: { peter: -10, happy: -5 }, next: null }] }, // 5 { text: "Lisa seninle dürüstçe konuşmak istiyor. Ne yaparsın?", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Tabii, ne söylemek istiyorsan dinliyorum.", effects: { lisa: 10, honest: 10 }, next: null }, { text: "Bunları konuşmak istemiyorum.", effects: { lisa: -10, honest: -10 }, next: null }] }, // 6 { text: "Rebecca ile ofiste samimi bir an yaşıyorsun. Lisa yanında.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Lisa burada, sonra konuşalım.", effects: { rebecca: -5, honest: 5 }, next: null }, { text: "Hemen sana geliyorum.", effects: { rebecca: 10, lisa: -10, betray: 10 }, next: null }] }, // 7 { text: "Yorgunsun, Lisa dışarı çıkmak istiyor.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Bugün yorgunum, evde kalalım.", effects: { lisa: -5, happy: -5 }, next: null }, { text: "Tamam, seninle dışarı çıkalım.", effects: { lisa: 10, happy: 5 }, next: null }] }, // 8 { text: "Alex önemli bir projeyi sana teslim etti.", portrait: 'alex', speaker: 'Alex', mood: "neutral", options: [{ text: "Gerçekçi zaman verirsek başarı şansı artar.", effects: { alex: 10, honest: 10 }, next: null }, { text: "Mümkün olduğunca hızlı yapacağım, sorun yok.", effects: { alex: -5, happy: 5 }, next: null }] }, // 9 { text: "Peter geçmişte yaptığın bir hatayı hatırlatıyor.", portrait: 'peter', speaker: 'Peter', mood: "angry", regretTrigger: "ignored_peter", options: [{ text: "Haklısın, özür dilerim.", effects: { peter: 10, honest: 10 }, next: null }, { text: "O günler geçti, unutalım.", effects: { peter: -10 }, meta: { ignoreRegret: true }, next: null }] }, // 10 { text: "Lisa bir sır sakladığını düşünüyor.", portrait: 'lisa', speaker: 'Lisa', regretTrigger: "betrayed_lisa", options: [{ text: "Sana her şeyi anlatacağım.", effects: { lisa: 10, honest: 10 }, next: null }, { text: "Beni yanlış anlıyorsun.", effects: { lisa: -10, honest: -10 }, meta: { type: "lie" }, next: null }] }, // 11 { text: "Rebecca ile iş çıkışı kafede buluşuyorsun.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Rebecca ile samimi bir sohbet et.", effects: { rebecca: 10, lust: 10, betray: 5 }, next: null }, { text: "Kısa kesip eve git.", effects: { rebecca: -5, lisa: 5, honest: 5 }, next: null }] }, // 12 { text: "Alex seni fazla mesaiye bırakmak istiyor.", portrait: 'alex', speaker: 'Alex', mood: "neutral", options: [{ text: "Kabul et, işini bitir.", effects: { alex: 10, happy: -5 }, next: null }, { text: "Reddet, eve git.", effects: { alex: -10, lisa: 5, happy: 5 }, next: null }] }, // 13 { text: "Peter ile eski günlerden konuşuyorsun.", portrait: 'peter', speaker: 'Peter', mood: "happy", options: [{ text: "Duygusal bir anı paylaş.", effects: { peter: 10, happy: 5 }, next: null }, { text: "Geçmişi geçiştir.", effects: { peter: -5 }, next: null }] }, // 14 { text: "Lisa ile romantik bir akşam yemeği.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Lisa'ya iltifat et.", effects: { lisa: 10, happy: 10, lust: 5 }, next: null }, { text: "Yemekle ilgilenme, telefona bak.", effects: { lisa: -10, happy: -5, lust: -5 }, next: null }] }, // 15 { text: "Rebecca işte sana yardım ediyor.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Teşekkür et, birlikte çalış.", effects: { rebecca: 10, honest: 5 }, next: null }, { text: "Yardımı reddet.", effects: { rebecca: -5 }, next: null }] }, // 16 { text: "Alex işte bir hata buldu.", portrait: 'alex', speaker: 'Alex', mood: "angry", options: [{ text: "Hatanı kabul et.", effects: { alex: 5, honest: 10 }, next: null }, { text: "Suçu başkasına at.", effects: { alex: -10, honest: -10, betray: 10 }, next: null }] }, // 17 { text: "Peter ile tartıştın.", portrait: 'peter', speaker: 'Peter', mood: "angry", options: [{ text: "Barışmak için adım at.", effects: { peter: 10, honest: 5 }, next: null }, { text: "Görmezden gel.", effects: { peter: -10, happy: -5 }, next: null }] }, // 18 { text: "Lisa ile hafta sonu planı yapıyorsun.", portrait: 'lisa', speaker: 'Lisa', options: [{ text: "Birlikte sinemaya git.", effects: { lisa: 10, happy: 5 }, next: null }, { text: "Evde kalmayı teklif et.", effects: { lisa: -5, happy: 5 }, next: null }] }, // 19 { text: "Rebecca ile iş gezisine çıkıyorsun.", portrait: 'rebecca', speaker: 'Rebecca', options: [{ text: "Samimi davran.", effects: { rebecca: 10, lust: 10, betray: 5 }, next: null }, { text: "Mesafeni koru.", effects: { rebecca: -5, honest: 5 }, next: null }] }, // 20 { text: "Alex yeni bir görev veriyor.", portrait: 'alex', speaker: 'Alex', mood: "neutral", options: [{ text: "Görevi kabul et.", effects: { alex: 10, happy: 5 }, next: null }, { text: "Görevi reddet.", effects: { alex: -10, happy: -5 }, next: null }] }]; // --- State --- // Relationship values (0-100) var rel_lisa = 50; var rel_rebecca = 50; var rel_peter = 50; var rel_alex = 50; // Bars (0-100) var bar_happy = 50; var bar_honest = 50; var bar_lust = 50; var bar_betray = 50; // --- Shadow bar (0-100, hidden from player) --- var bar_shadow = 0; // Bar-based flags (for special scenes/endings) var flags = {}; // Track important past choices for memory mechanic var pastChoices = []; // Turn counter for time-based triggers var turnCount = 0; // --- Ava: Time, salary, baby, pregnancy, money mechanics --- var dayCount = 1; // 1-based, every 2 questions = 1 day var mikeSalary = 100; var mikeMoney = 0; var mikeBabyCount = 0; var lisaPregnant = false; var rebeccaPregnant = false; var gisellePregnant = false; var showLisaPregOption = false; var showRebeccaPregOption = false; var showGisellePregOption = false; var giselleUnlocked = false; // Satın alındı mı? var shopItemStates = [false, false, false, false]; // 0: Giselle, 1-3: diğerleri // --- UI Elements --- // Portrait var portraitNode = null; // Speaker name var speakerText = null; // Story text var storyText = null; // Option buttons var optionButtons = []; // Relationship bars var barNodes = {}; // Karakter portreleri ve ilişki dereceleri için UI var characterPortraits = []; var characterLabels = []; // --- Ava: UI for day, salary, money, baby count --- var dayText = null; var salaryText = null; var moneyText = null; var babyText = null; // --- Functions --- // getNextNode: uygun story node'unu bar değerine göre seç // --- Ava: Prevent same question from repeating within last 20, and add more questions --- var lastStoryIndices = []; function getNextNode() { // Tüm story node'larını karıştır var indices = []; for (var i = 0; i < story.length; i++) { indices.push(i); } // Fisher-Yates shuffle for (var i = indices.length - 1; i > 0; i--) { var j = Math.floor(Math.random() * (i + 1)); var temp = indices[i]; indices[i] = indices[j]; indices[j] = temp; } // Ava: Filter out nodes that were used in the last 20 var filteredIndices = []; for (var k = 0; k < indices.length; k++) { var idx = indices[k]; if (lastStoryIndices.indexOf(idx) === -1) { filteredIndices.push(idx); } } // If less than 5 available, allow all (reset) var useIndices = filteredIndices.length > 5 ? filteredIndices : indices; // --- Giselle: Eğer satın alındıysa, havuza Giselle sorularını da ekle --- // --- Whiskey: Eğer satın alındıysa, havuza Whiskey sorularını da ekle --- // --- Villa: Eğer satın alındıysa, havuza Villa event ve sorularını da ekle --- var pool = []; for (var k = 0; k < useIndices.length; k++) { var idx = useIndices[k]; var node = story[idx]; // Sadece Giselle alınmışsa Giselle soruları havuza eklenir if (node && node.portrait === "giselle" && !giselleUnlocked) continue; // Sadece Whiskey alınmışsa Whiskey soruları havuza eklenir if (node && node.portrait === "whiskey" && !whiskeyUnlocked) continue; // Villa eventleri ve soruları sadece villaUnlocked ise eklenir if (node && node.id && node.id.indexOf("villa_") === 0 && !villaUnlocked) continue; pool.push({ idx: idx, node: node }); } if (giselleUnlocked) { // Son 20'de olmayan Giselle sorularını da ekle for (var g = 0; g < giselleQuestions.length; g++) { var gq = giselleQuestions[g]; var gqId = "giselle_" + g; // Sadece son 20'de yoksa ekle var alreadyUsed = false; for (var h = 0; h < lastStoryIndices.length; h++) { if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === gq.id) alreadyUsed = true; } if (!alreadyUsed) { pool.push({ idx: -1, node: gq }); } } } if (whiskeyUnlocked) { // Son 20'de olmayan Whiskey sorularını da ekle for (var w = 0; w < whiskeyQuestions.length; w++) { var wq = whiskeyQuestions[w]; var wqId = "whiskey_" + w; var alreadyUsedW = false; for (var h = 0; h < lastStoryIndices.length; h++) { if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === wq.id) alreadyUsedW = true; } if (!alreadyUsedW) { pool.push({ idx: -1, node: wq }); } } } if (villaUnlocked) { // Son 20'de olmayan Villa invite eventlerini ekle for (var v = 0; v < villaInviteEvents.length; v++) { var ve = villaInviteEvents[v]; var alreadyUsedV = false; for (var h = 0; h < lastStoryIndices.length; h++) { if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === ve.id) alreadyUsedV = true; } if (!alreadyUsedV) { pool.push({ idx: -1, node: ve }); } } // Son 20'de olmayan Villa özel sorularını ekle for (var vq = 0; vq < villaSpecialQuestions.length; vq++) { var vsq = villaSpecialQuestions[vq]; var alreadyUsedVSQ = false; for (var h = 0; h < lastStoryIndices.length; h++) { if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === vsq.id) alreadyUsedVSQ = true; } if (!alreadyUsedVSQ) { pool.push({ idx: -1, node: vsq }); } } } // Her bir node'u sırayla kontrol et, barCheck varsa uygun olanı döndür for (var k = 0; k < pool.length; k++) { var idx = pool[k].idx; var node = pool[k].node; if (!node.options || node.options.length === 0) continue; if (node.barCheck) { var key = node.barCheck.key; var min = typeof node.barCheck.min === "number" ? node.barCheck.min : -Infinity; var max = typeof node.barCheck.max === "number" ? node.barCheck.max : Infinity; var val = 0; if (key === "lisa") val = rel_lisa;else if (key === "rebecca") val = rel_rebecca;else if (key === "peter") val = rel_peter;else if (key === "alex") val = rel_alex;else if (key === "happy") val = bar_happy;else if (key === "honest") val = bar_honest;else if (key === "lust") val = bar_lust;else if (key === "betray") val = bar_betray; if (val >= min && val <= max) { lastStoryIndices.push(idx); if (lastStoryIndices.length > 20) lastStoryIndices.shift(); return idx; } } else { lastStoryIndices.push(idx); if (lastStoryIndices.length > 20) lastStoryIndices.shift(); return idx; } } // Hiçbiri uygun değilse ilk node'u döndür lastStoryIndices.push(0); if (lastStoryIndices.length > 20) lastStoryIndices.shift(); return 0; } function resetGameState() { rel_lisa = 50; rel_rebecca = 50; rel_peter = 50; rel_alex = 50; bar_happy = 50; bar_honest = 50; bar_lust = 50; bar_betray = 50; bar_shadow = 0; flags = {}; pastChoices = []; turnCount = 0; currentNode = 0; // Reset dramatic system nextDramaticTurn = 4 + Math.floor(Math.random() * 3); dramaticHistory = []; if (game._dramaticShadow) { game.removeChild(game._dramaticShadow); game._dramaticShadow = null; } dayCount = 1; mikeSalary = 100; mikeMoney = 0; mikeBabyCount = 0; lisaPregnant = false; rebeccaPregnant = false; gisellePregnant = false; giselleUnlocked = false; whiskeyUnlocked = false; villaUnlocked = false; shopItemStates = [false, false, false, false]; if (storage) { storage.mikeMoney = 0; storage.mikeSalary = 100; storage.mikeBabyCount = 0; storage.dayCount = 1; storage.lisaPregnant = false; storage.rebeccaPregnant = false; storage.gisellePregnant = false; storage.giselleUnlocked = false; storage.whiskeyUnlocked = false; storage.villaUnlocked = false; } } function createUI() { // Portrait if (portraitNode) game.removeChild(portraitNode); portraitNode = LK.getAsset('mike', { anchorX: 0.5, anchorY: 0.5 }); // Mike portresini ve karakteri ekrana tam ortala portraitNode.x = 2048 / 2; portraitNode.y = 520; game.addChild(portraitNode); // --- Mike portresine titreme animasyonu ekle --- function shakePortrait(node) { if (!node) return; var origX = 2048 / 2; var origY = 520; function doShake() { // Rastgele küçük bir ofset (±8px) var dx = (Math.random() - 0.5) * 16; var dy = (Math.random() - 0.5) * 10; tween(node, { x: origX + dx, y: origY + dy }, { duration: 80, easing: tween.linear, onFinish: function onFinish() { tween(node, { x: origX, y: origY }, { duration: 80, easing: tween.linear, onFinish: function onFinish() { LK.setTimeout(doShake, 80 + Math.floor(Math.random() * 60)); } }); } }); } doShake(); } shakePortrait(portraitNode); // --- Eğer ilgili karakter portresi varsa ona da titreme ekle --- if (game.relatedPortraitNode) { var _shakeRelated = function shakeRelated() { if (!relNode.parent) return; // Silindiyse dur var dx = (Math.random() - 0.5) * 16; var dy = (Math.random() - 0.5) * 10; tween(relNode, { x: relOrigX + dx, y: relOrigY + dy }, { duration: 80, easing: tween.linear, onFinish: function onFinish() { tween(relNode, { x: relOrigX, y: relOrigY }, { duration: 80, easing: tween.linear, onFinish: function onFinish() { LK.setTimeout(_shakeRelated, 80 + Math.floor(Math.random() * 60)); } }); } }); }; var relNode = game.relatedPortraitNode; var relOrigX = relNode.x; var relOrigY = relNode.y; _shakeRelated(); } // Speaker (isim) biraz daha aşağıda if (speakerText) game.removeChild(speakerText); speakerText = new Text2('', { size: 64, fill: '#ffffff' }); speakerText.anchor.set(0.5, 0.5); speakerText.x = 2048 / 2; speakerText.y = 740; game.addChild(speakerText); // Story text (olay) biraz daha aşağıda if (storyText) game.removeChild(storyText); storyText = new Text2('', { size: 54, fill: '#ffffff', wordWrap: true, wordWrapWidth: 1800 }); storyText.anchor.set(0.5, 0); storyText.x = 2048 / 2; storyText.y = 830; game.addChild(storyText); // Relationship bars var barNames = [{ key: 'happy', label: 'Mutluluk', y: 1100, val: bar_happy }, { key: 'honest', label: 'Dürüstlük', y: 1180, val: bar_honest }, { key: 'lust', label: 'Şehvet', y: 1260, val: bar_lust }, { key: 'betray', label: 'İhanet', y: 1340, val: bar_betray }]; for (var i = 0; i < barNames.length; i++) { var b = barNames[i]; if (barNodes[b.key]) game.removeChild(barNodes[b.key]); var bar = new RelationshipBar(); bar.setType(b.key); bar.setValue(b.val); // Bar ismi ve yüzdeyi birlikte göster if (bar.label) bar.removeChild(bar.label); bar.label = new Text2(b.label + ' (' + b.val + '%)', { size: 36, fill: '#ffffff' }); bar.label.anchor.set(1, 0.5); bar.label.x = bar.maxWidth + 20; bar.label.y = 20; bar.addChild(bar.label); bar.x = 2048 / 2 - 200; bar.y = b.y; game.addChild(bar); barNodes[b.key] = bar; } // Karakter portreleri ve ilişki dereceleri (en altta) for (var i = 0; i < characterPortraits.length; i++) { game.removeChild(characterPortraits[i]); } for (var i = 0; i < characterLabels.length; i++) { game.removeChild(characterLabels[i]); } characterPortraits = []; characterLabels = []; var chars = [{ key: 'lisa', label: 'Lisa', rel: rel_lisa }, { key: 'rebecca', label: 'Rebecca', rel: rel_rebecca }, { key: 'peter', label: 'Peter', rel: rel_peter }, { key: 'alex', label: 'Alex', rel: rel_alex }]; var startX = 2048 / 2 - 400 - 60; var y = 2600; for (var i = 0; i < chars.length; i++) { var c = chars[i]; var portrait = LK.getAsset(c.key, { anchorX: 0.5, anchorY: 1 }); portrait.x = startX + i * 270; portrait.y = y; game.addChild(portrait); characterPortraits.push(portrait); var label = new Text2(c.label + ': ' + c.rel + '%', { size: 44, fill: '#ffffff' }); label.anchor.set(0.5, 0); label.x = portrait.x; label.y = y + 10; game.addChild(label); characterLabels.push(label); } // --- Ava: Add day, salary, money, baby count UI --- if (dayText) game.removeChild(dayText); if (salaryText) game.removeChild(salaryText); if (moneyText) game.removeChild(moneyText); if (babyText) game.removeChild(babyText); dayText = new Text2('Gün: ' + dayCount, { size: 54, fill: '#fff' }); dayText.anchor.set(0, 0); dayText.x = 120; dayText.y = 80; game.addChild(dayText); salaryText = new Text2('Maaş: $' + mikeSalary, { size: 54, fill: '#fff' }); salaryText.anchor.set(0, 0); salaryText.x = 120; salaryText.y = 150; game.addChild(salaryText); moneyText = new Text2('Para: $' + mikeMoney, { size: 54, fill: '#fff' }); moneyText.anchor.set(0, 0); moneyText.x = 120; moneyText.y = 220; game.addChild(moneyText); babyText = new Text2('Bebek: ' + mikeBabyCount, { size: 54, fill: '#fff' }); babyText.anchor.set(0, 0); babyText.x = 120; babyText.y = 290; game.addChild(babyText); // --- Ava: Show relationship options if eligible --- // Remove old relationship option buttons if any if (game._relOptionBtns) { for (var i = 0; i < game._relOptionBtns.length; i++) { game.removeChild(game._relOptionBtns[i]); } } game._relOptionBtns = []; // --- Shop/Store UI (right side, vertical) --- if (game._shopNodes) { for (var i = 0; i < game._shopNodes.length; i++) { game.removeChild(game._shopNodes[i]); } } game._shopNodes = []; var shopAssetIds = ['giselle', 'shop_item2', 'shop_item3', 'shop_item4']; var shopPrices = [10000, 2500, 50000, 7500]; var shopLabels = ['Giselle', 'Whiskey', 'Villa', 'Eşya 4']; var shopYStart = 1200; // moved even further down var shopSpacing = 450; // even more space between items // --- Villa state --- if (typeof villaUnlocked === "undefined") villaUnlocked = false; if (typeof whiskeyUnlocked === "undefined") whiskeyUnlocked = false; for (var i = 0; i < 4; i++) { var assetId = shopAssetIds[i]; var node = LK.getAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); node.x = 2048 - 120; node.y = shopYStart + i * shopSpacing; node.scale.x = node.scale.y = 1.0; // Shop items are passive (dimmed, not interactive) until purchased, then active if (shopItemStates[i]) { node.alpha = 1.0; node.interactive = false; node.buttonMode = false; } else { node.alpha = 0.5; node.interactive = true; node.buttonMode = true; } // Price label (above the item) var priceText = ""; if (i === 0) { priceText = "$10,000"; } else if (i === 1) { priceText = "$2,500"; } else if (i === 2) { priceText = "$50,000"; } else if (i === 3) { priceText = "$7,500"; } var priceLabel = new Text2(priceText, { size: 38, fill: '#ffe066', fontWeight: 'bold' }); priceLabel.anchor.set(0.5, 1); priceLabel.x = node.x; priceLabel.y = node.y - node.height / 2 - 12; game.addChild(priceLabel); game._shopNodes.push(priceLabel); // Name label (below the item) var label = new Text2(shopLabels[i], { size: 36, fill: '#fff', wordWrap: true, wordWrapWidth: 180 }); label.anchor.set(0.5, 0); label.x = node.x; label.y = node.y + node.height / 2 + 10; game.addChild(node); game.addChild(label); game._shopNodes.push(node, label); // Giselle buy logic if (i === 0 && !giselleUnlocked) { node.down = function () { if (mikeMoney >= 10000) { mikeMoney -= 10000; giselleUnlocked = true; shopItemStates[0] = true; // After purchase, make the item active (full alpha, not interactive) node.alpha = 1.0; node.interactive = false; node.buttonMode = false; updateBars(); createUI(); } else { // Not enough money, flash red tween(node, { alpha: 0.3 }, { duration: 120, onFinish: function onFinish() { tween(node, { alpha: 1 }, { duration: 120 }); } }); } }; } // Whiskey buy logic if (i === 1 && !whiskeyUnlocked) { node.down = function () { if (mikeMoney >= 2500) { mikeMoney -= 2500; whiskeyUnlocked = true; shopItemStates[1] = true; // After purchase, make the item active (full alpha, not interactive) node.alpha = 1.0; node.interactive = false; node.buttonMode = false; updateBars(); createUI(); } else { // Not enough money, flash red tween(node, { alpha: 0.3 }, { duration: 120, onFinish: function onFinish() { tween(node, { alpha: 1 }, { duration: 120 }); } }); } }; } // Villa buy logic if (i === 2 && !villaUnlocked) { node.down = function () { if (mikeMoney >= 50000) { mikeMoney -= 50000; villaUnlocked = true; shopItemStates[2] = true; // After purchase, make the item active (full alpha, not interactive) node.alpha = 1.0; node.interactive = false; node.buttonMode = false; updateBars(); createUI(); } else { tween(node, { alpha: 0.3 }, { duration: 120, onFinish: function onFinish() { tween(node, { alpha: 1 }, { duration: 120 }); } }); } }; } } // Lisa if (rel_lisa > 70 && !lisaPregnant) { var btnLisa = new OptionButton(); btnLisa.setText("Lisa ile ilişkiye gir"); btnLisa.x = 2048 - 400; btnLisa.y = 80; btnLisa.setCallback(function () { // %30 hamile kalma şansı if (Math.random() < 0.3) { lisaPregnant = true; showStoryNode(currentNode); } }); game.addChild(btnLisa); game._relOptionBtns.push(btnLisa); } // Rebecca if (rel_rebecca > 70 && !rebeccaPregnant) { var btnRebecca = new OptionButton(); btnRebecca.setText("Rebecca ile ilişkiye gir"); btnRebecca.x = 2048 - 400; btnRebecca.y = 220; btnRebecca.setCallback(function () { if (Math.random() < 0.3) { rebeccaPregnant = true; showStoryNode(currentNode); } }); game.addChild(btnRebecca); game._relOptionBtns.push(btnRebecca); } // Giselle if (giselleUnlocked && !gisellePregnant) { var btnGiselle = new OptionButton(); btnGiselle.setText("Giselle ile ilişkiye gir"); btnGiselle.x = 2048 - 400; btnGiselle.y = 360; btnGiselle.setCallback(function () { if (Math.random() < 0.3) { gisellePregnant = true; showStoryNode(currentNode); } }); game.addChild(btnGiselle); game._relOptionBtns.push(btnGiselle); } } function updateBars() { if (typeof villaUnlocked !== "undefined" && villaUnlocked && bar_happy < 80) { bar_happy = 80; } barNodes['happy'].setValue(bar_happy); barNodes['honest'].setValue(bar_honest); barNodes['lust'].setValue(bar_lust); barNodes['betray'].setValue(bar_betray); // Bar isimleri ve yüzdeleri birlikte güncellensin barNodes['happy'].label.setText('Mutluluk (' + bar_happy + '%)'); barNodes['honest'].label.setText('Dürüstlük (' + bar_honest + '%)'); barNodes['lust'].label.setText('Şehvet (' + bar_lust + '%)'); barNodes['betray'].label.setText('İhanet (' + bar_betray + '%)'); // Karakter ilişki dereceleri güncellensin var rels = [rel_lisa, rel_rebecca, rel_peter, rel_alex]; var _loop = function _loop() { names = ['Lisa', 'Rebecca', 'Peter', 'Alex']; label = characterLabels[i]; prevText = label.text; newText = names[i] + ': ' + rels[i] + '%'; // Değer değiştiyse animasyon başlat if (prevText !== newText) { // Son değeri bul prevVal = 0; match = prevText && prevText.match(/: (\-?\d+)%/); if (match) prevVal = parseInt(match[1]); newVal = rels[i]; // Pozitif veya negatif değişim: sadece etkilenen karakter titresin if (newVal > prevVal || newVal < prevVal) { // Sadece ilişki değeri değişen karakter titresin portrait = characterPortraits[i]; if (portrait) { var _doShakeChar = function doShakeChar() { if (!portrait.parent || shakeCount >= 6) { // Titreme bitti, orijinal konuma dön portrait.x = origX; portrait.y = origY; return; } var dx = (Math.random() - 0.5) * 16; var dy = (Math.random() - 0.5) * 10; tween(portrait, { x: origX + dx, y: origY + dy }, { duration: 50, easing: tween.linear, onFinish: function onFinish() { tween(portrait, { x: origX, y: origY }, { duration: 50, easing: tween.linear, onFinish: function onFinish() { shakeCount++; LK.setTimeout(_doShakeChar, 10); } }); } }); }; // Titreme animasyonu uygula origX = portrait.x; origY = portrait.y; shakeCount = 0; _doShakeChar(); } } if (newVal > prevVal) { if (label.style) label.style.fill = '#00ff00'; tween(label, { alpha: 0.3 }, { duration: 120, easing: tween.linear, onFinish: function (lbl) { tween(lbl, { alpha: 1 }, { duration: 120, easing: tween.linear, onFinish: function (lbl2) { if (lbl2.style) lbl2.style.fill = '#ffffff'; }.bind(null, label) }); }.bind(null, label) }); } else if (newVal < prevVal) { if (label.style) label.style.fill = '#ff2222'; tween(label, { alpha: 0.3 }, { duration: 120, easing: tween.linear, onFinish: function (lbl) { tween(lbl, { alpha: 1 }, { duration: 120, easing: tween.linear, onFinish: function (lbl2) { if (lbl2.style) lbl2.style.fill = '#ffffff'; }.bind(null, label) }); }.bind(null, label) }); } } label.setText(newText); }, names, label, prevText, newText, prevVal, match, newVal, portrait, origX, origY, shakeCount; for (var i = 0; i < characterLabels.length; i++) { _loop(); } // --- Ava: Update day, salary, money, baby count UI --- if (dayText) dayText.setText('Gün: ' + dayCount); if (salaryText) salaryText.setText('Maaş: $' + mikeSalary); if (moneyText) moneyText.setText('Para: $' + mikeMoney); if (babyText) babyText.setText('Bebek: ' + mikeBabyCount); // Refresh relationship option buttons if (typeof createUI === "function") { // Only refresh if UI is visible (avoid infinite loop) if (game && typeof game._relOptionBtns !== "undefined") { createUI(); } } } function showStoryNode(idx) { // Remove old option buttons for (var i = 0; i < optionButtons.length; i++) { game.removeChild(optionButtons[i]); } optionButtons = []; // Dramatic choice injection: if turnCount >= nextDramaticTurn, show dramatic choice instead if (typeof nextDramaticTurn !== "undefined" && turnCount >= nextDramaticTurn) { showDramaticChoice(); return; } var node = story[idx]; // Portrait if (portraitNode) { if (node.portrait && LK.getAsset(node.portrait, {})) { portraitNode.texture = LK.getAsset(node.portrait, {}).texture; } // Mood-based tint or background for Lisa, Rebecca, Mike, Peter, Alex if (node.mood && (node.portrait === "lisa" || node.portrait === "rebecca" || node.portrait === "mike" || node.portrait === "peter" || node.portrait === "alex")) { // Mood to tint mapping var moodTints = { happy: 0x7ed321, sad: 0x4a90e2, angry: 0xd0021b, neutral: 0xffffff }; var tint = moodTints[node.mood] !== undefined ? moodTints[node.mood] : 0xffffff; portraitNode.tint = tint; } else { portraitNode.tint = 0xffffff; } // Remove any previous related character portrait if (game.relatedPortraitNode) { game.removeChild(game.relatedPortraitNode); game.relatedPortraitNode = null; } // If the node is about a character other than Mike, show that character next to Mike if (node.portrait && node.portrait !== "mike" && (node.portrait === "lisa" || node.portrait === "rebecca" || node.portrait === "peter" || node.portrait === "alex")) { var relatedPortrait = LK.getAsset(node.portrait, { anchorX: 0.5, anchorY: 0.5 }); // Place to the right of Mike, with a small gap relatedPortrait.x = portraitNode.x + portraitNode.width / 2 + relatedPortrait.width / 2 + 40; relatedPortrait.y = portraitNode.y; // Mood tint for related portrait if (node.mood) { var moodTints = { happy: 0x7ed321, sad: 0x4a90e2, angry: 0xd0021b, neutral: 0xffffff }; relatedPortrait.tint = moodTints[node.mood] !== undefined ? moodTints[node.mood] : 0xffffff; } else { relatedPortrait.tint = 0xffffff; } game.addChild(relatedPortrait); game.relatedPortraitNode = relatedPortrait; } else { if (game.relatedPortraitNode) { game.removeChild(game.relatedPortraitNode); game.relatedPortraitNode = null; } } } // Speaker if (speakerText) { speakerText.setText(node.speaker ? node.speaker : ''); } // Story text if (storyText) { // --- Hatırlatma ve Gölgeli Vicdan Mekanizması --- // 1. Eğer bu node bir regretTrigger içeriyorsa ve geçmişte ilgili regretLabel ile bir seçim yapıldıysa, iç ses/rüya olarak göster if (node.regretTrigger && pastChoices.indexOf(node.regretTrigger) !== -1) { // Vicdan sahnesi: iç ses veya rüya efektiyle göster var regretTexts = { "lied": "Gece rüyanda, Lisa'nın sana 'Bana neden yalan söyledin?' dediğini duyuyorsun. Vicdanın sızlıyor.", "betrayed_lisa": "Bir an için Lisa'nın gözlerinde hayal kırıklığını görüyorsun. İç sesin: 'Ona ihanet ettin.'", "ignored_peter": "Peter'ın üzgün bakışları aklından çıkmıyor. İç sesin: 'Dostunu yalnız bıraktın.'" }; var regretText = regretTexts[node.regretTrigger] || "Geçmişteki bir kararın gölgesi seni rahatsız ediyor."; storyText.setText(regretText + "\n\n(" + node.text + ")"); // Fade efekt: metni kısa süreliğine yarı saydam göster storyText.alpha = 0.5; tween(storyText, { alpha: 1 }, { duration: 1200, easing: tween.easeOut }); } else if ( // Yalancı Hafıza: Eğer honest bar düşükse ve geçmişte yalan söylendiyse, yanlış hatırlama metni göster bar_honest <= 30 && pastChoices.indexOf("lied") !== -1 && (node.id === "lisa_breakfast_mid" || node.id === "lisa_breakfast_high" || node.id === "lisa_breakfast_low")) { // Yalancı hafıza: Oyuncuya yanlış bilgi ver storyText.setText("Mike sanki o gün Lisa'ya doğruyu söylediğini hatırlıyordu... ama aslında yalan söylemişti.\n\n(" + node.text + ")"); storyText.alpha = 0.7; tween(storyText, { alpha: 1 }, { duration: 1200, easing: tween.easeOut }); } else if (node.id === "lisa_breakfast_mid" && pastChoices.indexOf("lied") !== -1) { storyText.setText("Lisa sana biraz mesafeli bakıyor. Geçmişteki yalanların etkisi sürüyor."); } else { storyText.setText(node.text); } } // Option buttons // --- Timed Choice Mechanism: If node.timedChoice is set, start a timer and auto-select if no choice is made --- var timedChoiceTimeout = null; var timedChoiceBar = null; if (node.options && node.options.length > 0) { // If previous timer exists, clear it if (game._timedChoiceTimeout) { LK.clearTimeout(game._timedChoiceTimeout); game._timedChoiceTimeout = null; } if (game._timedChoiceBar) { game.removeChild(game._timedChoiceBar); game._timedChoiceBar = null; } // If this node is a crisis/timed scene, e.g. node.timedChoice: { seconds: 5, default: 1 } var isTimed = node.timedChoice && typeof node.timedChoice.seconds === "number"; var timedSeconds = isTimed ? node.timedChoice.seconds : 0; var timedDefault = isTimed ? typeof node.timedChoice["default"] === "number" ? node.timedChoice["default"] : 0 : 0; var timedStart = Date.now(); var timedBarWidth = 900; var timedBarHeight = 24; var timedBarY = 1700 + node.options.length * 180 + 40; // Option button creation for (var i = 0; i < node.options.length; i++) { var opt = node.options[i]; // --- Requirements check --- var meetsReq = true; if (opt.requirements) { for (var key in opt.requirements) { var val = opt.requirements[key]; // Check current bar/relationship value var current = 0; if (key === 'lisa') current = rel_lisa;else if (key === 'rebecca') current = rel_rebecca;else if (key === 'peter') current = rel_peter;else if (key === 'alex') current = rel_alex;else if (key === 'happy') current = bar_happy;else if (key === 'honest') current = bar_honest;else if (key === 'lust') current = bar_lust;else if (key === 'betray') current = bar_betray; if (current < val) { meetsReq = false; break; } } } var btn = new OptionButton(); // --- Bilinmeyen Seçim Sistemi: option'a hiddenByBar eklendiyse ve bar yeterli değilse gizle --- var showAsHidden = false; if (opt.hiddenByBar) { // hiddenByBar: { key: 'honest', min: 60 } veya { key: 'betray', min: 40 } var barKey = opt.hiddenByBar.key; var minVal = typeof opt.hiddenByBar.min === "number" ? opt.hiddenByBar.min : 0; var currentVal = 0; if (barKey === 'lisa') currentVal = rel_lisa;else if (barKey === 'rebecca') currentVal = rel_rebecca;else if (barKey === 'peter') currentVal = rel_peter;else if (barKey === 'alex') currentVal = rel_alex;else if (barKey === 'happy') currentVal = bar_happy;else if (barKey === 'honest') currentVal = bar_honest;else if (barKey === 'lust') currentVal = bar_lust;else if (barKey === 'betray') currentVal = bar_betray; if (currentVal < minVal) showAsHidden = true; } if (showAsHidden) { btn.setText("???"); btn.bg.tint = 0x888888; btn.text.style.fill = '#bbbbbb'; btn.setCallback(function () {}); // No-op } else { btn.setText(opt.text); // If requirements not met, disable and gray out if (!meetsReq) { btn.bg.tint = 0x888888; btn.text.style.fill = '#bbbbbb'; btn.setCallback(function () {}); // No-op } else { btn.setCallback(function (opt, btnIdx) { return function () { // If a timed choice is running, clear the timer and bar if (game._timedChoiceTimeout) { LK.clearTimeout(game._timedChoiceTimeout); game._timedChoiceTimeout = null; } if (game._timedChoiceBar) { game.removeChild(game._timedChoiceBar); game._timedChoiceBar = null; } applyEffects(opt.effects, opt.meta); // Her zaman random bir sonraki soru seç, ama bar değerine göre uygun versiyonu seç var available = []; for (var j = 0; j < story.length; j++) { if (story[j].options && story[j].options.length > 0) available.push(j); } if (available.length > 0) { // getNextNode fonksiyonu ile uygun node'u seç var nextIdx = getNextNode(); currentNode = nextIdx; showStoryNode(currentNode); } else { // Oyun bitti, son ekranı göster showEnding(); } }; }(opt, i)); } } btn.x = 2048 / 2; btn.y = 1700 + i * 180; game.addChild(btn); optionButtons.push(btn); } // If this is a timed choice, show a timer bar and auto-select after timeout if (isTimed) { // Create a timer bar (background and fill) var barBg = LK.getAsset('bar_bg', { anchorX: 0.5, anchorY: 0.5 }); barBg.width = timedBarWidth; barBg.height = timedBarHeight; barBg.x = 2048 / 2; barBg.y = timedBarY; var barFill = LK.getAsset('bar_fill_betray', { anchorX: 0.5, anchorY: 0.5 }); barFill.width = timedBarWidth; barFill.height = timedBarHeight; barFill.x = 2048 / 2; barFill.y = timedBarY; // Add to game game.addChild(barBg); game.addChild(barFill); // Store for cleanup game._timedChoiceBar = barBg; game._timedChoiceBarFill = barFill; // Animate the bar fill var updateTimerBar = function updateTimerBar() { var elapsed = (Date.now() - timedStart) / 1000; var remain = Math.max(0, timedSeconds - elapsed); var ratio = remain / timedSeconds; barFill.width = timedBarWidth * ratio; if (ratio <= 0) { barFill.width = 0; } }; // Per-frame update for timer bar var timerBarInterval = LK.setInterval(function () { if (!game._timedChoiceBarFill) { LK.clearInterval(timerBarInterval); return; } updateTimerBar(); }, 50); // Timeout: auto-select default option game._timedChoiceTimeout = LK.setTimeout(function () { // Only trigger if still on this node if (game._timedChoiceBar) { // Simulate click on default option if (optionButtons[timedDefault] && typeof optionButtons[timedDefault].down === "function") { optionButtons[timedDefault].down(); } // Clean up timer bar if (game._timedChoiceBar) { game.removeChild(game._timedChoiceBar); game._timedChoiceBar = null; } if (game._timedChoiceBarFill) { game.removeChild(game._timedChoiceBarFill); game._timedChoiceBarFill = null; } LK.clearInterval(timerBarInterval); game._timedChoiceTimeout = null; } }, timedSeconds * 1000); } } } function applyEffects(effects, meta) { if (!effects) return; // --- Memory mechanic: record important choices --- // Example: If the player kisses Lisa, lies to Rebecca, etc. // We'll record meta.memoryLabel if present, otherwise try to infer from meta/type if (meta && meta.memoryLabel) { pastChoices.push(meta.memoryLabel); } else if (meta && meta.type === "lie") { pastChoices.push("lied"); // Regretful: lying is a regret } else if (meta && meta.type === "truth") { pastChoices.push("told_truth"); } // Regretful: betray Lisa if (typeof effects.lisa === 'number' && effects.lisa < 0 && typeof effects.betray === 'number' && effects.betray > 0) { pastChoices.push("betrayed_lisa"); } // Regretful: ignore Peter if (typeof effects.peter === 'number' && effects.peter < 0 && meta && meta.ignoreRegret) { pastChoices.push("ignored_peter"); } // Sadece yüzde 1 artıp azalsın if (typeof effects.lisa === 'number') rel_lisa = Math.max(0, Math.min(100, rel_lisa + (effects.lisa > 0 ? 1 : effects.lisa < 0 ? -1 : 0))); if (typeof effects.rebecca === 'number') rel_rebecca = Math.max(0, Math.min(100, rel_rebecca + (effects.rebecca > 0 ? 1 : effects.rebecca < 0 ? -1 : 0))); if (typeof effects.peter === 'number') rel_peter = Math.max(0, Math.min(100, rel_peter + (effects.peter > 0 ? 1 : effects.peter < 0 ? -1 : 0))); if (typeof effects.alex === 'number') rel_alex = Math.max(0, Math.min(100, rel_alex + (effects.alex > 0 ? 1 : effects.alex < 0 ? -1 : 0))); if (typeof effects.happy === 'number') { bar_happy = Math.max(0, Math.min(100, bar_happy + (effects.happy > 0 ? 1 : effects.happy < 0 ? -1 : 0))); if (typeof villaUnlocked !== "undefined" && villaUnlocked && bar_happy < 80) { bar_happy = 80; } } if (typeof effects.honest === 'number') bar_honest = Math.max(0, Math.min(100, bar_honest + (effects.honest > 0 ? 1 : effects.honest < 0 ? -1 : 0))); if (typeof effects.lust === 'number') bar_lust = Math.max(0, Math.min(100, bar_lust + (effects.lust > 0 ? 1 : effects.lust < 0 ? -1 : 0))); if (typeof effects.betray === 'number') bar_betray = Math.max(0, Math.min(100, bar_betray + (effects.betray > 0 ? 1 : effects.betray < 0 ? -1 : 0))); // --- Villa davet event: karakterle ilişkiyi %15 artır (etki zaten effects ile geliyor, ama burada ek bir kontrol de eklenebilir) --- if (meta && meta.type === "villa_invite" && typeof meta.character === "string") { if (meta.character === "lisa") rel_lisa = Math.min(100, rel_lisa + 15); if (meta.character === "rebecca") rel_rebecca = Math.min(100, rel_rebecca + 15); if (meta.character === "peter") rel_peter = Math.min(100, rel_peter + 15); if (meta.character === "alex") rel_alex = Math.min(100, rel_alex + 15); } // --- Giselle para harcama ve hamilelik --- if (meta && meta.type === "giselle_spend" && typeof meta.money === "number") { mikeMoney = Math.max(0, mikeMoney + meta.money); } // --- Whiskey para harcama --- if (meta && meta.type === "whiskey_spend" && typeof meta.money === "number") { mikeMoney = Math.max(0, mikeMoney + meta.money); } if (meta && meta.type === "giselle_baby" && giselleUnlocked && !gisellePregnant) { if (Math.random() < 0.3) { gisellePregnant = true; // Bebek doğumu bir sonraki günlerde gerçekleşecek } } // --- Shadow bar logic: increase/decrease based on hidden triggers --- // Betrayal, repeated lies, or negative choices increase shadow bar if (meta && meta.type === "lie" || typeof effects.betray === 'number' && effects.betray > 0) { bar_shadow = Math.max(0, Math.min(100, bar_shadow + 5)); } // If player is honest or makes a positive choice, shadow bar may decrease if (meta && meta.type === "truth" || typeof effects.honest === 'number' && effects.honest > 0) { bar_shadow = Math.max(0, bar_shadow - 2); } // If player ignores Peter or Lisa (meta.ignoreRegret), shadow bar increases if (meta && meta.ignoreRegret) { bar_shadow = Math.max(0, Math.min(100, bar_shadow + 3)); } // --- Honest bar penalty for repeated lies --- if (meta && meta.type === "lie") { // Lying reduces honest bar by 2 (or 1 if already low) bar_honest = Math.max(0, bar_honest - (bar_honest > 10 ? 2 : 1)); } // --- Relationship Cross Effects --- applyCrossEffects(effects, meta); updateBars(); // --- Turn-based trigger system --- // Increase turn count on every choice turnCount++; // --- Ava: Advance time every 2 turns (1 day = 2 questions) --- if (turnCount % 2 === 0) { dayCount++; // Mike maaş alır mikeMoney += mikeSalary; // Alex ile ilişki > 70 ise maaş +50 if (rel_alex > 70) { mikeSalary += 50; } // Alex ile ilişki < 30 ise maaş -20 if (rel_alex < 30) { mikeSalary = Math.max(0, mikeSalary - 20); } // Peter ile ilişki > 70 ise mutluluk +1 if (rel_peter > 70) { bar_happy = Math.min(100, bar_happy + 1); } // Lisa hamile ise doğum (her gün %10 ihtimal) if (lisaPregnant && Math.random() < 0.1) { mikeBabyCount++; lisaPregnant = false; } // Rebecca hamile ise doğum (her gün %10 ihtimal) if (rebeccaPregnant && Math.random() < 0.1) { mikeBabyCount++; rebeccaPregnant = false; } // Giselle hamile ise doğum (her gün %10 ihtimal) if (gisellePregnant && Math.random() < 0.1) { mikeBabyCount++; gisellePregnant = false; } // Save to storage storage.mikeMoney = mikeMoney; storage.mikeSalary = mikeSalary; storage.mikeBabyCount = mikeBabyCount; storage.dayCount = dayCount; storage.lisaPregnant = lisaPregnant; storage.rebeccaPregnant = rebeccaPregnant; // Update UI updateBars(); } // --- Dış Etki Mekanizması: Lust bar 3 tur boyunca yüksekse otomatik karar --- // Son 3 turdaki lust bar değerlerini takip et if (!flags.lustHistory) flags.lustHistory = []; flags.lustHistory.push(bar_lust); if (flags.lustHistory.length > 3) flags.lustHistory.shift(); // Eğer son 3 turda lust barı 70 ve üzeriyse, otomatik bir karar tetiklenir (ör: irade kaybı) if (flags.lustHistory.length === 3 && flags.lustHistory[0] >= 70 && flags.lustHistory[1] >= 70 && flags.lustHistory[2] >= 70 && !flags.lustAutoDecision) { flags.lustAutoDecision = true; // Oyuncunun kontrolü dışında bir olay: Rebecca ile yakınlaşma if (storyText) { storyText.setText("Mike, arzularına yenik düşüyor ve Rebecca'ya karşı koyamıyor. (Dış etki: İrade kaybı)"); storyText.alpha = 0.7; tween(storyText, { alpha: 1 }, { duration: 1200, easing: tween.easeOut }); } // Bar ve ilişkilerde otomatik değişiklikler rel_rebecca = Math.min(100, rel_rebecca + 5); bar_lust = Math.min(100, bar_lust + 5); bar_betray = Math.min(100, bar_betray + 5); updateBars(); // Sonraki node'a otomatik geçiş (Rebecca ile ilgili bir sahneye öncelik ver) var rebeccaIdx = -1; for (var i = 0; i < story.length; i++) { if (story[i].portrait === "rebecca" && story[i].options && story[i].options.length > 0) { rebeccaIdx = i; break; } } if (rebeccaIdx !== -1) { currentNode = rebeccaIdx; LK.setTimeout(function () { showStoryNode(currentNode); }, 1800); return; } } // Zamana bağlı özel rüya sahnesi tetikleyici örneği if (turnCount > 15 && bar_lust > 60 && !flags["specialDreamTriggered"]) { flags["specialDreamTriggered"] = true; showEnding("Mike, arzularının peşinden sürüklendiği özel bir rüya görüyor. (Zamana bağlı özel sahne)"); return; } // --- Bar-based flag system --- // Example: if betrayal bar reaches 80 or more, set betrayalUnlocked flag if (bar_betray >= 80) { flags["betrayalUnlocked"] = true; } if (bar_honest >= 90) { flags["honestyMaster"] = true; } if (bar_lust >= 90) { flags["lustHigh"] = true; } if (bar_happy >= 90) { flags["happinessPeak"] = true; } if (rel_lisa >= 90) { flags["lisaBond"] = true; } if (rel_rebecca >= 90) { flags["rebeccaBond"] = true; } if (rel_peter >= 90) { flags["peterBond"] = true; } if (rel_alex >= 90) { flags["alexBond"] = true; } // --- Shadow bar event triggers (hidden, unexpected events) --- if (!flags.shadow30 && bar_shadow >= 30) { flags.shadow30 = true; // Ani içsel monolog: Mike'ın öfke patlaması if (storyText) { storyText.setText("Mike'ın içinde bir öfke kabarıyor. (İç ses: 'Bazen her şeyi yakıp yıkmak istiyorum...')\n\n" + (storyText.text || "")); storyText.alpha = 0.7; tween(storyText, { alpha: 1 }, { duration: 1000, easing: tween.easeOut }); } } if (!flags.shadow60 && bar_shadow >= 60) { flags.shadow60 = true; // Mike'ın beklenmedik bir şekilde bağırması (oyuncuya yansır) if (storyText) { storyText.setText("Mike aniden bağırıyor: 'YETER ARTIK!'\n\n" + (storyText.text || "")); storyText.alpha = 0.7; tween(storyText, { alpha: 1 }, { duration: 1000, easing: tween.easeOut }); } // Portrait kırmızıya döner, kısa süreliğine if (portraitNode) { var oldTint = portraitNode.tint; portraitNode.tint = 0xd0021b; tween(portraitNode, { tint: oldTint }, { duration: 1200, easing: tween.easeOut }); } } if (!flags.shadow90 && bar_shadow >= 90) { flags.shadow90 = true; // Mike'ın içsel çöküşü: iç ses, portre fade out if (storyText) { storyText.setText("Mike'ın zihni karanlığa gömülüyor. (İç ses: 'Artık kendimi tanıyamıyorum...')\n\n" + (storyText.text || "")); storyText.alpha = 0.5; tween(storyText, { alpha: 1 }, { duration: 1500, easing: tween.easeOut }); } if (portraitNode) { tween(portraitNode, { alpha: 0.2 }, { duration: 1500, easing: tween.easeOut }); } } // Check for fail/win conditions if (bar_happy <= 0) { showEnding('Mutluluk sıfırlandı. Mike depresyona girdi.'); return; } if (bar_honest <= 0) { showEnding('Dürüstlük sıfırlandı. Mike yalanlarla dolu bir hayata saplandı.'); return; } if (bar_lust <= 0) { showEnding('Şehvet sıfırlandı. Mike hayattan keyif alamıyor.'); return; } if (bar_betray >= 100) { showEnding('İhanet %100 oldu. Mike ilişkilerini kaybetti.'); return; } } // İlişki çaprazlama mekanizması: Lisa ile yakınlık artınca Rebecca kıskanır, Rebecca ile yakınlık artınca Lisa üzülür, vs. function applyCrossEffects(effects, meta) { // Lisa ile yakınlık artarsa Rebecca'nın ilişkisi biraz azalır (kıskançlık) if (typeof effects.lisa === 'number' && effects.lisa > 0) { // Lisa ile +1 yakınlık, Rebecca -1 rel_rebecca = Math.max(0, rel_rebecca - 1); } // Rebecca ile yakınlık artarsa Lisa'nın ilişkisi biraz azalır (kıskançlık) if (typeof effects.rebecca === 'number' && effects.rebecca > 0) { rel_lisa = Math.max(0, rel_lisa - 1); } // Lisa ile yakınlık azalırsa Rebecca biraz mutlu olur (rekabet) if (typeof effects.lisa === 'number' && effects.lisa < 0) { rel_rebecca = Math.min(100, rel_rebecca + 1); } // Rebecca ile yakınlık azalırsa Lisa biraz mutlu olur (rekabet) if (typeof effects.rebecca === 'number' && effects.rebecca < 0) { rel_lisa = Math.min(100, rel_lisa + 1); } // Betray (ihanet) barı artarsa Lisa ve Rebecca'nın ilişkisi biraz azalır if (typeof effects.betray === 'number' && effects.betray > 0) { rel_lisa = Math.max(0, rel_lisa - 1); rel_rebecca = Math.max(0, rel_rebecca - 1); } // Lust barı çok artarsa (ör: Rebecca ile), Lisa'nın ilişkisi biraz azalır if (typeof effects.lust === 'number' && effects.lust > 0) { rel_lisa = Math.max(0, rel_lisa - 1); } // Happy barı çok azalırsa, tüm ilişkiler biraz azalır if (typeof effects.happy === 'number' && effects.happy < 0) { rel_lisa = Math.max(0, rel_lisa - 1); rel_rebecca = Math.max(0, rel_rebecca - 1); rel_peter = Math.max(0, rel_peter - 1); rel_alex = Math.max(0, rel_alex - 1); } } function showEnding(msg) { // Remove option buttons for (var i = 0; i < optionButtons.length; i++) { game.removeChild(optionButtons[i]); } optionButtons = []; // --- Animated, bar-specific game over --- // Determine which bar triggered game over var endingType = null; if (typeof msg === "string") { if (msg.indexOf("Mutluluk") !== -1) endingType = "happy";else if (msg.indexOf("Dürüstlük") !== -1) endingType = "honest";else if (msg.indexOf("Şehvet") !== -1) endingType = "lust";else if (msg.indexOf("İhanet") !== -1) endingType = "betray"; } // Default: Mike portrait var portraitKey = "mike"; var endingText = msg; var mood = "sad"; var crossX = null; // Custom portrait and text for each bar if (endingType === "betray") { // Mike gözaltına alınıyor portraitKey = "mike"; endingText = "SON: Mike ihanetin bedelini ödedi ve gözaltına alındı.\n\nYeniden başlamak için ekrana dokunun."; mood = "angry"; crossX = true; } else if (endingType === "lust") { // Lisa uzaklaşıyor portraitKey = "lisa"; endingText = "SON: Lisa, Mike'ın tutkularının sönmesiyle uzaklaştı.\n\nYeniden başlamak için ekrana dokunun."; mood = "sad"; crossX = true; } else if (endingType === "happy") { // Mike depresyona giriyor portraitKey = "mike"; endingText = "SON: Mike mutluluğunu kaybetti ve depresyona girdi.\n\nYeniden başlamak için ekrana dokunun."; mood = "sad"; crossX = false; } else if (endingType === "honest") { // Mike yalanlarla dolu bir hayata saplandı portraitKey = "mike"; endingText = "SON: Mike dürüstlüğünü kaybetti, yalanlarla dolu bir hayata saplandı.\n\nYeniden başlamak için ekrana dokunun."; mood = "angry"; crossX = true; } // Show ending text if (storyText) { if (endingText) { storyText.setText(endingText); } else if (msg) { storyText.setText('SON: ' + msg + '\n\nYeniden başlamak için ekrana dokunun.'); } else { storyText.setText('SON: Mike’ın hikayesi burada bitiyor.\n\nYeniden başlamak için ekrana dokunun.'); } } // Remove speaker if (speakerText) speakerText.setText(''); // Animate portrait: change to relevant character, mood tint, fade out, and cross if needed if (portraitNode) { // Change portrait image if (LK.getAsset(portraitKey, {})) { portraitNode.texture = LK.getAsset(portraitKey, {}).texture; } // Mood-based tint var moodTints = { happy: 0x7ed321, sad: 0x4a90e2, angry: 0xd0021b, neutral: 0xffffff }; var tint = moodTints[mood] !== undefined ? moodTints[mood] : 0xffffff; portraitNode.tint = tint; // Animate: fade out after 1.2s tween(portraitNode, { alpha: 0.3 }, { duration: 1200, easing: tween.easeOut }); // If crossX, show a red cross over portrait if (crossX) { // Create a red cross using two rectangles (since we can't draw lines) var cross1 = LK.getAsset('bar_fill_betray', { anchorX: 0.5, anchorY: 0.5 }); var cross2 = LK.getAsset('bar_fill_betray', { anchorX: 0.5, anchorY: 0.5 }); // Set size and rotation for cross var size = Math.max(portraitNode.width, portraitNode.height) * 0.9; cross1.width = size; cross1.height = 24; cross2.width = size; cross2.height = 24; cross1.rotation = Math.PI / 4; cross2.rotation = -Math.PI / 4; cross1.alpha = 0.85; cross2.alpha = 0.85; cross1.x = portraitNode.x; cross1.y = portraitNode.y; cross2.x = portraitNode.x; cross2.y = portraitNode.y; cross1.zIndex = 100; cross2.zIndex = 100; game.addChild(cross1); game.addChild(cross2); // Animate cross: fade in, then fade out after 1.2s cross1.alpha = 0; cross2.alpha = 0; tween(cross1, { alpha: 0.85 }, { duration: 400, easing: tween.easeOut }); tween(cross2, { alpha: 0.85 }, { duration: 400, easing: tween.easeOut }); // Fade out after 1.2s LK.setTimeout(function () { tween(cross1, { alpha: 0 }, { duration: 600, easing: tween.easeOut }); tween(cross2, { alpha: 0 }, { duration: 600, easing: tween.easeOut }); LK.setTimeout(function () { game.removeChild(cross1); game.removeChild(cross2); }, 700); }, 1200); } } // Add restart handler game.down = function (x, y, obj) { game.down = null; restartGame(); }; } function restartGame() { resetGameState(); updateBars(); showStoryNode(currentNode); // Remove restart handler game.down = null; } // --- Start Game --- resetGameState(); createUI(); updateBars(); showStoryNode(currentNode); // --- No dragging or move events needed for this game --- // --- Game update (not used, but required for LK) --- game.update = function () { // No per-frame logic needed };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// OptionButton: For displaying a choice
var OptionButton = Container.expand(function () {
var self = Container.call(this);
self.bg = self.attachAsset('option_btn', {
anchorX: 0.5,
anchorY: 0.5
});
self.text = null;
self.callback = null;
self.setText = function (str) {
if (self.text) self.removeChild(self.text);
self.text = new Text2(str, {
size: 54,
fill: '#222222'
});
self.text.anchor.set(0.5, 0.5);
self.text.x = 0;
self.text.y = 0;
self.addChild(self.text);
};
self.setCallback = function (cb) {
self.callback = cb;
};
self.down = function (x, y, obj) {
if (self.callback) self.callback();
};
return self;
});
// Passive background object base class
var PassiveBgObject = Container.expand(function () {
var self = Container.call(this);
self.speed = 0;
self.assetId = '';
self.asset = null;
self.setAsset = function (assetId) {
if (self.asset) self.removeChild(self.asset);
self.assetId = assetId;
self.asset = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
};
self.resetPosition = function () {
// Start just outside right edge, random Y
self.x = 2048 + (self.asset ? self.asset.width : 100) / 2 + Math.random() * 200;
self.y = 200 + Math.random() * 2100;
};
self.update = function () {
if (typeof self.lastX === "undefined") self.lastX = self.x;
self.x -= self.speed;
// If off screen to the left, reset
if (self.lastX >= -200 && self.x < -200) {
self.resetPosition();
}
self.lastX = self.x;
};
return self;
});
// Motorcycle
var BgMotorcycle = PassiveBgObject.expand(function () {
var self = PassiveBgObject.call(this);
self.setAsset('bg_motorcycle');
self.speed = 4.0 + Math.random() * 1.5;
self.resetPosition();
return self;
});
// Heart
var BgHeart = PassiveBgObject.expand(function () {
var self = PassiveBgObject.call(this);
self.setAsset('bg_heart');
self.speed = 2.7 + Math.random() * 1.2;
self.resetPosition();
return self;
});
// Football
var BgFootball = PassiveBgObject.expand(function () {
var self = PassiveBgObject.call(this);
self.setAsset('bg_football');
self.speed = 2.5 + Math.random() * 1.2;
self.resetPosition();
return self;
});
// Car
var BgCar = PassiveBgObject.expand(function () {
var self = PassiveBgObject.call(this);
self.setAsset('bg_car');
self.speed = 3.2 + Math.random() * 1.5;
self.resetPosition();
return self;
});
// Briefcase
var BgBriefcase = PassiveBgObject.expand(function () {
var self = PassiveBgObject.call(this);
self.setAsset('bg_briefcase');
self.speed = 2.2 + Math.random() * 1.2;
self.resetPosition();
return self;
});
// RelationshipBar: For displaying and updating a bar (happiness, honesty, lust, betrayal)
var RelationshipBar = Container.expand(function () {
var self = Container.call(this);
self.bg = self.attachAsset('bar_bg', {
anchorX: 0,
anchorY: 0
});
self.fill = null;
self.label = null;
self.value = 100; // 0-100
self.maxWidth = 400;
self.type = 'happy'; // 'happy', 'honest', 'lust', 'betray'
self.setType = function (type) {
self.type = type;
var fillId = 'bar_fill_happy';
if (type === 'honest') fillId = 'bar_fill_honest';
if (type === 'lust') fillId = 'bar_fill_lust';
if (type === 'betray') fillId = 'bar_fill_betray';
if (self.fill) self.removeChild(self.fill);
self.fill = self.attachAsset(fillId, {
anchorX: 0,
anchorY: 0
});
self.fill.x = 0;
self.fill.y = 0;
self.fill.width = self.maxWidth;
self.fill.height = 40;
self.fill.zIndex = 1;
self.bg.zIndex = 0;
self.setValue(self.value);
};
self.setValue = function (val) {
self.value = Math.max(0, Math.min(100, val));
if (self.fill) {
self.fill.width = self.maxWidth * (self.value / 100);
}
if (self.label) {
self.label.setText(self.value + '%');
}
};
self.setLabel = function (text) {
if (self.label) self.removeChild(self.label);
self.label = new Text2(text, {
size: 36,
fill: '#ffffff'
});
self.label.anchor.set(1, 0.5);
self.label.x = self.maxWidth + 20;
self.label.y = 20;
self.addChild(self.label);
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Animate passive background objects
// Sağdan sola giden araba
// Sağdan sola giden iş çantası
// Sağdan sola giden ateşli kalp
// Sağdan sola giden futbol topu
// Sağdan sola giden motor
// --- Shop/Store assets (right side) ---
// Example id, replace with real
if (typeof bgObjects !== "undefined") {
for (var i = 0; i < bgObjects.length; i++) {
if (bgObjects[i] && typeof bgObjects[i].update === "function") {
bgObjects[i].update();
}
}
}
// No per-frame logic needed
// Not: 'background' asseti image olarak tanımlanmalı, ör: LK.init.image('background', {width:2048, height:2732, id:'YOUR_IMAGE_ID'})
var backgroundNode = LK.getAsset('background', {
anchorX: 0,
anchorY: 0
});
backgroundNode.width = 2048;
backgroundNode.height = 2732;
backgroundNode.x = 0;
backgroundNode.y = 0;
backgroundNode.zIndex = -100; // Her şeyin arkasında dursun
game.addChild(backgroundNode);
// --- Passive background objects (car, briefcase, heart, football, motorcycle) ---
var bgObjects = [];
function spawnBgObjects() {
// Remove old ones if any
for (var i = 0; i < bgObjects.length; i++) {
if (bgObjects[i] && bgObjects[i].parent) {
game.removeChild(bgObjects[i]);
}
}
bgObjects = [];
// Add 2 of each for variety
for (var i = 0; i < 2; i++) {
var car = new BgCar();
var briefcase = new BgBriefcase();
var heart = new BgHeart();
var football = new BgFootball();
var motorcycle = new BgMotorcycle();
game.addChild(car);
game.addChild(briefcase);
game.addChild(heart);
game.addChild(football);
game.addChild(motorcycle);
bgObjects.push(car, briefcase, heart, football, motorcycle);
}
}
spawnBgObjects();
// Çarpıcı seçimler: her 4-6 sahnede bir, yüksek risk/ödül, animasyonlu, barları büyük oranda etkiler
// --- Dramatic Choice (Çarpıcı Seçim) System ---
var dramaticChoices = [{
id: "rebecca_room",
text: "Rebecca ile iş gezisindesiniz. Aynı odada mı kalacaksınız, farklı mı?",
portrait: "rebecca",
speaker: "Rebecca",
dramatic: true,
options: [{
text: "Aynı odada kal",
effects: {
rebecca: 15,
lust: 15,
betray: 15
},
meta: {
memoryLabel: "rebecca_room_same"
}
}, {
text: "Farklı odada kal",
effects: {
honest: 10,
rebecca: -5
},
meta: {
memoryLabel: "rebecca_room_diff"
}
}]
}, {
id: "lisa_warns_alex",
text: "Lisa seni, iş yerinde Alex ile fazla yakın görünmen konusunda uyarıyor. Tepkin ne olur?",
portrait: "lisa",
speaker: "Lisa",
dramatic: true,
options: [{
text: "Anlar ve saygı gösterirsin",
effects: {
lisa: 20,
honest: 15
},
meta: {
memoryLabel: "lisa_warns_respect"
}
}, {
text: "Umursamaz davranırsın",
effects: {
lisa: -20,
betray: 15
},
meta: {
memoryLabel: "lisa_warns_ignore"
}
}]
}, {
id: "alex_secret",
text: "Alex senden gizli bir bilgi istiyor. Paylaşacak mısın?",
portrait: "alex",
speaker: "Alex",
dramatic: true,
options: [{
text: "Paylaş",
effects: {
betray: 20,
alex: 10
},
meta: {
memoryLabel: "alex_secret_share"
}
}, {
text: "Sakla",
effects: {
honest: 20,
alex: -10
},
meta: {
memoryLabel: "alex_secret_hide"
}
}]
}, {
id: "peter_lisa_fears",
text: "Peter sana, Lisa ile ilgili endişelerini paylaşıyor. Ona inanacak mısın?",
portrait: "peter",
speaker: "Peter",
dramatic: true,
options: [{
text: "Evet",
effects: {
peter: 15,
honest: 10
},
meta: {
memoryLabel: "peter_lisa_believe"
}
}, {
text: "Hayır",
effects: {
peter: -15,
betray: 10
},
meta: {
memoryLabel: "peter_lisa_deny"
}
}]
}, {
id: "rebecca_night",
text: "Rebecca gece seni evine davet ediyor. Gidiyor musun?",
portrait: "rebecca",
speaker: "Rebecca",
dramatic: true,
options: [{
text: "Evet",
effects: {
rebecca: 20,
lust: 15,
betray: 20
},
meta: {
memoryLabel: "rebecca_night_yes"
}
}, {
text: "Hayır",
effects: {
honest: 15
},
meta: {
memoryLabel: "rebecca_night_no"
}
}]
}, {
id: "lisa_serious_talk",
text: "Lisa, seninle ciddi bir konuşma yapmak istiyor. Onu dinleyecek misin?",
portrait: "lisa",
speaker: "Lisa",
dramatic: true,
options: [{
text: "Dinle",
effects: {
lisa: 20,
honest: 10
},
meta: {
memoryLabel: "lisa_serious_listen"
}
}, {
text: "Dinleme",
effects: {
lisa: -20,
happy: -15
},
meta: {
memoryLabel: "lisa_serious_ignore"
}
}]
}, {
id: "alex_secret_deal",
text: "Alex ile gizli bir anlaşma teklif ediyor. Kabul edecek misin?",
portrait: "alex",
speaker: "Alex",
dramatic: true,
options: [{
text: "Evet",
effects: {
alex: 20,
betray: 20
},
meta: {
memoryLabel: "alex_deal_yes"
}
}, {
text: "Hayır",
effects: {
honest: 20,
alex: -15
},
meta: {
memoryLabel: "alex_deal_no"
}
}]
}, {
id: "peter_big_secret",
text: "Peter, seni büyük bir sırrı hakkında uyarıyor. Güveniyor musun?",
portrait: "peter",
speaker: "Peter",
dramatic: true,
options: [{
text: "Evet",
effects: {
peter: 20,
honest: 10
},
meta: {
memoryLabel: "peter_secret_trust"
}
}, {
text: "Hayır",
effects: {
peter: -20,
betray: 15
},
meta: {
memoryLabel: "peter_secret_distrust"
}
}]
}, {
id: "rebecca_club",
text: "Rebecca ile bir gece kulübünde dans ediyorsun. Daha yakın davranacak mısın?",
portrait: "rebecca",
speaker: "Rebecca",
dramatic: true,
options: [{
text: "Evet",
effects: {
rebecca: 15,
lust: 15,
betray: 10
},
meta: {
memoryLabel: "rebecca_club_yes"
}
}, {
text: "Hayır",
effects: {
honest: 10
},
meta: {
memoryLabel: "rebecca_club_no"
}
}]
}, {
id: "lisa_gossip",
text: "Lisa seni iş arkadaşlarınla ilgili dedikodulara karışmakla suçluyor. Savunacak mısın?",
portrait: "lisa",
speaker: "Lisa",
dramatic: true,
options: [{
text: "Savun",
effects: {
lisa: 10,
honest: 15
},
meta: {
memoryLabel: "lisa_gossip_defend"
}
}, {
text: "Kabullen",
effects: {
lisa: -15,
betray: 10
},
meta: {
memoryLabel: "lisa_gossip_admit"
}
}]
}, {
id: "alex_promotion",
text: "Alex, seni iş yerinde terfi ile ödüllendiriyor ama bir karşılık bekliyor. Kabul edecek misin?",
portrait: "alex",
speaker: "Alex",
dramatic: true,
options: [{
text: "Evet",
effects: {
alex: 25,
betray: 25
},
meta: {
memoryLabel: "alex_promotion_yes"
}
}, {
text: "Hayır",
effects: {
honest: 20
},
meta: {
memoryLabel: "alex_promotion_no"
}
}]
}, {
id: "peter_sacrifice",
text: "Peter’in sana yardım etmek için büyük bir fedakarlık yapması gerekiyor. Kabul edecek misin?",
portrait: "peter",
speaker: "Peter",
dramatic: true,
options: [{
text: "Evet",
effects: {
peter: 25,
happy: 15
},
meta: {
memoryLabel: "peter_sacrifice_yes"
}
}, {
text: "Hayır",
effects: {
peter: -20,
betray: 10
},
meta: {
memoryLabel: "peter_sacrifice_no"
}
}]
}, {
id: "rebecca_restaurant",
text: "Rebecca, iş seyahatinde seni bir restoranda yalnız bırakıyor. Tek başına kalacak mısın yoksa kalabalığa mı karışacaksın?",
portrait: "rebecca",
speaker: "Rebecca",
dramatic: true,
options: [{
text: "Tek başına",
effects: {
rebecca: 10,
lust: 10
},
meta: {
memoryLabel: "rebecca_restaurant_alone"
}
}, {
text: "Kalabalık",
effects: {
honest: 10
},
meta: {
memoryLabel: "rebecca_restaurant_crowd"
}
}]
}, {
id: "lisa_memory",
text: "Lisa sana eski bir anısını anlatıyor ve senden destek bekliyor. Onun yanında olacak mısın?",
portrait: "lisa",
speaker: "Lisa",
dramatic: true,
options: [{
text: "Evet",
effects: {
lisa: 20,
happy: 15
},
meta: {
memoryLabel: "lisa_memory_yes"
}
}, {
text: "Hayır",
effects: {
lisa: -15
},
meta: {
memoryLabel: "lisa_memory_no"
}
}]
}, {
id: "alex_ethics",
text: "Alex’in zorlayıcı teklifine karşılık verirken etik dışı bir şey yapman isteniyor. Kabul mü?",
portrait: "alex",
speaker: "Alex",
dramatic: true,
options: [{
text: "Evet",
effects: {
alex: 20,
betray: 25
},
meta: {
memoryLabel: "alex_ethics_yes"
}
}, {
text: "Hayır",
effects: {
honest: 20
},
meta: {
memoryLabel: "alex_ethics_no"
}
}]
}, {
id: "peter_secret_share",
text: "Peter seni beklenmedik bir şekilde büyük bir sırrını açıklıyor. Tepkin ne olur?",
portrait: "peter",
speaker: "Peter",
dramatic: true,
options: [{
text: "Sırlarınızı paylaşmaya devam edersin",
effects: {
peter: 20,
honest: 15
},
meta: {
memoryLabel: "peter_secret_share_yes"
}
}, {
text: "Mesafeli olursun",
effects: {
peter: -15,
betray: 10
},
meta: {
memoryLabel: "peter_secret_share_no"
}
}]
}, {
id: "rebecca_bar_lisa",
text: "Rebecca ile iş sonrası bara gittiniz. Lisa ile yüzleşmeye hazır mısın?",
portrait: "rebecca",
speaker: "Rebecca",
dramatic: true,
options: [{
text: "Evet",
effects: {
betray: 20,
lust: 15,
rebecca: 10
},
meta: {
memoryLabel: "rebecca_bar_lisa_yes"
}
}, {
text: "Hayır",
effects: {
honest: 15,
lisa: 10
},
meta: {
memoryLabel: "rebecca_bar_lisa_no"
}
}]
}, {
id: "lisa_crisis",
text: "Lisa sana, evlilikte bir kriz yaşıyor ve profesyonel yardım almak istiyor. Destek verir misin?",
portrait: "lisa",
speaker: "Lisa",
dramatic: true,
options: [{
text: "Evet",
effects: {
lisa: 25,
happy: 20
},
meta: {
memoryLabel: "lisa_crisis_yes"
}
}, {
text: "Hayır",
effects: {
lisa: -25
},
meta: {
memoryLabel: "lisa_crisis_no"
}
}]
}, {
id: "alex_risk",
text: "Alex, kariyerin için büyük bir tehlike barındıran bir riski göze almana izin veriyor. Kabul mü?",
portrait: "alex",
speaker: "Alex",
dramatic: true,
options: [{
text: "Evet",
effects: {
alex: 30,
betray: 30
},
meta: {
memoryLabel: "alex_risk_yes"
}
}, {
text: "Hayır",
effects: {
honest: 20
},
meta: {
memoryLabel: "alex_risk_no"
}
}]
}, {
id: "peter_conflict",
text: "Peter ile aranızda aniden büyük bir anlaşmazlık çıkıyor. Özür dileyecek misin?",
portrait: "peter",
speaker: "Peter",
dramatic: true,
options: [{
text: "Evet",
effects: {
peter: 20,
happy: 15
},
meta: {
memoryLabel: "peter_conflict_yes"
}
}, {
text: "Hayır",
effects: {
peter: -20,
betray: 15
},
meta: {
memoryLabel: "peter_conflict_no"
}
}]
}];
// Dramatic choice frequency: every 4-6 turns, randomize
var nextDramaticTurn = 4 + Math.floor(Math.random() * 3);
var dramaticHistory = [];
// Helper: get a random dramatic choice not recently shown
function getDramaticChoice() {
var available = [];
for (var i = 0; i < dramaticChoices.length; i++) {
if (dramaticHistory.indexOf(dramaticChoices[i].id) === -1) {
available.push(dramaticChoices[i]);
}
}
// If all have been shown, reset history
if (available.length === 0) {
dramaticHistory = [];
available = dramaticChoices.slice();
}
var idx = Math.floor(Math.random() * available.length);
return available[idx];
}
// Show a dramatic choice with animation, music pause, and shadow overlay
function showDramaticChoice() {
// Remove old option buttons
for (var i = 0; i < optionButtons.length; i++) {
game.removeChild(optionButtons[i]);
}
optionButtons = [];
// Pick a dramatic choice
var node = getDramaticChoice();
dramaticHistory.push(node.id);
// Pause music (if any)
if (typeof LK.stopMusic === "function") LK.stopMusic();
// Shadow overlay
if (!game._dramaticShadow) {
var shadow = LK.getAsset('bar_bg', {
anchorX: 0,
anchorY: 0
});
shadow.width = 2048;
shadow.height = 2732;
shadow.x = 0;
shadow.y = 0;
shadow.alpha = 0.0; // Start fully transparent
shadow.zIndex = 99;
game.addChild(shadow);
game._dramaticShadow = shadow;
// Animate shadow fade-in
tween(shadow, {
alpha: 0.7
}, {
duration: 220,
easing: tween.easeOut
});
} else {
// If already present, ensure it's visible and interactive
game._dramaticShadow.alpha = 0.7;
game._dramaticShadow.zIndex = 99;
}
// Portrait
if (portraitNode && node.portrait && LK.getAsset(node.portrait, {})) {
portraitNode.texture = LK.getAsset(node.portrait, {}).texture;
portraitNode.tint = 0xffffff;
}
// Speaker
if (speakerText) speakerText.setText(node.speaker ? node.speaker : '');
// Story text
if (storyText) {
storyText.setText(node.text);
storyText.alpha = 1.0; // No animation
}
// Dramatic option buttons: ensure visible, enabled, and selectable
for (var i = 0; i < node.options.length; i++) {
(function (opt, idx) {
var btn = new OptionButton();
btn.setText(opt.text);
// Büyük ve dikkat çekici: butonları daha büyük yap
btn.scale.x = 1.35;
btn.scale.y = 1.35;
// Ekranda tamamen görünür ve aralıklı olacak şekilde ayarla
// Yüksekliğe göre ortala, iki seçenek için yukarıdan ve aşağıdan eşit boşluk bırak
var totalBtnHeight = 2 * (btn.bg.height * btn.scale.y) + 120;
var startY = 1800 - totalBtnHeight / 2;
btn.x = 2048 / 2;
btn.y = startY + idx * (btn.bg.height * btn.scale.y + 120);
btn.alpha = 1.0;
btn.bg.tint = 0x000000;
if (btn.text && btn.text.style) btn.text.style.fill = '#ffffff';
btn.zIndex = 100;
btn.interactive = true;
btn.buttonMode = true;
// Make sure button is enabled and not grayed out
btn.bg.tint = 0x000000;
if (btn.text && btn.text.style) btn.text.style.fill = '#ffffff';
// Remove any previous disabled state
btn.alpha = 1.0;
btn.visible = true;
btn.setCallback(function () {
// Seçim sırasında iki butonu da büyüt ve animasyon ekle
for (var j = 0; j < optionButtons.length; j++) {
var b = optionButtons[j];
// Seçilen buton daha fazla büyüsün, diğeri de büyüsün ama biraz az
var targetScale = b === btn ? 1.55 : 1.25;
tween(b.scale, {
x: targetScale,
y: targetScale
}, {
duration: 220,
easing: tween.easeOut
});
tween(b, {
alpha: 1
}, {
duration: 220,
easing: tween.easeOut
});
}
// Seçimden kısa süre sonra butonları ve gölgeyi kaldır
LK.setTimeout(function () {
// Remove shadow overlay with fade out
if (game._dramaticShadow) {
tween(game._dramaticShadow, {
alpha: 0
}, {
duration: 180,
easing: tween.easeIn,
onFinish: function onFinish() {
if (game._dramaticShadow) {
game.removeChild(game._dramaticShadow);
game._dramaticShadow = null;
}
}
});
}
// Remove buttons instantly
for (var j = 0; j < optionButtons.length; j++) {
(function (b) {
game.removeChild(b);
})(optionButtons[j]);
}
optionButtons = [];
// Apply effects (dramatic: +10~+30 or -30)
applyDramaticEffects(opt.effects, opt.meta);
// Resume music (if any)
if (typeof LK.playMusic === "function") LK.playMusic('musicId');
// Next dramatic turn: 4-6 turns later
nextDramaticTurn = turnCount + 4 + Math.floor(Math.random() * 3);
// Continue with normal story
LK.setTimeout(function () {
var nextIdx = getNextNode();
currentNode = nextIdx;
showStoryNode(currentNode);
}, 600);
}, 260);
});
game.addChild(btn);
optionButtons.push(btn);
})(node.options[i], i);
}
}
// Apply dramatic effects: bar changes are much larger
function applyDramaticEffects(effects, meta) {
if (!effects) return;
// Record memory
if (meta && meta.memoryLabel) pastChoices.push(meta.memoryLabel);
// Dramatic: apply full effect value (not just +1/-1)
if (typeof effects.lisa === 'number') rel_lisa = Math.max(0, Math.min(100, rel_lisa + effects.lisa));
if (typeof effects.rebecca === 'number') rel_rebecca = Math.max(0, Math.min(100, rel_rebecca + effects.rebecca));
if (typeof effects.peter === 'number') rel_peter = Math.max(0, Math.min(100, rel_peter + effects.peter));
if (typeof effects.alex === 'number') rel_alex = Math.max(0, Math.min(100, rel_alex + effects.alex));
if (typeof effects.happy === 'number') bar_happy = Math.max(0, Math.min(100, bar_happy + effects.happy));
if (typeof effects.honest === 'number') bar_honest = Math.max(0, Math.min(100, bar_honest + effects.honest));
if (typeof effects.lust === 'number') bar_lust = Math.max(0, Math.min(100, bar_lust + effects.lust));
if (typeof effects.betray === 'number') bar_betray = Math.max(0, Math.min(100, bar_betray + effects.betray));
// Shadow bar: dramatic choices have bigger impact
if (typeof effects.betray === 'number' && effects.betray > 0) bar_shadow = Math.max(0, Math.min(100, bar_shadow + 10));
if (typeof effects.honest === 'number' && effects.honest > 0) bar_shadow = Math.max(0, bar_shadow - 5);
updateBars();
turnCount++;
// Cross effects
applyCrossEffects(effects, meta);
// Check for ending
if (bar_happy <= 0) {
showEnding('Mutluluk sıfırlandı. Mike depresyona girdi.');
return;
}
if (bar_honest <= 0) {
showEnding('Dürüstlük sıfırlandı. Mike yalanlarla dolu bir hayata saplandı.');
return;
}
if (bar_lust <= 0) {
showEnding('Şehvet sıfırlandı. Mike hayattan keyif alamıyor.');
return;
}
if (bar_betray >= 100) {
showEnding('İhanet %100 oldu. Mike ilişkilerini kaybetti.');
return;
}
}
// Each story node: { text, options: [ {text, effects, next} ], portrait, speaker }
// --- Story Data ---
// Character portraits (simple colored boxes for now)
// Bar backgrounds and fills
// Option buttons
// --- Whiskey'e özel sorular (yalnızca satın alındıysa gösterilecek) ---
var whiskeyQuestions = [{
id: "whiskey_intro",
text: "Whiskey: 'Hav hav! Mike, parka gidelim mi?'",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Whiskey'i parka götür.",
effects: {
happy: 5
}
}, {
text: "Bugün evde kalalım.",
effects: {
happy: -2
}
}]
}, {
id: "whiskey_walk",
text: "Whiskey kapının önünde heyecanla bekliyor. Dışarı çıkarmak ister misin?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Whiskey ile uzun yürüyüş yap.",
effects: {
happy: 5
}
}, {
text: "Kısa bir yürüyüş yap.",
effects: {
happy: 2
}
}, {
text: "Yürüyüşe çıkma.",
effects: {
happy: -3
}
}]
}, {
id: "whiskey_vet",
text: "Whiskey biraz halsiz görünüyor. Veterinere götürecek misin?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Veterinere götür. ($200 harca)",
effects: {
happy: 5
},
meta: {
type: "whiskey_spend",
money: -200
}
}, {
text: "Evde dinlensin.",
effects: {
happy: -2
}
}]
}, {
id: "whiskey_toy",
text: "Whiskey yeni bir oyuncak istiyor.",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Oyuncak al. ($50 harca)",
effects: {
happy: 3
},
meta: {
type: "whiskey_spend",
money: -50
}
}, {
text: "Oyuncak alma.",
effects: {
happy: -2
}
}]
}, {
id: "whiskey_bath",
text: "Whiskey çamura bulandı! Yıkayacak mısın?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Whiskey'i yıka.",
effects: {
happy: 2
}
}, {
text: "Yıkamadan bırak.",
effects: {
happy: -3
}
}]
}, {
id: "whiskey_trick",
text: "Whiskey yeni bir numara öğrenmek istiyor. Öğretecek misin?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Yeni numara öğret.",
effects: {
happy: 4
}
}, {
text: "Vakit ayırma.",
effects: {
happy: -2
}
}]
}, {
id: "whiskey_vacation",
text: "Tatile çıkacaksınız. Whiskey'i de götürecek misin?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Whiskey'i de götür. ($300 harca)",
effects: {
happy: 5
},
meta: {
type: "whiskey_spend",
money: -300
}
}, {
text: "Whiskey'i pansiyona bırak. ($150 harca)",
effects: {
happy: 2
},
meta: {
type: "whiskey_spend",
money: -150
}
}]
}, {
id: "whiskey_birthday",
text: "Whiskey'in doğum günü! Ona özel bir şey yapmak ister misin?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Köpek pastası al. ($80 harca)",
effects: {
happy: 4
},
meta: {
type: "whiskey_spend",
money: -80
}
}, {
text: "Sadece sarıl.",
effects: {
happy: 2
}
}]
}, {
id: "whiskey_lost",
text: "Whiskey bahçede kayboldu! Arayacak mısın?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Bahçede ara.",
effects: {
happy: 3
}
}, {
text: "Kendi gelir diye bekle.",
effects: {
happy: -3
}
}]
}, {
id: "whiskey_vet2",
text: "Whiskey aşı zamanı geldi. Aşı yaptıracak mısın?",
portrait: "whiskey",
speaker: "Whiskey",
options: [{
text: "Aşı yaptır. ($120 harca)",
effects: {
happy: 3
},
meta: {
type: "whiskey_spend",
money: -120
}
}, {
text: "Aşıyı ertele.",
effects: {
happy: -2
}
}]
}];
// --- Villa'ya davet eventleri ve özel sorular (her karakter için 2'şer tane) ---
var villaInviteEvents = [{
id: "villa_invite_lisa",
text: "Artık bir villan var! Lisa'yı eve davet etmek ister misin?",
portrait: "lisa",
speaker: "Lisa",
options: [{
text: "Lisa'yı villaya davet et.",
effects: {
lisa: 15,
happy: 5
},
meta: {
type: "villa_invite",
character: "lisa"
}
}, {
text: "Davet etme.",
effects: {
lisa: -2
}
}]
}, {
id: "villa_invite_rebecca",
text: "Artık bir villan var! Rebecca'yı eve davet etmek ister misin?",
portrait: "rebecca",
speaker: "Rebecca",
options: [{
text: "Rebecca'yı villaya davet et.",
effects: {
rebecca: 15,
happy: 5
},
meta: {
type: "villa_invite",
character: "rebecca"
}
}, {
text: "Davet etme.",
effects: {
rebecca: -2
}
}]
}, {
id: "villa_invite_peter",
text: "Artık bir villan var! Peter'ı eve davet etmek ister misin?",
portrait: "peter",
speaker: "Peter",
options: [{
text: "Peter'ı villaya davet et.",
effects: {
peter: 15,
happy: 5
},
meta: {
type: "villa_invite",
character: "peter"
}
}, {
text: "Davet etme.",
effects: {
peter: -2
}
}]
}, {
id: "villa_invite_alex",
text: "Artık bir villan var! Alex'i eve davet etmek ister misin?",
portrait: "alex",
speaker: "Alex",
options: [{
text: "Alex'i villaya davet et.",
effects: {
alex: 15,
happy: 5
},
meta: {
type: "villa_invite",
character: "alex"
}
}, {
text: "Davet etme.",
effects: {
alex: -2
}
}]
}];
var villaSpecialQuestions = [
// Lisa
{
id: "villa_lisa_1",
text: "Lisa: 'Bu evde birlikte yeni anılar biriktirelim mi?'",
portrait: "lisa",
speaker: "Lisa",
options: [{
text: "Evet, birlikte çok güzel anılarımız olacak.",
effects: {
lisa: 10,
happy: 5
}
}, {
text: "Ev güzel ama önemli olan sensin.",
effects: {
lisa: 7,
honest: 3
}
}]
}, {
id: "villa_lisa_2",
text: "Lisa: 'Villada bir parti verelim mi?'",
portrait: "lisa",
speaker: "Lisa",
options: [{
text: "Harika fikir, parti verelim.",
effects: {
lisa: 8,
happy: 4
}
}, {
text: "Parti istemiyorum.",
effects: {
lisa: -3
}
}]
},
// Rebecca
{
id: "villa_rebecca_1",
text: "Rebecca: 'Villanın havuzunda gece yüzmek ister misin?'",
portrait: "rebecca",
speaker: "Rebecca",
options: [{
text: "Tabii, birlikte yüzmek harika olur.",
effects: {
rebecca: 10,
lust: 5
}
}, {
text: "Yorgunum, başka zaman.",
effects: {
rebecca: -2
}
}]
}, {
id: "villa_rebecca_2",
text: "Rebecca: 'Villada baş başa bir akşam geçirelim mi?'",
portrait: "rebecca",
speaker: "Rebecca",
options: [{
text: "Evet, baş başa kalmak güzel olur.",
effects: {
rebecca: 8,
happy: 3
}
}, {
text: "Bugün olmaz.",
effects: {
rebecca: -2
}
}]
},
// Peter
{
id: "villa_peter_1",
text: "Peter: 'Bahçede mangal yapalım mı?'",
portrait: "peter",
speaker: "Peter",
options: [{
text: "Mangal harika olur!",
effects: {
peter: 10,
happy: 4
}
}, {
text: "Başka zaman.",
effects: {
peter: -2
}
}]
}, {
id: "villa_peter_2",
text: "Peter: 'Villada birlikte film gecesi yapalım mı?'",
portrait: "peter",
speaker: "Peter",
options: [{
text: "Evet, film gecesi yapalım.",
effects: {
peter: 8,
happy: 3
}
}, {
text: "İstemiyorum.",
effects: {
peter: -2
}
}]
},
// Alex
{
id: "villa_alex_1",
text: "Alex: 'Bu villada iş toplantısı yapmak isterim.'",
portrait: "alex",
speaker: "Alex",
options: [{
text: "Tabii, toplantı yapabiliriz.",
effects: {
alex: 10,
happy: 2
}
}, {
text: "Evde iş konuşmak istemiyorum.",
effects: {
alex: -2
}
}]
}, {
id: "villa_alex_2",
text: "Alex: 'Villanın manzarası harika, burada çalışmak isterim.'",
portrait: "alex",
speaker: "Alex",
options: [{
text: "İstediğin zaman gelebilirsin.",
effects: {
alex: 8,
honest: 2
}
}, {
text: "Evde yalnız kalmak istiyorum.",
effects: {
alex: -2
}
}]
}];
// --- Giselle'e özel sorular (yalnızca satın alındıysa gösterilecek) ---
var giselleQuestions = [{
id: "giselle_intro",
text: "Giselle: 'Mike, yeni bir çanta almak istiyorum. Bütçemiz yeterli mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Tabii, hemen alalım. ($500 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -500
}
}, {
text: "Şu an alamayız, bütçemiz kısıtlı.",
effects: {
happy: -5,
honest: 5
},
meta: {
type: "truth"
}
}]
}, {
id: "giselle_shopping",
text: "Giselle: 'Alışverişe çıkalım mı? Birkaç şey almak istiyorum.'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Giselle'e para ver. ($300 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -300
}
}, {
text: "Bugün alışveriş yok.",
effects: {
happy: -5
}
}]
}, {
id: "giselle_dinner",
text: "Giselle: 'Bu akşam dışarıda yemek yiyelim mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Lüks restorana git. ($400 harca)",
effects: {
happy: 10,
lust: 5
},
meta: {
type: "giselle_spend",
money: -400
}
}, {
text: "Evde yemek yapalım.",
effects: {
happy: -5
}
}]
}, {
id: "giselle_gift",
text: "Giselle: 'Bana hediye alır mısın?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Pahalı bir kolye al. ($1000 harca)",
effects: {
happy: 10,
lust: 5
},
meta: {
type: "giselle_spend",
money: -1000
}
}, {
text: "Küçük bir hediye al. ($100 harca)",
effects: {
happy: 3
},
meta: {
type: "giselle_spend",
money: -100
}
}, {
text: "Hediye almayacağım.",
effects: {
happy: -10
}
}]
}, {
id: "giselle_jealous",
text: "Giselle: 'Lisa ile çok vakit geçiriyorsun, kıskanıyorum.'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Giselle'e güven ver.",
effects: {
happy: 5,
honest: 5
}
}, {
text: "Lisa ile görüşmeyi azalt.",
effects: {
happy: 2,
lust: -2
}
}]
}, {
id: "giselle_party",
text: "Giselle: 'Hafta sonu partiye gidelim mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Partiye git. ($200 harca)",
effects: {
happy: 5,
lust: 5
},
meta: {
type: "giselle_spend",
money: -200
}
}, {
text: "Evde kalalım.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_baby",
text: "Giselle: 'Bir bebek sahibi olmayı düşünür müsün?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Evet, isterim.",
effects: {
happy: 10,
lust: 5
},
meta: {
type: "giselle_baby"
}
}, {
text: "Henüz hazır değilim.",
effects: {
happy: -5
}
}]
}, {
id: "giselle_trip",
text: "Giselle: 'Birlikte tatile çıkalım mı?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Tatile çık. ($1500 harca)",
effects: {
happy: 10,
lust: 5
},
meta: {
type: "giselle_spend",
money: -1500
}
}, {
text: "Tatil için paramız yok.",
effects: {
happy: -5
}
}]
}, {
id: "giselle_friends",
text: "Giselle: 'Arkadaşlarımı davet edebilir miyim?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Tabii, davet et.",
effects: {
happy: 5
}
}, {
text: "Hayır, bu akşam yalnız kalalım.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_shoes",
text: "Giselle: 'Yeni ayakkabılar almak istiyorum.'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Ayakkabı al. ($250 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -250
}
}, {
text: "Şu an alamayız.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_movie",
text: "Giselle: 'Bu akşam sinemaya gidelim mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Sinemaya git. ($100 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -100
}
}, {
text: "Evde film izleyelim.",
effects: {
happy: 2
}
}]
}, {
id: "giselle_dress",
text: "Giselle: 'Yeni bir elbise almak istiyorum.'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Elbise al. ($350 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -350
}
}, {
text: "Şu an alamayız.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_jewelry",
text: "Giselle: 'Takı mağazasına gidelim mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Takı al. ($200 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -200
}
}, {
text: "Takı almayalım.",
effects: {
happy: -2
}
}]
}, {
id: "giselle_spa",
text: "Giselle: 'Birlikte spa'ya gidelim mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Spa'ya git. ($400 harca)",
effects: {
happy: 7
},
meta: {
type: "giselle_spend",
money: -400
}
}, {
text: "Evde dinlenelim.",
effects: {
happy: 2
}
}]
}, {
id: "giselle_phone",
text: "Giselle: 'Yeni bir telefon almak istiyorum.'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Telefon al. ($1200 harca)",
effects: {
happy: 10
},
meta: {
type: "giselle_spend",
money: -1200
}
}, {
text: "Şu an alamayız.",
effects: {
happy: -5
}
}]
}, {
id: "giselle_bag",
text: "Giselle: 'Çantam eskidi, yenisini alabilir miyiz?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Çanta al. ($300 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -300
}
}, {
text: "Şu an alamayız.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_makeup",
text: "Giselle: 'Kozmetik alışverişi yapalım mı?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Kozmetik al. ($150 harca)",
effects: {
happy: 3
},
meta: {
type: "giselle_spend",
money: -150
}
}, {
text: "Hayır, gerek yok.",
effects: {
happy: -2
}
}]
}, {
id: "giselle_jacket",
text: "Giselle: 'Yeni bir ceket almak istiyorum.'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Ceket al. ($400 harca)",
effects: {
happy: 5
},
meta: {
type: "giselle_spend",
money: -400
}
}, {
text: "Şu an alamayız.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_ring",
text: "Giselle: 'Yüzük bakmaya gidelim mi?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Yüzük al. ($800 harca)",
effects: {
happy: 8
},
meta: {
type: "giselle_spend",
money: -800
}
}, {
text: "Yüzük almayalım.",
effects: {
happy: -3
}
}]
}, {
id: "giselle_baby2",
text: "Giselle: 'Bebek sahibi olmayı hâlâ düşünüyor musun?'",
portrait: "giselle",
speaker: "Giselle",
options: [{
text: "Evet, isterim.",
effects: {
happy: 10,
lust: 5
},
meta: {
type: "giselle_baby"
}
}, {
text: "Henüz hazır değilim.",
effects: {
happy: -5
}
}]
}];
// --- Ana story havuzu ---
var story = [
// Lisa kahvaltı - düşük ilişki
{
id: "lisa_breakfast_low",
text: "Lisa sabah kahvaltı hazırlamış ama aranız biraz soğuk. Mike ne der?",
portrait: 'lisa',
speaker: 'Lisa',
mood: "sad",
barCheck: {
key: "lisa",
max: 40
},
options: [{
text: "Yine mi aynı şey, biraz değişiklik yap.",
effects: {
lisa: -10,
happy: -5
},
meta: {
type: "truth"
},
next: null
}, {
text: "Teşekkür etmeden geçiştir.",
effects: {
lisa: -5
},
meta: {
type: "lie"
},
next: null
}]
},
// Lisa kahvaltı - orta ilişki
{
id: "lisa_breakfast_mid",
text: "Lisa sabah kahvaltı hazırlamış. Mike ne der?",
portrait: 'lisa',
speaker: 'Lisa',
mood: "neutral",
barCheck: {
key: "lisa",
min: 41,
max: 80
},
regretTrigger: "lied",
options: [{
text: "Çok güzel olmuş, teşekkür ederim.",
effects: {
lisa: 10,
happy: 5
},
next: null
}, {
text: "Yine mi aynı şey, biraz değişiklik yap.",
effects: {
lisa: -10,
happy: -5
},
meta: {
type: "lie"
},
next: null
}]
},
// Lisa kahvaltı - yüksek ilişki
{
id: "lisa_breakfast_high",
text: "Lisa sabah kahvaltı hazırlamış, aranız çok iyi. Mike ne der?",
portrait: 'lisa',
speaker: 'Lisa',
mood: "happy",
barCheck: {
key: "lisa",
min: 81
},
options: [{
text: "Sana her gün teşekkür etsem az, harikasın.",
effects: {
lisa: 10,
happy: 10
},
next: null
}, {
text: "Bugün de seninle kahvaltı yapmak çok güzel.",
effects: {
lisa: 5,
happy: 5
},
next: null
}]
},
// Rebecca sabah mesaj - düşük ilişki
{
id: "rebecca_morning_low",
text: "Rebecca sabah mesaj atıyor ama aranız biraz soğuk: 'Günaydın, öğle arasında buluşalım mı?'",
portrait: 'rebecca',
speaker: 'Rebecca',
mood: "sad",
barCheck: {
key: "rebecca",
max: 40
},
options: [{
text: "Şu an yoğunum, sonra konuşuruz.",
effects: {
rebecca: -5,
honest: 5
},
meta: {
type: "truth"
},
next: null
}, {
text: "Kısa cevap ver.",
effects: {
rebecca: -5
},
meta: {
type: "lie"
},
next: null
}]
},
// Rebecca sabah mesaj - orta ilişki
{
id: "rebecca_morning_mid",
text: "Rebecca sabah mesaj atıyor: 'Günaydın, öğle arasında buluşalım mı?'",
portrait: 'rebecca',
speaker: 'Rebecca',
mood: "neutral",
barCheck: {
key: "rebecca",
min: 41,
max: 80
},
options: [{
text: "Tabii, öğle arasında buluşalım.",
effects: {
rebecca: 10,
lust: 5,
betray: 5
},
next: null
}, {
text: "Şu an yoğunum, sonra konuşuruz.",
effects: {
rebecca: -5,
honest: 5
},
next: null
}]
},
// Rebecca sabah mesaj - yüksek ilişki
{
id: "rebecca_morning_high",
text: "Rebecca sabah mesaj atıyor, aranız çok iyi: 'Günaydın yakışıklı, öğle arasında buluşalım mı?'",
portrait: 'rebecca',
speaker: 'Rebecca',
mood: "happy",
barCheck: {
key: "rebecca",
min: 81
},
options: [{
text: "Seni görmek için sabırsızlanıyorum.",
effects: {
rebecca: 10,
lust: 10,
betray: 10
},
next: null
}, {
text: "Bugün işim var ama akşam konuşalım.",
effects: {
rebecca: 5,
honest: 5
},
next: null
}]
},
// ... (diğer orijinal story node'lar buraya eklenebilir, örnek olarak ilk iki olay çoğaltıldı)
// 3
{
text: "Patronun Alex seni sert bir şekilde eleştiriyor. Ne yaparsın?",
portrait: 'alex',
speaker: 'Alex',
mood: "angry",
options: [{
text: "Haklısınız, daha dikkatli olacağım.",
effects: {
alex: 10,
honest: 5,
happy: -5
},
next: null
}, {
text: "Bana fazla yükleniyorsunuz, adil değil.",
effects: {
alex: -10,
happy: -5
},
next: null
}]
},
// --- Ava: New story questions for more variety ---
{
text: "Lisa ile alışverişe çıktınız. Lisa yeni bir elbise almak istiyor.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Elbise almasına destek ol.",
effects: {
lisa: 10,
happy: 5
}
}, {
text: "Bütçemiz kısıtlı, başka zaman alalım.",
effects: {
lisa: -5,
honest: 5
}
}]
}, {
text: "Rebecca iş yerinde sana bir sır veriyor.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Sırrını sakla.",
effects: {
rebecca: 10,
honest: 5
}
}, {
text: "Sırrı başkasına anlat.",
effects: {
rebecca: -10,
betray: 10
}
}]
}, {
text: "Peter ile futbol maçı izliyorsunuz.",
portrait: 'peter',
speaker: 'Peter',
options: [{
text: "Beraber tezahürat yap.",
effects: {
peter: 10,
happy: 5
}
}, {
text: "Maçtan sıkıldığını söyle.",
effects: {
peter: -5
}
}]
}, {
text: "Alex yeni bir iş fırsatı sunuyor.",
portrait: 'alex',
speaker: 'Alex',
options: [{
text: "Fırsatı kabul et.",
effects: {
alex: 10,
happy: 5
}
}, {
text: "Reddet, mevcut işinden memnunsun.",
effects: {
alex: -5,
honest: 5
}
}]
}, {
text: "Lisa ile tartıştınız. Lisa üzgün.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Özür dile.",
effects: {
lisa: 10,
honest: 5
}
}, {
text: "Haklı olduğunu savun.",
effects: {
lisa: -10
}
}]
}, {
text: "Rebecca ile sinemaya gitme planı yapıyorsun.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Romantik bir film seç.",
effects: {
rebecca: 10,
lust: 5
}
}, {
text: "Aksiyon filmi seç.",
effects: {
rebecca: 5
}
}]
}, {
text: "Peter sana bir kitap öneriyor.",
portrait: 'peter',
speaker: 'Peter',
options: [{
text: "Kitabı oku ve yorum yap.",
effects: {
peter: 10,
honest: 5
}
}, {
text: "Kitabı okumadığını itiraf et.",
effects: {
peter: -5,
honest: 5
}
}]
}, {
text: "Alex ile iş seyahatine çıkıyorsun.",
portrait: 'alex',
speaker: 'Alex',
options: [{
text: "Alex ile yakınlaş.",
effects: {
alex: 10,
betray: 5
}
}, {
text: "Mesafeni koru.",
effects: {
alex: 5,
honest: 5
}
}]
}, {
text: "Lisa sana sürpriz bir doğum günü partisi hazırlıyor.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Çok mutlu ol ve teşekkür et.",
effects: {
lisa: 10,
happy: 10
}
}, {
text: "Sürprizleri sevmediğini söyle.",
effects: {
lisa: -5,
honest: 5
}
}]
}, {
text: "Rebecca ile bir tartışma yaşıyorsun.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Barışmak için adım at.",
effects: {
rebecca: 10
}
}, {
text: "Tartışmayı uzat.",
effects: {
rebecca: -10
}
}]
}, {
text: "Peter ile eski bir fotoğraf albümüne bakıyorsun.",
portrait: 'peter',
speaker: 'Peter',
options: [{
text: "Güzel anıları hatırla.",
effects: {
peter: 10,
happy: 5
}
}, {
text: "Geçmişi konuşmak istemediğini söyle.",
effects: {
peter: -5
}
}]
}, {
text: "Alex iş yerinde seni övüyor.",
portrait: 'alex',
speaker: 'Alex',
options: [{
text: "Teşekkür et.",
effects: {
alex: 10,
happy: 5
}
}, {
text: "Mütevazı davran.",
effects: {
alex: 5
}
}]
}, {
text: "Lisa ile birlikte yemek yapıyorsun.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Birlikte eğlenerek yemek yap.",
effects: {
lisa: 10,
happy: 5
}
}, {
text: "Yemek yapmayı sevmediğini söyle.",
effects: {
lisa: -5
}
}]
}, {
text: "Rebecca yeni bir hobiye başlamak istiyor.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Onu destekle.",
effects: {
rebecca: 10
}
}, {
text: "Hobisini gereksiz bul.",
effects: {
rebecca: -5
}
}]
}, {
text: "Peter ile bir iş projesinde çalışıyorsun.",
portrait: 'peter',
speaker: 'Peter',
options: [{
text: "Peter'ın fikirlerine değer ver.",
effects: {
peter: 10
}
}, {
text: "Kendi bildiğini yap.",
effects: {
peter: -5
}
}]
}, {
text: "Alex ile bir anlaşmazlık yaşıyorsun.",
portrait: 'alex',
speaker: 'Alex',
options: [{
text: "Uzlaşmacı ol.",
effects: {
alex: 10
}
}, {
text: "Kendi fikrinde ısrar et.",
effects: {
alex: -5
}
}]
},
// 3
{
text: "Patronun Alex seni sert bir şekilde eleştiriyor. Ne yaparsın?",
portrait: 'alex',
speaker: 'Alex',
mood: "angry",
options: [{
text: "Haklısınız, daha dikkatli olacağım.",
effects: {
alex: 10,
honest: 5,
happy: -5
},
next: null
}, {
text: "Bana fazla yükleniyorsunuz, adil değil.",
effects: {
alex: -10,
happy: -5
},
next: null
}]
},
// 4
{
text: "Peter zor durumda olduğunu söylüyor. Ne yaparsın?",
portrait: 'peter',
speaker: 'Peter',
mood: "sad",
options: [{
text: "Yanındayım, neye ihtiyacın varsa söyle.",
effects: {
peter: 10,
happy: 5
},
next: null
}, {
text: "Kendi işimle meşgulüm, üzgünüm.",
effects: {
peter: -10,
happy: -5
},
next: null
}]
},
// 5
{
text: "Lisa seninle dürüstçe konuşmak istiyor. Ne yaparsın?",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Tabii, ne söylemek istiyorsan dinliyorum.",
effects: {
lisa: 10,
honest: 10
},
next: null
}, {
text: "Bunları konuşmak istemiyorum.",
effects: {
lisa: -10,
honest: -10
},
next: null
}]
},
// 6
{
text: "Rebecca ile ofiste samimi bir an yaşıyorsun. Lisa yanında.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Lisa burada, sonra konuşalım.",
effects: {
rebecca: -5,
honest: 5
},
next: null
}, {
text: "Hemen sana geliyorum.",
effects: {
rebecca: 10,
lisa: -10,
betray: 10
},
next: null
}]
},
// 7
{
text: "Yorgunsun, Lisa dışarı çıkmak istiyor.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Bugün yorgunum, evde kalalım.",
effects: {
lisa: -5,
happy: -5
},
next: null
}, {
text: "Tamam, seninle dışarı çıkalım.",
effects: {
lisa: 10,
happy: 5
},
next: null
}]
},
// 8
{
text: "Alex önemli bir projeyi sana teslim etti.",
portrait: 'alex',
speaker: 'Alex',
mood: "neutral",
options: [{
text: "Gerçekçi zaman verirsek başarı şansı artar.",
effects: {
alex: 10,
honest: 10
},
next: null
}, {
text: "Mümkün olduğunca hızlı yapacağım, sorun yok.",
effects: {
alex: -5,
happy: 5
},
next: null
}]
},
// 9
{
text: "Peter geçmişte yaptığın bir hatayı hatırlatıyor.",
portrait: 'peter',
speaker: 'Peter',
mood: "angry",
regretTrigger: "ignored_peter",
options: [{
text: "Haklısın, özür dilerim.",
effects: {
peter: 10,
honest: 10
},
next: null
}, {
text: "O günler geçti, unutalım.",
effects: {
peter: -10
},
meta: {
ignoreRegret: true
},
next: null
}]
},
// 10
{
text: "Lisa bir sır sakladığını düşünüyor.",
portrait: 'lisa',
speaker: 'Lisa',
regretTrigger: "betrayed_lisa",
options: [{
text: "Sana her şeyi anlatacağım.",
effects: {
lisa: 10,
honest: 10
},
next: null
}, {
text: "Beni yanlış anlıyorsun.",
effects: {
lisa: -10,
honest: -10
},
meta: {
type: "lie"
},
next: null
}]
},
// 11
{
text: "Rebecca ile iş çıkışı kafede buluşuyorsun.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Rebecca ile samimi bir sohbet et.",
effects: {
rebecca: 10,
lust: 10,
betray: 5
},
next: null
}, {
text: "Kısa kesip eve git.",
effects: {
rebecca: -5,
lisa: 5,
honest: 5
},
next: null
}]
},
// 12
{
text: "Alex seni fazla mesaiye bırakmak istiyor.",
portrait: 'alex',
speaker: 'Alex',
mood: "neutral",
options: [{
text: "Kabul et, işini bitir.",
effects: {
alex: 10,
happy: -5
},
next: null
}, {
text: "Reddet, eve git.",
effects: {
alex: -10,
lisa: 5,
happy: 5
},
next: null
}]
},
// 13
{
text: "Peter ile eski günlerden konuşuyorsun.",
portrait: 'peter',
speaker: 'Peter',
mood: "happy",
options: [{
text: "Duygusal bir anı paylaş.",
effects: {
peter: 10,
happy: 5
},
next: null
}, {
text: "Geçmişi geçiştir.",
effects: {
peter: -5
},
next: null
}]
},
// 14
{
text: "Lisa ile romantik bir akşam yemeği.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Lisa'ya iltifat et.",
effects: {
lisa: 10,
happy: 10,
lust: 5
},
next: null
}, {
text: "Yemekle ilgilenme, telefona bak.",
effects: {
lisa: -10,
happy: -5,
lust: -5
},
next: null
}]
},
// 15
{
text: "Rebecca işte sana yardım ediyor.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Teşekkür et, birlikte çalış.",
effects: {
rebecca: 10,
honest: 5
},
next: null
}, {
text: "Yardımı reddet.",
effects: {
rebecca: -5
},
next: null
}]
},
// 16
{
text: "Alex işte bir hata buldu.",
portrait: 'alex',
speaker: 'Alex',
mood: "angry",
options: [{
text: "Hatanı kabul et.",
effects: {
alex: 5,
honest: 10
},
next: null
}, {
text: "Suçu başkasına at.",
effects: {
alex: -10,
honest: -10,
betray: 10
},
next: null
}]
},
// 17
{
text: "Peter ile tartıştın.",
portrait: 'peter',
speaker: 'Peter',
mood: "angry",
options: [{
text: "Barışmak için adım at.",
effects: {
peter: 10,
honest: 5
},
next: null
}, {
text: "Görmezden gel.",
effects: {
peter: -10,
happy: -5
},
next: null
}]
},
// 18
{
text: "Lisa ile hafta sonu planı yapıyorsun.",
portrait: 'lisa',
speaker: 'Lisa',
options: [{
text: "Birlikte sinemaya git.",
effects: {
lisa: 10,
happy: 5
},
next: null
}, {
text: "Evde kalmayı teklif et.",
effects: {
lisa: -5,
happy: 5
},
next: null
}]
},
// 19
{
text: "Rebecca ile iş gezisine çıkıyorsun.",
portrait: 'rebecca',
speaker: 'Rebecca',
options: [{
text: "Samimi davran.",
effects: {
rebecca: 10,
lust: 10,
betray: 5
},
next: null
}, {
text: "Mesafeni koru.",
effects: {
rebecca: -5,
honest: 5
},
next: null
}]
},
// 20
{
text: "Alex yeni bir görev veriyor.",
portrait: 'alex',
speaker: 'Alex',
mood: "neutral",
options: [{
text: "Görevi kabul et.",
effects: {
alex: 10,
happy: 5
},
next: null
}, {
text: "Görevi reddet.",
effects: {
alex: -10,
happy: -5
},
next: null
}]
}];
// --- State ---
// Relationship values (0-100)
var rel_lisa = 50;
var rel_rebecca = 50;
var rel_peter = 50;
var rel_alex = 50;
// Bars (0-100)
var bar_happy = 50;
var bar_honest = 50;
var bar_lust = 50;
var bar_betray = 50;
// --- Shadow bar (0-100, hidden from player) ---
var bar_shadow = 0;
// Bar-based flags (for special scenes/endings)
var flags = {};
// Track important past choices for memory mechanic
var pastChoices = [];
// Turn counter for time-based triggers
var turnCount = 0;
// --- Ava: Time, salary, baby, pregnancy, money mechanics ---
var dayCount = 1; // 1-based, every 2 questions = 1 day
var mikeSalary = 100;
var mikeMoney = 0;
var mikeBabyCount = 0;
var lisaPregnant = false;
var rebeccaPregnant = false;
var gisellePregnant = false;
var showLisaPregOption = false;
var showRebeccaPregOption = false;
var showGisellePregOption = false;
var giselleUnlocked = false; // Satın alındı mı?
var shopItemStates = [false, false, false, false]; // 0: Giselle, 1-3: diğerleri
// --- UI Elements ---
// Portrait
var portraitNode = null;
// Speaker name
var speakerText = null;
// Story text
var storyText = null;
// Option buttons
var optionButtons = [];
// Relationship bars
var barNodes = {};
// Karakter portreleri ve ilişki dereceleri için UI
var characterPortraits = [];
var characterLabels = [];
// --- Ava: UI for day, salary, money, baby count ---
var dayText = null;
var salaryText = null;
var moneyText = null;
var babyText = null;
// --- Functions ---
// getNextNode: uygun story node'unu bar değerine göre seç
// --- Ava: Prevent same question from repeating within last 20, and add more questions ---
var lastStoryIndices = [];
function getNextNode() {
// Tüm story node'larını karıştır
var indices = [];
for (var i = 0; i < story.length; i++) {
indices.push(i);
}
// Fisher-Yates shuffle
for (var i = indices.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = indices[i];
indices[i] = indices[j];
indices[j] = temp;
}
// Ava: Filter out nodes that were used in the last 20
var filteredIndices = [];
for (var k = 0; k < indices.length; k++) {
var idx = indices[k];
if (lastStoryIndices.indexOf(idx) === -1) {
filteredIndices.push(idx);
}
}
// If less than 5 available, allow all (reset)
var useIndices = filteredIndices.length > 5 ? filteredIndices : indices;
// --- Giselle: Eğer satın alındıysa, havuza Giselle sorularını da ekle ---
// --- Whiskey: Eğer satın alındıysa, havuza Whiskey sorularını da ekle ---
// --- Villa: Eğer satın alındıysa, havuza Villa event ve sorularını da ekle ---
var pool = [];
for (var k = 0; k < useIndices.length; k++) {
var idx = useIndices[k];
var node = story[idx];
// Sadece Giselle alınmışsa Giselle soruları havuza eklenir
if (node && node.portrait === "giselle" && !giselleUnlocked) continue;
// Sadece Whiskey alınmışsa Whiskey soruları havuza eklenir
if (node && node.portrait === "whiskey" && !whiskeyUnlocked) continue;
// Villa eventleri ve soruları sadece villaUnlocked ise eklenir
if (node && node.id && node.id.indexOf("villa_") === 0 && !villaUnlocked) continue;
pool.push({
idx: idx,
node: node
});
}
if (giselleUnlocked) {
// Son 20'de olmayan Giselle sorularını da ekle
for (var g = 0; g < giselleQuestions.length; g++) {
var gq = giselleQuestions[g];
var gqId = "giselle_" + g;
// Sadece son 20'de yoksa ekle
var alreadyUsed = false;
for (var h = 0; h < lastStoryIndices.length; h++) {
if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === gq.id) alreadyUsed = true;
}
if (!alreadyUsed) {
pool.push({
idx: -1,
node: gq
});
}
}
}
if (whiskeyUnlocked) {
// Son 20'de olmayan Whiskey sorularını da ekle
for (var w = 0; w < whiskeyQuestions.length; w++) {
var wq = whiskeyQuestions[w];
var wqId = "whiskey_" + w;
var alreadyUsedW = false;
for (var h = 0; h < lastStoryIndices.length; h++) {
if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === wq.id) alreadyUsedW = true;
}
if (!alreadyUsedW) {
pool.push({
idx: -1,
node: wq
});
}
}
}
if (villaUnlocked) {
// Son 20'de olmayan Villa invite eventlerini ekle
for (var v = 0; v < villaInviteEvents.length; v++) {
var ve = villaInviteEvents[v];
var alreadyUsedV = false;
for (var h = 0; h < lastStoryIndices.length; h++) {
if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === ve.id) alreadyUsedV = true;
}
if (!alreadyUsedV) {
pool.push({
idx: -1,
node: ve
});
}
}
// Son 20'de olmayan Villa özel sorularını ekle
for (var vq = 0; vq < villaSpecialQuestions.length; vq++) {
var vsq = villaSpecialQuestions[vq];
var alreadyUsedVSQ = false;
for (var h = 0; h < lastStoryIndices.length; h++) {
if (story[lastStoryIndices[h]] && story[lastStoryIndices[h]].id === vsq.id) alreadyUsedVSQ = true;
}
if (!alreadyUsedVSQ) {
pool.push({
idx: -1,
node: vsq
});
}
}
}
// Her bir node'u sırayla kontrol et, barCheck varsa uygun olanı döndür
for (var k = 0; k < pool.length; k++) {
var idx = pool[k].idx;
var node = pool[k].node;
if (!node.options || node.options.length === 0) continue;
if (node.barCheck) {
var key = node.barCheck.key;
var min = typeof node.barCheck.min === "number" ? node.barCheck.min : -Infinity;
var max = typeof node.barCheck.max === "number" ? node.barCheck.max : Infinity;
var val = 0;
if (key === "lisa") val = rel_lisa;else if (key === "rebecca") val = rel_rebecca;else if (key === "peter") val = rel_peter;else if (key === "alex") val = rel_alex;else if (key === "happy") val = bar_happy;else if (key === "honest") val = bar_honest;else if (key === "lust") val = bar_lust;else if (key === "betray") val = bar_betray;
if (val >= min && val <= max) {
lastStoryIndices.push(idx);
if (lastStoryIndices.length > 20) lastStoryIndices.shift();
return idx;
}
} else {
lastStoryIndices.push(idx);
if (lastStoryIndices.length > 20) lastStoryIndices.shift();
return idx;
}
}
// Hiçbiri uygun değilse ilk node'u döndür
lastStoryIndices.push(0);
if (lastStoryIndices.length > 20) lastStoryIndices.shift();
return 0;
}
function resetGameState() {
rel_lisa = 50;
rel_rebecca = 50;
rel_peter = 50;
rel_alex = 50;
bar_happy = 50;
bar_honest = 50;
bar_lust = 50;
bar_betray = 50;
bar_shadow = 0;
flags = {};
pastChoices = [];
turnCount = 0;
currentNode = 0;
// Reset dramatic system
nextDramaticTurn = 4 + Math.floor(Math.random() * 3);
dramaticHistory = [];
if (game._dramaticShadow) {
game.removeChild(game._dramaticShadow);
game._dramaticShadow = null;
}
dayCount = 1;
mikeSalary = 100;
mikeMoney = 0;
mikeBabyCount = 0;
lisaPregnant = false;
rebeccaPregnant = false;
gisellePregnant = false;
giselleUnlocked = false;
whiskeyUnlocked = false;
villaUnlocked = false;
shopItemStates = [false, false, false, false];
if (storage) {
storage.mikeMoney = 0;
storage.mikeSalary = 100;
storage.mikeBabyCount = 0;
storage.dayCount = 1;
storage.lisaPregnant = false;
storage.rebeccaPregnant = false;
storage.gisellePregnant = false;
storage.giselleUnlocked = false;
storage.whiskeyUnlocked = false;
storage.villaUnlocked = false;
}
}
function createUI() {
// Portrait
if (portraitNode) game.removeChild(portraitNode);
portraitNode = LK.getAsset('mike', {
anchorX: 0.5,
anchorY: 0.5
});
// Mike portresini ve karakteri ekrana tam ortala
portraitNode.x = 2048 / 2;
portraitNode.y = 520;
game.addChild(portraitNode);
// --- Mike portresine titreme animasyonu ekle ---
function shakePortrait(node) {
if (!node) return;
var origX = 2048 / 2;
var origY = 520;
function doShake() {
// Rastgele küçük bir ofset (±8px)
var dx = (Math.random() - 0.5) * 16;
var dy = (Math.random() - 0.5) * 10;
tween(node, {
x: origX + dx,
y: origY + dy
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
tween(node, {
x: origX,
y: origY
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
LK.setTimeout(doShake, 80 + Math.floor(Math.random() * 60));
}
});
}
});
}
doShake();
}
shakePortrait(portraitNode);
// --- Eğer ilgili karakter portresi varsa ona da titreme ekle ---
if (game.relatedPortraitNode) {
var _shakeRelated = function shakeRelated() {
if (!relNode.parent) return; // Silindiyse dur
var dx = (Math.random() - 0.5) * 16;
var dy = (Math.random() - 0.5) * 10;
tween(relNode, {
x: relOrigX + dx,
y: relOrigY + dy
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
tween(relNode, {
x: relOrigX,
y: relOrigY
}, {
duration: 80,
easing: tween.linear,
onFinish: function onFinish() {
LK.setTimeout(_shakeRelated, 80 + Math.floor(Math.random() * 60));
}
});
}
});
};
var relNode = game.relatedPortraitNode;
var relOrigX = relNode.x;
var relOrigY = relNode.y;
_shakeRelated();
}
// Speaker (isim) biraz daha aşağıda
if (speakerText) game.removeChild(speakerText);
speakerText = new Text2('', {
size: 64,
fill: '#ffffff'
});
speakerText.anchor.set(0.5, 0.5);
speakerText.x = 2048 / 2;
speakerText.y = 740;
game.addChild(speakerText);
// Story text (olay) biraz daha aşağıda
if (storyText) game.removeChild(storyText);
storyText = new Text2('', {
size: 54,
fill: '#ffffff',
wordWrap: true,
wordWrapWidth: 1800
});
storyText.anchor.set(0.5, 0);
storyText.x = 2048 / 2;
storyText.y = 830;
game.addChild(storyText);
// Relationship bars
var barNames = [{
key: 'happy',
label: 'Mutluluk',
y: 1100,
val: bar_happy
}, {
key: 'honest',
label: 'Dürüstlük',
y: 1180,
val: bar_honest
}, {
key: 'lust',
label: 'Şehvet',
y: 1260,
val: bar_lust
}, {
key: 'betray',
label: 'İhanet',
y: 1340,
val: bar_betray
}];
for (var i = 0; i < barNames.length; i++) {
var b = barNames[i];
if (barNodes[b.key]) game.removeChild(barNodes[b.key]);
var bar = new RelationshipBar();
bar.setType(b.key);
bar.setValue(b.val);
// Bar ismi ve yüzdeyi birlikte göster
if (bar.label) bar.removeChild(bar.label);
bar.label = new Text2(b.label + ' (' + b.val + '%)', {
size: 36,
fill: '#ffffff'
});
bar.label.anchor.set(1, 0.5);
bar.label.x = bar.maxWidth + 20;
bar.label.y = 20;
bar.addChild(bar.label);
bar.x = 2048 / 2 - 200;
bar.y = b.y;
game.addChild(bar);
barNodes[b.key] = bar;
}
// Karakter portreleri ve ilişki dereceleri (en altta)
for (var i = 0; i < characterPortraits.length; i++) {
game.removeChild(characterPortraits[i]);
}
for (var i = 0; i < characterLabels.length; i++) {
game.removeChild(characterLabels[i]);
}
characterPortraits = [];
characterLabels = [];
var chars = [{
key: 'lisa',
label: 'Lisa',
rel: rel_lisa
}, {
key: 'rebecca',
label: 'Rebecca',
rel: rel_rebecca
}, {
key: 'peter',
label: 'Peter',
rel: rel_peter
}, {
key: 'alex',
label: 'Alex',
rel: rel_alex
}];
var startX = 2048 / 2 - 400 - 60;
var y = 2600;
for (var i = 0; i < chars.length; i++) {
var c = chars[i];
var portrait = LK.getAsset(c.key, {
anchorX: 0.5,
anchorY: 1
});
portrait.x = startX + i * 270;
portrait.y = y;
game.addChild(portrait);
characterPortraits.push(portrait);
var label = new Text2(c.label + ': ' + c.rel + '%', {
size: 44,
fill: '#ffffff'
});
label.anchor.set(0.5, 0);
label.x = portrait.x;
label.y = y + 10;
game.addChild(label);
characterLabels.push(label);
}
// --- Ava: Add day, salary, money, baby count UI ---
if (dayText) game.removeChild(dayText);
if (salaryText) game.removeChild(salaryText);
if (moneyText) game.removeChild(moneyText);
if (babyText) game.removeChild(babyText);
dayText = new Text2('Gün: ' + dayCount, {
size: 54,
fill: '#fff'
});
dayText.anchor.set(0, 0);
dayText.x = 120;
dayText.y = 80;
game.addChild(dayText);
salaryText = new Text2('Maaş: $' + mikeSalary, {
size: 54,
fill: '#fff'
});
salaryText.anchor.set(0, 0);
salaryText.x = 120;
salaryText.y = 150;
game.addChild(salaryText);
moneyText = new Text2('Para: $' + mikeMoney, {
size: 54,
fill: '#fff'
});
moneyText.anchor.set(0, 0);
moneyText.x = 120;
moneyText.y = 220;
game.addChild(moneyText);
babyText = new Text2('Bebek: ' + mikeBabyCount, {
size: 54,
fill: '#fff'
});
babyText.anchor.set(0, 0);
babyText.x = 120;
babyText.y = 290;
game.addChild(babyText);
// --- Ava: Show relationship options if eligible ---
// Remove old relationship option buttons if any
if (game._relOptionBtns) {
for (var i = 0; i < game._relOptionBtns.length; i++) {
game.removeChild(game._relOptionBtns[i]);
}
}
game._relOptionBtns = [];
// --- Shop/Store UI (right side, vertical) ---
if (game._shopNodes) {
for (var i = 0; i < game._shopNodes.length; i++) {
game.removeChild(game._shopNodes[i]);
}
}
game._shopNodes = [];
var shopAssetIds = ['giselle', 'shop_item2', 'shop_item3', 'shop_item4'];
var shopPrices = [10000, 2500, 50000, 7500];
var shopLabels = ['Giselle', 'Whiskey', 'Villa', 'Eşya 4'];
var shopYStart = 1200; // moved even further down
var shopSpacing = 450; // even more space between items
// --- Villa state ---
if (typeof villaUnlocked === "undefined") villaUnlocked = false;
if (typeof whiskeyUnlocked === "undefined") whiskeyUnlocked = false;
for (var i = 0; i < 4; i++) {
var assetId = shopAssetIds[i];
var node = LK.getAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
node.x = 2048 - 120;
node.y = shopYStart + i * shopSpacing;
node.scale.x = node.scale.y = 1.0;
// Shop items are passive (dimmed, not interactive) until purchased, then active
if (shopItemStates[i]) {
node.alpha = 1.0;
node.interactive = false;
node.buttonMode = false;
} else {
node.alpha = 0.5;
node.interactive = true;
node.buttonMode = true;
}
// Price label (above the item)
var priceText = "";
if (i === 0) {
priceText = "$10,000";
} else if (i === 1) {
priceText = "$2,500";
} else if (i === 2) {
priceText = "$50,000";
} else if (i === 3) {
priceText = "$7,500";
}
var priceLabel = new Text2(priceText, {
size: 38,
fill: '#ffe066',
fontWeight: 'bold'
});
priceLabel.anchor.set(0.5, 1);
priceLabel.x = node.x;
priceLabel.y = node.y - node.height / 2 - 12;
game.addChild(priceLabel);
game._shopNodes.push(priceLabel);
// Name label (below the item)
var label = new Text2(shopLabels[i], {
size: 36,
fill: '#fff',
wordWrap: true,
wordWrapWidth: 180
});
label.anchor.set(0.5, 0);
label.x = node.x;
label.y = node.y + node.height / 2 + 10;
game.addChild(node);
game.addChild(label);
game._shopNodes.push(node, label);
// Giselle buy logic
if (i === 0 && !giselleUnlocked) {
node.down = function () {
if (mikeMoney >= 10000) {
mikeMoney -= 10000;
giselleUnlocked = true;
shopItemStates[0] = true;
// After purchase, make the item active (full alpha, not interactive)
node.alpha = 1.0;
node.interactive = false;
node.buttonMode = false;
updateBars();
createUI();
} else {
// Not enough money, flash red
tween(node, {
alpha: 0.3
}, {
duration: 120,
onFinish: function onFinish() {
tween(node, {
alpha: 1
}, {
duration: 120
});
}
});
}
};
}
// Whiskey buy logic
if (i === 1 && !whiskeyUnlocked) {
node.down = function () {
if (mikeMoney >= 2500) {
mikeMoney -= 2500;
whiskeyUnlocked = true;
shopItemStates[1] = true;
// After purchase, make the item active (full alpha, not interactive)
node.alpha = 1.0;
node.interactive = false;
node.buttonMode = false;
updateBars();
createUI();
} else {
// Not enough money, flash red
tween(node, {
alpha: 0.3
}, {
duration: 120,
onFinish: function onFinish() {
tween(node, {
alpha: 1
}, {
duration: 120
});
}
});
}
};
}
// Villa buy logic
if (i === 2 && !villaUnlocked) {
node.down = function () {
if (mikeMoney >= 50000) {
mikeMoney -= 50000;
villaUnlocked = true;
shopItemStates[2] = true;
// After purchase, make the item active (full alpha, not interactive)
node.alpha = 1.0;
node.interactive = false;
node.buttonMode = false;
updateBars();
createUI();
} else {
tween(node, {
alpha: 0.3
}, {
duration: 120,
onFinish: function onFinish() {
tween(node, {
alpha: 1
}, {
duration: 120
});
}
});
}
};
}
}
// Lisa
if (rel_lisa > 70 && !lisaPregnant) {
var btnLisa = new OptionButton();
btnLisa.setText("Lisa ile ilişkiye gir");
btnLisa.x = 2048 - 400;
btnLisa.y = 80;
btnLisa.setCallback(function () {
// %30 hamile kalma şansı
if (Math.random() < 0.3) {
lisaPregnant = true;
showStoryNode(currentNode);
}
});
game.addChild(btnLisa);
game._relOptionBtns.push(btnLisa);
}
// Rebecca
if (rel_rebecca > 70 && !rebeccaPregnant) {
var btnRebecca = new OptionButton();
btnRebecca.setText("Rebecca ile ilişkiye gir");
btnRebecca.x = 2048 - 400;
btnRebecca.y = 220;
btnRebecca.setCallback(function () {
if (Math.random() < 0.3) {
rebeccaPregnant = true;
showStoryNode(currentNode);
}
});
game.addChild(btnRebecca);
game._relOptionBtns.push(btnRebecca);
}
// Giselle
if (giselleUnlocked && !gisellePregnant) {
var btnGiselle = new OptionButton();
btnGiselle.setText("Giselle ile ilişkiye gir");
btnGiselle.x = 2048 - 400;
btnGiselle.y = 360;
btnGiselle.setCallback(function () {
if (Math.random() < 0.3) {
gisellePregnant = true;
showStoryNode(currentNode);
}
});
game.addChild(btnGiselle);
game._relOptionBtns.push(btnGiselle);
}
}
function updateBars() {
if (typeof villaUnlocked !== "undefined" && villaUnlocked && bar_happy < 80) {
bar_happy = 80;
}
barNodes['happy'].setValue(bar_happy);
barNodes['honest'].setValue(bar_honest);
barNodes['lust'].setValue(bar_lust);
barNodes['betray'].setValue(bar_betray);
// Bar isimleri ve yüzdeleri birlikte güncellensin
barNodes['happy'].label.setText('Mutluluk (' + bar_happy + '%)');
barNodes['honest'].label.setText('Dürüstlük (' + bar_honest + '%)');
barNodes['lust'].label.setText('Şehvet (' + bar_lust + '%)');
barNodes['betray'].label.setText('İhanet (' + bar_betray + '%)');
// Karakter ilişki dereceleri güncellensin
var rels = [rel_lisa, rel_rebecca, rel_peter, rel_alex];
var _loop = function _loop() {
names = ['Lisa', 'Rebecca', 'Peter', 'Alex'];
label = characterLabels[i];
prevText = label.text;
newText = names[i] + ': ' + rels[i] + '%'; // Değer değiştiyse animasyon başlat
if (prevText !== newText) {
// Son değeri bul
prevVal = 0;
match = prevText && prevText.match(/: (\-?\d+)%/);
if (match) prevVal = parseInt(match[1]);
newVal = rels[i]; // Pozitif veya negatif değişim: sadece etkilenen karakter titresin
if (newVal > prevVal || newVal < prevVal) {
// Sadece ilişki değeri değişen karakter titresin
portrait = characterPortraits[i];
if (portrait) {
var _doShakeChar = function doShakeChar() {
if (!portrait.parent || shakeCount >= 6) {
// Titreme bitti, orijinal konuma dön
portrait.x = origX;
portrait.y = origY;
return;
}
var dx = (Math.random() - 0.5) * 16;
var dy = (Math.random() - 0.5) * 10;
tween(portrait, {
x: origX + dx,
y: origY + dy
}, {
duration: 50,
easing: tween.linear,
onFinish: function onFinish() {
tween(portrait, {
x: origX,
y: origY
}, {
duration: 50,
easing: tween.linear,
onFinish: function onFinish() {
shakeCount++;
LK.setTimeout(_doShakeChar, 10);
}
});
}
});
};
// Titreme animasyonu uygula
origX = portrait.x;
origY = portrait.y;
shakeCount = 0;
_doShakeChar();
}
}
if (newVal > prevVal) {
if (label.style) label.style.fill = '#00ff00';
tween(label, {
alpha: 0.3
}, {
duration: 120,
easing: tween.linear,
onFinish: function (lbl) {
tween(lbl, {
alpha: 1
}, {
duration: 120,
easing: tween.linear,
onFinish: function (lbl2) {
if (lbl2.style) lbl2.style.fill = '#ffffff';
}.bind(null, label)
});
}.bind(null, label)
});
} else if (newVal < prevVal) {
if (label.style) label.style.fill = '#ff2222';
tween(label, {
alpha: 0.3
}, {
duration: 120,
easing: tween.linear,
onFinish: function (lbl) {
tween(lbl, {
alpha: 1
}, {
duration: 120,
easing: tween.linear,
onFinish: function (lbl2) {
if (lbl2.style) lbl2.style.fill = '#ffffff';
}.bind(null, label)
});
}.bind(null, label)
});
}
}
label.setText(newText);
},
names,
label,
prevText,
newText,
prevVal,
match,
newVal,
portrait,
origX,
origY,
shakeCount;
for (var i = 0; i < characterLabels.length; i++) {
_loop();
}
// --- Ava: Update day, salary, money, baby count UI ---
if (dayText) dayText.setText('Gün: ' + dayCount);
if (salaryText) salaryText.setText('Maaş: $' + mikeSalary);
if (moneyText) moneyText.setText('Para: $' + mikeMoney);
if (babyText) babyText.setText('Bebek: ' + mikeBabyCount);
// Refresh relationship option buttons
if (typeof createUI === "function") {
// Only refresh if UI is visible (avoid infinite loop)
if (game && typeof game._relOptionBtns !== "undefined") {
createUI();
}
}
}
function showStoryNode(idx) {
// Remove old option buttons
for (var i = 0; i < optionButtons.length; i++) {
game.removeChild(optionButtons[i]);
}
optionButtons = [];
// Dramatic choice injection: if turnCount >= nextDramaticTurn, show dramatic choice instead
if (typeof nextDramaticTurn !== "undefined" && turnCount >= nextDramaticTurn) {
showDramaticChoice();
return;
}
var node = story[idx];
// Portrait
if (portraitNode) {
if (node.portrait && LK.getAsset(node.portrait, {})) {
portraitNode.texture = LK.getAsset(node.portrait, {}).texture;
}
// Mood-based tint or background for Lisa, Rebecca, Mike, Peter, Alex
if (node.mood && (node.portrait === "lisa" || node.portrait === "rebecca" || node.portrait === "mike" || node.portrait === "peter" || node.portrait === "alex")) {
// Mood to tint mapping
var moodTints = {
happy: 0x7ed321,
sad: 0x4a90e2,
angry: 0xd0021b,
neutral: 0xffffff
};
var tint = moodTints[node.mood] !== undefined ? moodTints[node.mood] : 0xffffff;
portraitNode.tint = tint;
} else {
portraitNode.tint = 0xffffff;
}
// Remove any previous related character portrait
if (game.relatedPortraitNode) {
game.removeChild(game.relatedPortraitNode);
game.relatedPortraitNode = null;
}
// If the node is about a character other than Mike, show that character next to Mike
if (node.portrait && node.portrait !== "mike" && (node.portrait === "lisa" || node.portrait === "rebecca" || node.portrait === "peter" || node.portrait === "alex")) {
var relatedPortrait = LK.getAsset(node.portrait, {
anchorX: 0.5,
anchorY: 0.5
});
// Place to the right of Mike, with a small gap
relatedPortrait.x = portraitNode.x + portraitNode.width / 2 + relatedPortrait.width / 2 + 40;
relatedPortrait.y = portraitNode.y;
// Mood tint for related portrait
if (node.mood) {
var moodTints = {
happy: 0x7ed321,
sad: 0x4a90e2,
angry: 0xd0021b,
neutral: 0xffffff
};
relatedPortrait.tint = moodTints[node.mood] !== undefined ? moodTints[node.mood] : 0xffffff;
} else {
relatedPortrait.tint = 0xffffff;
}
game.addChild(relatedPortrait);
game.relatedPortraitNode = relatedPortrait;
} else {
if (game.relatedPortraitNode) {
game.removeChild(game.relatedPortraitNode);
game.relatedPortraitNode = null;
}
}
}
// Speaker
if (speakerText) {
speakerText.setText(node.speaker ? node.speaker : '');
}
// Story text
if (storyText) {
// --- Hatırlatma ve Gölgeli Vicdan Mekanizması ---
// 1. Eğer bu node bir regretTrigger içeriyorsa ve geçmişte ilgili regretLabel ile bir seçim yapıldıysa, iç ses/rüya olarak göster
if (node.regretTrigger && pastChoices.indexOf(node.regretTrigger) !== -1) {
// Vicdan sahnesi: iç ses veya rüya efektiyle göster
var regretTexts = {
"lied": "Gece rüyanda, Lisa'nın sana 'Bana neden yalan söyledin?' dediğini duyuyorsun. Vicdanın sızlıyor.",
"betrayed_lisa": "Bir an için Lisa'nın gözlerinde hayal kırıklığını görüyorsun. İç sesin: 'Ona ihanet ettin.'",
"ignored_peter": "Peter'ın üzgün bakışları aklından çıkmıyor. İç sesin: 'Dostunu yalnız bıraktın.'"
};
var regretText = regretTexts[node.regretTrigger] || "Geçmişteki bir kararın gölgesi seni rahatsız ediyor.";
storyText.setText(regretText + "\n\n(" + node.text + ")");
// Fade efekt: metni kısa süreliğine yarı saydam göster
storyText.alpha = 0.5;
tween(storyText, {
alpha: 1
}, {
duration: 1200,
easing: tween.easeOut
});
} else if (
// Yalancı Hafıza: Eğer honest bar düşükse ve geçmişte yalan söylendiyse, yanlış hatırlama metni göster
bar_honest <= 30 && pastChoices.indexOf("lied") !== -1 && (node.id === "lisa_breakfast_mid" || node.id === "lisa_breakfast_high" || node.id === "lisa_breakfast_low")) {
// Yalancı hafıza: Oyuncuya yanlış bilgi ver
storyText.setText("Mike sanki o gün Lisa'ya doğruyu söylediğini hatırlıyordu... ama aslında yalan söylemişti.\n\n(" + node.text + ")");
storyText.alpha = 0.7;
tween(storyText, {
alpha: 1
}, {
duration: 1200,
easing: tween.easeOut
});
} else if (node.id === "lisa_breakfast_mid" && pastChoices.indexOf("lied") !== -1) {
storyText.setText("Lisa sana biraz mesafeli bakıyor. Geçmişteki yalanların etkisi sürüyor.");
} else {
storyText.setText(node.text);
}
}
// Option buttons
// --- Timed Choice Mechanism: If node.timedChoice is set, start a timer and auto-select if no choice is made ---
var timedChoiceTimeout = null;
var timedChoiceBar = null;
if (node.options && node.options.length > 0) {
// If previous timer exists, clear it
if (game._timedChoiceTimeout) {
LK.clearTimeout(game._timedChoiceTimeout);
game._timedChoiceTimeout = null;
}
if (game._timedChoiceBar) {
game.removeChild(game._timedChoiceBar);
game._timedChoiceBar = null;
}
// If this node is a crisis/timed scene, e.g. node.timedChoice: { seconds: 5, default: 1 }
var isTimed = node.timedChoice && typeof node.timedChoice.seconds === "number";
var timedSeconds = isTimed ? node.timedChoice.seconds : 0;
var timedDefault = isTimed ? typeof node.timedChoice["default"] === "number" ? node.timedChoice["default"] : 0 : 0;
var timedStart = Date.now();
var timedBarWidth = 900;
var timedBarHeight = 24;
var timedBarY = 1700 + node.options.length * 180 + 40;
// Option button creation
for (var i = 0; i < node.options.length; i++) {
var opt = node.options[i];
// --- Requirements check ---
var meetsReq = true;
if (opt.requirements) {
for (var key in opt.requirements) {
var val = opt.requirements[key];
// Check current bar/relationship value
var current = 0;
if (key === 'lisa') current = rel_lisa;else if (key === 'rebecca') current = rel_rebecca;else if (key === 'peter') current = rel_peter;else if (key === 'alex') current = rel_alex;else if (key === 'happy') current = bar_happy;else if (key === 'honest') current = bar_honest;else if (key === 'lust') current = bar_lust;else if (key === 'betray') current = bar_betray;
if (current < val) {
meetsReq = false;
break;
}
}
}
var btn = new OptionButton();
// --- Bilinmeyen Seçim Sistemi: option'a hiddenByBar eklendiyse ve bar yeterli değilse gizle ---
var showAsHidden = false;
if (opt.hiddenByBar) {
// hiddenByBar: { key: 'honest', min: 60 } veya { key: 'betray', min: 40 }
var barKey = opt.hiddenByBar.key;
var minVal = typeof opt.hiddenByBar.min === "number" ? opt.hiddenByBar.min : 0;
var currentVal = 0;
if (barKey === 'lisa') currentVal = rel_lisa;else if (barKey === 'rebecca') currentVal = rel_rebecca;else if (barKey === 'peter') currentVal = rel_peter;else if (barKey === 'alex') currentVal = rel_alex;else if (barKey === 'happy') currentVal = bar_happy;else if (barKey === 'honest') currentVal = bar_honest;else if (barKey === 'lust') currentVal = bar_lust;else if (barKey === 'betray') currentVal = bar_betray;
if (currentVal < minVal) showAsHidden = true;
}
if (showAsHidden) {
btn.setText("???");
btn.bg.tint = 0x888888;
btn.text.style.fill = '#bbbbbb';
btn.setCallback(function () {}); // No-op
} else {
btn.setText(opt.text);
// If requirements not met, disable and gray out
if (!meetsReq) {
btn.bg.tint = 0x888888;
btn.text.style.fill = '#bbbbbb';
btn.setCallback(function () {}); // No-op
} else {
btn.setCallback(function (opt, btnIdx) {
return function () {
// If a timed choice is running, clear the timer and bar
if (game._timedChoiceTimeout) {
LK.clearTimeout(game._timedChoiceTimeout);
game._timedChoiceTimeout = null;
}
if (game._timedChoiceBar) {
game.removeChild(game._timedChoiceBar);
game._timedChoiceBar = null;
}
applyEffects(opt.effects, opt.meta);
// Her zaman random bir sonraki soru seç, ama bar değerine göre uygun versiyonu seç
var available = [];
for (var j = 0; j < story.length; j++) {
if (story[j].options && story[j].options.length > 0) available.push(j);
}
if (available.length > 0) {
// getNextNode fonksiyonu ile uygun node'u seç
var nextIdx = getNextNode();
currentNode = nextIdx;
showStoryNode(currentNode);
} else {
// Oyun bitti, son ekranı göster
showEnding();
}
};
}(opt, i));
}
}
btn.x = 2048 / 2;
btn.y = 1700 + i * 180;
game.addChild(btn);
optionButtons.push(btn);
}
// If this is a timed choice, show a timer bar and auto-select after timeout
if (isTimed) {
// Create a timer bar (background and fill)
var barBg = LK.getAsset('bar_bg', {
anchorX: 0.5,
anchorY: 0.5
});
barBg.width = timedBarWidth;
barBg.height = timedBarHeight;
barBg.x = 2048 / 2;
barBg.y = timedBarY;
var barFill = LK.getAsset('bar_fill_betray', {
anchorX: 0.5,
anchorY: 0.5
});
barFill.width = timedBarWidth;
barFill.height = timedBarHeight;
barFill.x = 2048 / 2;
barFill.y = timedBarY;
// Add to game
game.addChild(barBg);
game.addChild(barFill);
// Store for cleanup
game._timedChoiceBar = barBg;
game._timedChoiceBarFill = barFill;
// Animate the bar fill
var updateTimerBar = function updateTimerBar() {
var elapsed = (Date.now() - timedStart) / 1000;
var remain = Math.max(0, timedSeconds - elapsed);
var ratio = remain / timedSeconds;
barFill.width = timedBarWidth * ratio;
if (ratio <= 0) {
barFill.width = 0;
}
};
// Per-frame update for timer bar
var timerBarInterval = LK.setInterval(function () {
if (!game._timedChoiceBarFill) {
LK.clearInterval(timerBarInterval);
return;
}
updateTimerBar();
}, 50);
// Timeout: auto-select default option
game._timedChoiceTimeout = LK.setTimeout(function () {
// Only trigger if still on this node
if (game._timedChoiceBar) {
// Simulate click on default option
if (optionButtons[timedDefault] && typeof optionButtons[timedDefault].down === "function") {
optionButtons[timedDefault].down();
}
// Clean up timer bar
if (game._timedChoiceBar) {
game.removeChild(game._timedChoiceBar);
game._timedChoiceBar = null;
}
if (game._timedChoiceBarFill) {
game.removeChild(game._timedChoiceBarFill);
game._timedChoiceBarFill = null;
}
LK.clearInterval(timerBarInterval);
game._timedChoiceTimeout = null;
}
}, timedSeconds * 1000);
}
}
}
function applyEffects(effects, meta) {
if (!effects) return;
// --- Memory mechanic: record important choices ---
// Example: If the player kisses Lisa, lies to Rebecca, etc.
// We'll record meta.memoryLabel if present, otherwise try to infer from meta/type
if (meta && meta.memoryLabel) {
pastChoices.push(meta.memoryLabel);
} else if (meta && meta.type === "lie") {
pastChoices.push("lied");
// Regretful: lying is a regret
} else if (meta && meta.type === "truth") {
pastChoices.push("told_truth");
}
// Regretful: betray Lisa
if (typeof effects.lisa === 'number' && effects.lisa < 0 && typeof effects.betray === 'number' && effects.betray > 0) {
pastChoices.push("betrayed_lisa");
}
// Regretful: ignore Peter
if (typeof effects.peter === 'number' && effects.peter < 0 && meta && meta.ignoreRegret) {
pastChoices.push("ignored_peter");
}
// Sadece yüzde 1 artıp azalsın
if (typeof effects.lisa === 'number') rel_lisa = Math.max(0, Math.min(100, rel_lisa + (effects.lisa > 0 ? 1 : effects.lisa < 0 ? -1 : 0)));
if (typeof effects.rebecca === 'number') rel_rebecca = Math.max(0, Math.min(100, rel_rebecca + (effects.rebecca > 0 ? 1 : effects.rebecca < 0 ? -1 : 0)));
if (typeof effects.peter === 'number') rel_peter = Math.max(0, Math.min(100, rel_peter + (effects.peter > 0 ? 1 : effects.peter < 0 ? -1 : 0)));
if (typeof effects.alex === 'number') rel_alex = Math.max(0, Math.min(100, rel_alex + (effects.alex > 0 ? 1 : effects.alex < 0 ? -1 : 0)));
if (typeof effects.happy === 'number') {
bar_happy = Math.max(0, Math.min(100, bar_happy + (effects.happy > 0 ? 1 : effects.happy < 0 ? -1 : 0)));
if (typeof villaUnlocked !== "undefined" && villaUnlocked && bar_happy < 80) {
bar_happy = 80;
}
}
if (typeof effects.honest === 'number') bar_honest = Math.max(0, Math.min(100, bar_honest + (effects.honest > 0 ? 1 : effects.honest < 0 ? -1 : 0)));
if (typeof effects.lust === 'number') bar_lust = Math.max(0, Math.min(100, bar_lust + (effects.lust > 0 ? 1 : effects.lust < 0 ? -1 : 0)));
if (typeof effects.betray === 'number') bar_betray = Math.max(0, Math.min(100, bar_betray + (effects.betray > 0 ? 1 : effects.betray < 0 ? -1 : 0)));
// --- Villa davet event: karakterle ilişkiyi %15 artır (etki zaten effects ile geliyor, ama burada ek bir kontrol de eklenebilir) ---
if (meta && meta.type === "villa_invite" && typeof meta.character === "string") {
if (meta.character === "lisa") rel_lisa = Math.min(100, rel_lisa + 15);
if (meta.character === "rebecca") rel_rebecca = Math.min(100, rel_rebecca + 15);
if (meta.character === "peter") rel_peter = Math.min(100, rel_peter + 15);
if (meta.character === "alex") rel_alex = Math.min(100, rel_alex + 15);
}
// --- Giselle para harcama ve hamilelik ---
if (meta && meta.type === "giselle_spend" && typeof meta.money === "number") {
mikeMoney = Math.max(0, mikeMoney + meta.money);
}
// --- Whiskey para harcama ---
if (meta && meta.type === "whiskey_spend" && typeof meta.money === "number") {
mikeMoney = Math.max(0, mikeMoney + meta.money);
}
if (meta && meta.type === "giselle_baby" && giselleUnlocked && !gisellePregnant) {
if (Math.random() < 0.3) {
gisellePregnant = true;
// Bebek doğumu bir sonraki günlerde gerçekleşecek
}
}
// --- Shadow bar logic: increase/decrease based on hidden triggers ---
// Betrayal, repeated lies, or negative choices increase shadow bar
if (meta && meta.type === "lie" || typeof effects.betray === 'number' && effects.betray > 0) {
bar_shadow = Math.max(0, Math.min(100, bar_shadow + 5));
}
// If player is honest or makes a positive choice, shadow bar may decrease
if (meta && meta.type === "truth" || typeof effects.honest === 'number' && effects.honest > 0) {
bar_shadow = Math.max(0, bar_shadow - 2);
}
// If player ignores Peter or Lisa (meta.ignoreRegret), shadow bar increases
if (meta && meta.ignoreRegret) {
bar_shadow = Math.max(0, Math.min(100, bar_shadow + 3));
}
// --- Honest bar penalty for repeated lies ---
if (meta && meta.type === "lie") {
// Lying reduces honest bar by 2 (or 1 if already low)
bar_honest = Math.max(0, bar_honest - (bar_honest > 10 ? 2 : 1));
}
// --- Relationship Cross Effects ---
applyCrossEffects(effects, meta);
updateBars();
// --- Turn-based trigger system ---
// Increase turn count on every choice
turnCount++;
// --- Ava: Advance time every 2 turns (1 day = 2 questions) ---
if (turnCount % 2 === 0) {
dayCount++;
// Mike maaş alır
mikeMoney += mikeSalary;
// Alex ile ilişki > 70 ise maaş +50
if (rel_alex > 70) {
mikeSalary += 50;
}
// Alex ile ilişki < 30 ise maaş -20
if (rel_alex < 30) {
mikeSalary = Math.max(0, mikeSalary - 20);
}
// Peter ile ilişki > 70 ise mutluluk +1
if (rel_peter > 70) {
bar_happy = Math.min(100, bar_happy + 1);
}
// Lisa hamile ise doğum (her gün %10 ihtimal)
if (lisaPregnant && Math.random() < 0.1) {
mikeBabyCount++;
lisaPregnant = false;
}
// Rebecca hamile ise doğum (her gün %10 ihtimal)
if (rebeccaPregnant && Math.random() < 0.1) {
mikeBabyCount++;
rebeccaPregnant = false;
}
// Giselle hamile ise doğum (her gün %10 ihtimal)
if (gisellePregnant && Math.random() < 0.1) {
mikeBabyCount++;
gisellePregnant = false;
}
// Save to storage
storage.mikeMoney = mikeMoney;
storage.mikeSalary = mikeSalary;
storage.mikeBabyCount = mikeBabyCount;
storage.dayCount = dayCount;
storage.lisaPregnant = lisaPregnant;
storage.rebeccaPregnant = rebeccaPregnant;
// Update UI
updateBars();
}
// --- Dış Etki Mekanizması: Lust bar 3 tur boyunca yüksekse otomatik karar ---
// Son 3 turdaki lust bar değerlerini takip et
if (!flags.lustHistory) flags.lustHistory = [];
flags.lustHistory.push(bar_lust);
if (flags.lustHistory.length > 3) flags.lustHistory.shift();
// Eğer son 3 turda lust barı 70 ve üzeriyse, otomatik bir karar tetiklenir (ör: irade kaybı)
if (flags.lustHistory.length === 3 && flags.lustHistory[0] >= 70 && flags.lustHistory[1] >= 70 && flags.lustHistory[2] >= 70 && !flags.lustAutoDecision) {
flags.lustAutoDecision = true;
// Oyuncunun kontrolü dışında bir olay: Rebecca ile yakınlaşma
if (storyText) {
storyText.setText("Mike, arzularına yenik düşüyor ve Rebecca'ya karşı koyamıyor. (Dış etki: İrade kaybı)");
storyText.alpha = 0.7;
tween(storyText, {
alpha: 1
}, {
duration: 1200,
easing: tween.easeOut
});
}
// Bar ve ilişkilerde otomatik değişiklikler
rel_rebecca = Math.min(100, rel_rebecca + 5);
bar_lust = Math.min(100, bar_lust + 5);
bar_betray = Math.min(100, bar_betray + 5);
updateBars();
// Sonraki node'a otomatik geçiş (Rebecca ile ilgili bir sahneye öncelik ver)
var rebeccaIdx = -1;
for (var i = 0; i < story.length; i++) {
if (story[i].portrait === "rebecca" && story[i].options && story[i].options.length > 0) {
rebeccaIdx = i;
break;
}
}
if (rebeccaIdx !== -1) {
currentNode = rebeccaIdx;
LK.setTimeout(function () {
showStoryNode(currentNode);
}, 1800);
return;
}
}
// Zamana bağlı özel rüya sahnesi tetikleyici örneği
if (turnCount > 15 && bar_lust > 60 && !flags["specialDreamTriggered"]) {
flags["specialDreamTriggered"] = true;
showEnding("Mike, arzularının peşinden sürüklendiği özel bir rüya görüyor. (Zamana bağlı özel sahne)");
return;
}
// --- Bar-based flag system ---
// Example: if betrayal bar reaches 80 or more, set betrayalUnlocked flag
if (bar_betray >= 80) {
flags["betrayalUnlocked"] = true;
}
if (bar_honest >= 90) {
flags["honestyMaster"] = true;
}
if (bar_lust >= 90) {
flags["lustHigh"] = true;
}
if (bar_happy >= 90) {
flags["happinessPeak"] = true;
}
if (rel_lisa >= 90) {
flags["lisaBond"] = true;
}
if (rel_rebecca >= 90) {
flags["rebeccaBond"] = true;
}
if (rel_peter >= 90) {
flags["peterBond"] = true;
}
if (rel_alex >= 90) {
flags["alexBond"] = true;
}
// --- Shadow bar event triggers (hidden, unexpected events) ---
if (!flags.shadow30 && bar_shadow >= 30) {
flags.shadow30 = true;
// Ani içsel monolog: Mike'ın öfke patlaması
if (storyText) {
storyText.setText("Mike'ın içinde bir öfke kabarıyor. (İç ses: 'Bazen her şeyi yakıp yıkmak istiyorum...')\n\n" + (storyText.text || ""));
storyText.alpha = 0.7;
tween(storyText, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeOut
});
}
}
if (!flags.shadow60 && bar_shadow >= 60) {
flags.shadow60 = true;
// Mike'ın beklenmedik bir şekilde bağırması (oyuncuya yansır)
if (storyText) {
storyText.setText("Mike aniden bağırıyor: 'YETER ARTIK!'\n\n" + (storyText.text || ""));
storyText.alpha = 0.7;
tween(storyText, {
alpha: 1
}, {
duration: 1000,
easing: tween.easeOut
});
}
// Portrait kırmızıya döner, kısa süreliğine
if (portraitNode) {
var oldTint = portraitNode.tint;
portraitNode.tint = 0xd0021b;
tween(portraitNode, {
tint: oldTint
}, {
duration: 1200,
easing: tween.easeOut
});
}
}
if (!flags.shadow90 && bar_shadow >= 90) {
flags.shadow90 = true;
// Mike'ın içsel çöküşü: iç ses, portre fade out
if (storyText) {
storyText.setText("Mike'ın zihni karanlığa gömülüyor. (İç ses: 'Artık kendimi tanıyamıyorum...')\n\n" + (storyText.text || ""));
storyText.alpha = 0.5;
tween(storyText, {
alpha: 1
}, {
duration: 1500,
easing: tween.easeOut
});
}
if (portraitNode) {
tween(portraitNode, {
alpha: 0.2
}, {
duration: 1500,
easing: tween.easeOut
});
}
}
// Check for fail/win conditions
if (bar_happy <= 0) {
showEnding('Mutluluk sıfırlandı. Mike depresyona girdi.');
return;
}
if (bar_honest <= 0) {
showEnding('Dürüstlük sıfırlandı. Mike yalanlarla dolu bir hayata saplandı.');
return;
}
if (bar_lust <= 0) {
showEnding('Şehvet sıfırlandı. Mike hayattan keyif alamıyor.');
return;
}
if (bar_betray >= 100) {
showEnding('İhanet %100 oldu. Mike ilişkilerini kaybetti.');
return;
}
}
// İlişki çaprazlama mekanizması: Lisa ile yakınlık artınca Rebecca kıskanır, Rebecca ile yakınlık artınca Lisa üzülür, vs.
function applyCrossEffects(effects, meta) {
// Lisa ile yakınlık artarsa Rebecca'nın ilişkisi biraz azalır (kıskançlık)
if (typeof effects.lisa === 'number' && effects.lisa > 0) {
// Lisa ile +1 yakınlık, Rebecca -1
rel_rebecca = Math.max(0, rel_rebecca - 1);
}
// Rebecca ile yakınlık artarsa Lisa'nın ilişkisi biraz azalır (kıskançlık)
if (typeof effects.rebecca === 'number' && effects.rebecca > 0) {
rel_lisa = Math.max(0, rel_lisa - 1);
}
// Lisa ile yakınlık azalırsa Rebecca biraz mutlu olur (rekabet)
if (typeof effects.lisa === 'number' && effects.lisa < 0) {
rel_rebecca = Math.min(100, rel_rebecca + 1);
}
// Rebecca ile yakınlık azalırsa Lisa biraz mutlu olur (rekabet)
if (typeof effects.rebecca === 'number' && effects.rebecca < 0) {
rel_lisa = Math.min(100, rel_lisa + 1);
}
// Betray (ihanet) barı artarsa Lisa ve Rebecca'nın ilişkisi biraz azalır
if (typeof effects.betray === 'number' && effects.betray > 0) {
rel_lisa = Math.max(0, rel_lisa - 1);
rel_rebecca = Math.max(0, rel_rebecca - 1);
}
// Lust barı çok artarsa (ör: Rebecca ile), Lisa'nın ilişkisi biraz azalır
if (typeof effects.lust === 'number' && effects.lust > 0) {
rel_lisa = Math.max(0, rel_lisa - 1);
}
// Happy barı çok azalırsa, tüm ilişkiler biraz azalır
if (typeof effects.happy === 'number' && effects.happy < 0) {
rel_lisa = Math.max(0, rel_lisa - 1);
rel_rebecca = Math.max(0, rel_rebecca - 1);
rel_peter = Math.max(0, rel_peter - 1);
rel_alex = Math.max(0, rel_alex - 1);
}
}
function showEnding(msg) {
// Remove option buttons
for (var i = 0; i < optionButtons.length; i++) {
game.removeChild(optionButtons[i]);
}
optionButtons = [];
// --- Animated, bar-specific game over ---
// Determine which bar triggered game over
var endingType = null;
if (typeof msg === "string") {
if (msg.indexOf("Mutluluk") !== -1) endingType = "happy";else if (msg.indexOf("Dürüstlük") !== -1) endingType = "honest";else if (msg.indexOf("Şehvet") !== -1) endingType = "lust";else if (msg.indexOf("İhanet") !== -1) endingType = "betray";
}
// Default: Mike portrait
var portraitKey = "mike";
var endingText = msg;
var mood = "sad";
var crossX = null;
// Custom portrait and text for each bar
if (endingType === "betray") {
// Mike gözaltına alınıyor
portraitKey = "mike";
endingText = "SON: Mike ihanetin bedelini ödedi ve gözaltına alındı.\n\nYeniden başlamak için ekrana dokunun.";
mood = "angry";
crossX = true;
} else if (endingType === "lust") {
// Lisa uzaklaşıyor
portraitKey = "lisa";
endingText = "SON: Lisa, Mike'ın tutkularının sönmesiyle uzaklaştı.\n\nYeniden başlamak için ekrana dokunun.";
mood = "sad";
crossX = true;
} else if (endingType === "happy") {
// Mike depresyona giriyor
portraitKey = "mike";
endingText = "SON: Mike mutluluğunu kaybetti ve depresyona girdi.\n\nYeniden başlamak için ekrana dokunun.";
mood = "sad";
crossX = false;
} else if (endingType === "honest") {
// Mike yalanlarla dolu bir hayata saplandı
portraitKey = "mike";
endingText = "SON: Mike dürüstlüğünü kaybetti, yalanlarla dolu bir hayata saplandı.\n\nYeniden başlamak için ekrana dokunun.";
mood = "angry";
crossX = true;
}
// Show ending text
if (storyText) {
if (endingText) {
storyText.setText(endingText);
} else if (msg) {
storyText.setText('SON: ' + msg + '\n\nYeniden başlamak için ekrana dokunun.');
} else {
storyText.setText('SON: Mike’ın hikayesi burada bitiyor.\n\nYeniden başlamak için ekrana dokunun.');
}
}
// Remove speaker
if (speakerText) speakerText.setText('');
// Animate portrait: change to relevant character, mood tint, fade out, and cross if needed
if (portraitNode) {
// Change portrait image
if (LK.getAsset(portraitKey, {})) {
portraitNode.texture = LK.getAsset(portraitKey, {}).texture;
}
// Mood-based tint
var moodTints = {
happy: 0x7ed321,
sad: 0x4a90e2,
angry: 0xd0021b,
neutral: 0xffffff
};
var tint = moodTints[mood] !== undefined ? moodTints[mood] : 0xffffff;
portraitNode.tint = tint;
// Animate: fade out after 1.2s
tween(portraitNode, {
alpha: 0.3
}, {
duration: 1200,
easing: tween.easeOut
});
// If crossX, show a red cross over portrait
if (crossX) {
// Create a red cross using two rectangles (since we can't draw lines)
var cross1 = LK.getAsset('bar_fill_betray', {
anchorX: 0.5,
anchorY: 0.5
});
var cross2 = LK.getAsset('bar_fill_betray', {
anchorX: 0.5,
anchorY: 0.5
});
// Set size and rotation for cross
var size = Math.max(portraitNode.width, portraitNode.height) * 0.9;
cross1.width = size;
cross1.height = 24;
cross2.width = size;
cross2.height = 24;
cross1.rotation = Math.PI / 4;
cross2.rotation = -Math.PI / 4;
cross1.alpha = 0.85;
cross2.alpha = 0.85;
cross1.x = portraitNode.x;
cross1.y = portraitNode.y;
cross2.x = portraitNode.x;
cross2.y = portraitNode.y;
cross1.zIndex = 100;
cross2.zIndex = 100;
game.addChild(cross1);
game.addChild(cross2);
// Animate cross: fade in, then fade out after 1.2s
cross1.alpha = 0;
cross2.alpha = 0;
tween(cross1, {
alpha: 0.85
}, {
duration: 400,
easing: tween.easeOut
});
tween(cross2, {
alpha: 0.85
}, {
duration: 400,
easing: tween.easeOut
});
// Fade out after 1.2s
LK.setTimeout(function () {
tween(cross1, {
alpha: 0
}, {
duration: 600,
easing: tween.easeOut
});
tween(cross2, {
alpha: 0
}, {
duration: 600,
easing: tween.easeOut
});
LK.setTimeout(function () {
game.removeChild(cross1);
game.removeChild(cross2);
}, 700);
}, 1200);
}
}
// Add restart handler
game.down = function (x, y, obj) {
game.down = null;
restartGame();
};
}
function restartGame() {
resetGameState();
updateBars();
showStoryNode(currentNode);
// Remove restart handler
game.down = null;
}
// --- Start Game ---
resetGameState();
createUI();
updateBars();
showStoryNode(currentNode);
// --- No dragging or move events needed for this game ---
// --- Game update (not used, but required for LK) ---
game.update = function () {
// No per-frame logic needed
};
Boss Man head. In-Game asset. 2d. High contrast. No shadows
Housewife Head. In-Game asset. 2d. High contrast. No shadows
Blonde Handsome Man. In-Game asset. 2d. High contrast. No shadows
handsome, black hair, goat beard man head. In-Game asset. 2d. High contrast. No shadows
sexy ginger woman head In-Game asset. 2d. High contrast. No shadows
briefcase. In-Game asset. 2d. High contrast. No shadows
soccer ball. In-Game asset. 2d. High contrast. No shadows
flame heart. In-Game asset. 2d. High contrast. No shadows
motorcycle. In-Game asset. 2d. High contrast. No shadows
limuzin. In-Game asset. 2d. High contrast. No shadows
Black popart background. Only dark colors. Lots of pop art reference In-Game asset. 2d. High contrast. No shadows
Sexy beautiful French Woman face In-Game asset. 2d. High contrast. No shadows
German Shepard face. realistic In-Game asset. 2d. High contrast. No shadows
realistic villa. In-Game asset. 2d. High contrast. No shadows