User prompt
stın alınan eşyaları daha aşağı indir. Ayrıca aralarını biraz aç. Ve fiyatlarını da üzerlerine yaz
User prompt
şimdi biriken para ile bir şeyler satın alabilelim. ekranın sağ tarafına dikey şekilde dört adet yeni asset koy. İlki Giselle adında bir kadın. 10000 Dolar fiyatı. Giselle'i satın alınca o da hikayeye dahil olacak ve 20 soru ekleyelim sadece Giselle için. Hep para harcamak isteyecek Giselle. Giselle'de bebek sahibi olabilecek tıpkı Lisa ve Rebecca'da olan sistemin aynısı. Giselle satın alınmadan Giselle'in sorularını gösterme sakın. Giselle satın alındıktan sonra arada Giselle'in soruları da çıkacak. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Daha çok soru ekleyelim. Bir de aynı soru art arda gelmesin. en az 20 sorudan sonra yeniden gelsin
User prompt
imdi zaman ekleyelim oyuna. Her iki soru bir gün olsun. Lisa ve Rebecca ile ilişki 70'in üzerine çıkınca ilişkiye girme seçeneği çıksın ve %30 ihtimalle hamile kalsın. Mike'ın kaç bebeği var sayacı da olsun. Ayrınca Mike her gün para kazansın. 100 dolar maaş ile başlasın. Alex ile aralarının %70'in üzerinde olduğu her gün sonu Mike'ın maaşı 50 dolar artsın. Eğer Alex ile ilişkisi %30'un altına düşerse her düşük olduğu gün için 20 dolar azalsın. Mike'ın güncel maaşı ve toplam parası da yazsın ekranda. Mike'ın Peter ile arasının %70'in üstünde olduğu her gün için Mutluluk 1 artsın. ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Please fix the bug: 'self.setAsset is not a function' in or related to this line: 'self.setAsset('bg_car');' Line Number: 42
User prompt
şimdi arka planda sağdan sola ilerleyip ekrandan çıkacak pasif araba, iş çantası, ateşli kalp, futbol topu ve motor olarak 5 ayrı asset tanımlayalım. Pasif olsunlar ve tamamen arkaplan için ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
asset olarak ata. Ben değiştirebileyim
User prompt
oyuna bacground asseti atar mısın
User prompt
arkaplan asseti atar mısın
User prompt
ya sadece ilişki değeri değişen karakter titresin. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Hepsi yanıp sönüyor. En iyisi tamamen kaldır bu maske olayını. Etkilenen titresin ve dursun sadece
User prompt
Arkadaşım altta asset yeşil ya da kırmızı maske alıp sönecek. Sadece etkilenen karakterin asseti olacak. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'Cannot set properties of undefined (setting 'fill')' in or related to this line: 'label.style.fill = '#00ff00';' Line Number: 1814
User prompt
Şimdi yukarıdaki Mike'ın ve Karakterin asset'i hafif hareket etsin titreyerek. En altta Karakterler sonuca göre ilişki değeri değişirken pozitif ise yeşil yanıp sönsün negatif ise kırmızı yanıp sönsün ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Mike'ın görüntüsünün altında yazan karakter ismini ve olayı biraz daha aşağı alalım. Mike ve Karakteri ekrana ortalayalım
User prompt
Please fix the bug: 'Uncaught TypeError: tween.create is not a function' in or related to this line: 'tween.create(storyText).to({' Line Number: 2191
User prompt
Çarpıcı Seçimler Modülünde seçenekler siyah arka plan üzerine beyaz yazı olsun.
User prompt
Please fix the bug: 'Script error.' in or related to this line: 'tween(b, {' Line Number: 739 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Çarpıcı seçim modülü devreye girdiğinde seçenekler iki yeni buton ile sunulsun.Büyük ve dikkat çekici olsun ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
ekran shadow oluyor. seçenekler gri oluyor ve seçim yaptırmıyor. Lütfen düzeltir misin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
hala görünmüyor. Tamamen görünür yap. Seçmeme izin versin. Hatta o durumlarda iki seçim de büyüsün daha fazla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
çARPICI SEÇİMLERDE ŞIKLAR EKRANDA GÖRÜNMÜYOR. dÜZELTİR MİSİN
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'btn.text.style.fill = '#fff';' Line Number: 703
User prompt
yA BU HATA VEREN KISMI ÇIKAR OYUNDAN TWEEN.CREATE NEYSE ARTIK
User prompt
Please fix the bug: 'Uncaught TypeError: tween.to is not a function' in or related to this line: 'tween.to(shadow, {' Line Number: 677
/**** * Plugins ****/ var tween = LK.import("@upit/tween.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; }); // 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 ****/ // --- Dramatic Choice (Çarpıcı Seçim) System --- // Çarpıcı seçimler: her 4-6 sahnede bir, yüksek risk/ödül, animasyonlu, barları büyük oranda etkiler 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; shadow.zIndex = 99; game.addChild(shadow); game._dramaticShadow = shadow; tween.create(shadow).to({ alpha: 0.7 }, 400).start(); } // 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 = 0.0; tween.to(storyText, { alpha: 1 }, 400).start(); } // Dramatic option buttons: animated grow/shrink for (var i = 0; i < node.options.length; i++) { (function (opt, idx) { var btn = new OptionButton(); btn.setText(opt.text); btn.x = 2048 / 2; btn.y = 1700 + idx * 220; btn.scale.x = 0.7; btn.scale.y = 0.7; btn.alpha = 0.0; btn.bg.tint = 0x222222; btn.text.style.fill = '#fff'; btn.zIndex = 100; game.addChild(btn); optionButtons.push(btn); // Animate: grow in, pulse tween.to(btn, { alpha: 1, scaleX: 1.1, scaleY: 1.1 }, 300).start().onComplete(function () { tween.to(btn, { scaleX: 1.0, scaleY: 1.0 }, 200).start(); }); btn.setCallback(function () { // Remove shadow overlay if (game._dramaticShadow) { tween.to(game._dramaticShadow, { alpha: 0 }, 300).start().onComplete(function () { game.removeChild(game._dramaticShadow); game._dramaticShadow = null; }); } // Remove buttons with fade for (var j = 0; j < optionButtons.length; j++) { (function (b) { tween.to(b, { alpha: 0 }, 200).start().onComplete(function () { 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); }); })(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 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 }] }, // 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; // Current story node var currentNode = 0; // --- 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 = []; // --- Functions --- // getNextNode: uygun story node'unu bar değerine göre seç 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; } // Her bir node'u sırayla kontrol et, barCheck varsa uygun olanı döndür for (var k = 0; k < indices.length; k++) { var idx = indices[k]; var node = story[idx]; 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) { return idx; } } else { // barCheck yoksa, her zaman seçilebilir return idx; } } // Hiçbiri uygun değilse ilk node'u döndür 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; } } function createUI() { // Portrait if (portraitNode) game.removeChild(portraitNode); portraitNode = LK.getAsset('mike', { anchorX: 0.5, anchorY: 0.5 }); portraitNode.x = 2048 / 2; portraitNode.y = 400; game.addChild(portraitNode); // Speaker 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 = 700; game.addChild(speakerText); // Story text 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 = 800; 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); } } function updateBars() { 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]; for (var i = 0; i < characterLabels.length; i++) { var names = ['Lisa', 'Rebecca', 'Peter', 'Alex']; characterLabels[i].setText(names[i] + ': ' + rels[i] + '%'); } } 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.create(storyText).to({ alpha: 1 }, 1200).start(); } 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.create(storyText).to({ alpha: 1 }, 1200).start(); } 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 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))); // --- 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++; // --- 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.create(storyText).to({ alpha: 1 }, 1200).start(); } // 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.create(storyText).to({ alpha: 1 }, 1000).start(); } } 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.create(storyText).to({ alpha: 1 }, 1000).start(); } // Portrait kırmızıya döner, kısa süreliğine if (portraitNode) { var oldTint = portraitNode.tint; portraitNode.tint = 0xd0021b; tween.create(portraitNode).to({ tint: oldTint }, 1200).start(); } } 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.create(storyText).to({ alpha: 1 }, 1500).start(); } if (portraitNode) { tween.create(portraitNode).to({ alpha: 0.2 }, 1500).start(); } } // 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.create(portraitNode).to({ alpha: 0.3 }, 1200).start(); // 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.create(cross1).to({ alpha: 0.85 }, 400).start(); tween.create(cross2).to({ alpha: 0.85 }, 400).start(); // Fade out after 1.2s LK.setTimeout(function () { tween.create(cross1).to({ alpha: 0 }, 600).start(); tween.create(cross2).to({ alpha: 0 }, 600).start(); 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");
/****
* 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;
});
// 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
****/
// --- Dramatic Choice (Çarpıcı Seçim) System ---
// Çarpıcı seçimler: her 4-6 sahnede bir, yüksek risk/ödül, animasyonlu, barları büyük oranda etkiler
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;
shadow.zIndex = 99;
game.addChild(shadow);
game._dramaticShadow = shadow;
tween.create(shadow).to({
alpha: 0.7
}, 400).start();
}
// 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 = 0.0;
tween.to(storyText, {
alpha: 1
}, 400).start();
}
// Dramatic option buttons: animated grow/shrink
for (var i = 0; i < node.options.length; i++) {
(function (opt, idx) {
var btn = new OptionButton();
btn.setText(opt.text);
btn.x = 2048 / 2;
btn.y = 1700 + idx * 220;
btn.scale.x = 0.7;
btn.scale.y = 0.7;
btn.alpha = 0.0;
btn.bg.tint = 0x222222;
btn.text.style.fill = '#fff';
btn.zIndex = 100;
game.addChild(btn);
optionButtons.push(btn);
// Animate: grow in, pulse
tween.to(btn, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, 300).start().onComplete(function () {
tween.to(btn, {
scaleX: 1.0,
scaleY: 1.0
}, 200).start();
});
btn.setCallback(function () {
// Remove shadow overlay
if (game._dramaticShadow) {
tween.to(game._dramaticShadow, {
alpha: 0
}, 300).start().onComplete(function () {
game.removeChild(game._dramaticShadow);
game._dramaticShadow = null;
});
}
// Remove buttons with fade
for (var j = 0; j < optionButtons.length; j++) {
(function (b) {
tween.to(b, {
alpha: 0
}, 200).start().onComplete(function () {
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);
});
})(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
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
}]
},
// 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;
// Current story node
var currentNode = 0;
// --- 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 = [];
// --- Functions ---
// getNextNode: uygun story node'unu bar değerine göre seç
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;
}
// Her bir node'u sırayla kontrol et, barCheck varsa uygun olanı döndür
for (var k = 0; k < indices.length; k++) {
var idx = indices[k];
var node = story[idx];
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) {
return idx;
}
} else {
// barCheck yoksa, her zaman seçilebilir
return idx;
}
}
// Hiçbiri uygun değilse ilk node'u döndür
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;
}
}
function createUI() {
// Portrait
if (portraitNode) game.removeChild(portraitNode);
portraitNode = LK.getAsset('mike', {
anchorX: 0.5,
anchorY: 0.5
});
portraitNode.x = 2048 / 2;
portraitNode.y = 400;
game.addChild(portraitNode);
// Speaker
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 = 700;
game.addChild(speakerText);
// Story text
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 = 800;
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);
}
}
function updateBars() {
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];
for (var i = 0; i < characterLabels.length; i++) {
var names = ['Lisa', 'Rebecca', 'Peter', 'Alex'];
characterLabels[i].setText(names[i] + ': ' + rels[i] + '%');
}
}
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.create(storyText).to({
alpha: 1
}, 1200).start();
} 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.create(storyText).to({
alpha: 1
}, 1200).start();
} 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 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)));
// --- 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++;
// --- 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.create(storyText).to({
alpha: 1
}, 1200).start();
}
// 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.create(storyText).to({
alpha: 1
}, 1000).start();
}
}
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.create(storyText).to({
alpha: 1
}, 1000).start();
}
// Portrait kırmızıya döner, kısa süreliğine
if (portraitNode) {
var oldTint = portraitNode.tint;
portraitNode.tint = 0xd0021b;
tween.create(portraitNode).to({
tint: oldTint
}, 1200).start();
}
}
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.create(storyText).to({
alpha: 1
}, 1500).start();
}
if (portraitNode) {
tween.create(portraitNode).to({
alpha: 0.2
}, 1500).start();
}
}
// 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.create(portraitNode).to({
alpha: 0.3
}, 1200).start();
// 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.create(cross1).to({
alpha: 0.85
}, 400).start();
tween.create(cross2).to({
alpha: 0.85
}, 400).start();
// Fade out after 1.2s
LK.setTimeout(function () {
tween.create(cross1).to({
alpha: 0
}, 600).start();
tween.create(cross2).to({
alpha: 0
}, 600).start();
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