/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Achievement = Container.expand(function () {
var self = Container.call(this);
self.achievements = {
firstWin: {
unlocked: false,
name: 'First Victory',
description: 'Win your first race'
},
tenWins: {
unlocked: false,
name: 'Champion',
description: 'Win 10 races'
},
firstBreed: {
unlocked: false,
name: 'Breeder',
description: 'Breed your first horse'
},
millionaire: {
unlocked: false,
name: 'Millionaire',
description: 'Earn $1,000,000'
},
collector: {
unlocked: false,
name: 'Collector',
description: 'Own 10 horses'
},
trainer: {
unlocked: false,
name: 'Master Trainer',
description: 'Train horses 50 times'
},
speedster: {
unlocked: false,
name: 'Speed Demon',
description: 'Have a horse with 100+ speed'
},
endurance: {
unlocked: false,
name: 'Endurance Master',
description: 'Have a horse with 100+ stamina'
}
};
self.checkAchievements = function () {
// Check first win
if (!self.achievements.firstWin.unlocked && LK.getScore() >= 1) {
self.unlockAchievement('firstWin');
}
// Check ten wins
if (!self.achievements.tenWins.unlocked && LK.getScore() >= 10) {
self.unlockAchievement('tenWins');
}
// Check millionaire
if (!self.achievements.millionaire.unlocked && totalEarnings >= 1000000) {
self.unlockAchievement('millionaire');
}
// Check collector
if (!self.achievements.collector.unlocked && horses.length >= 10) {
self.unlockAchievement('collector');
}
// Check trainer
if (!self.achievements.trainer.unlocked && trainingCount >= 50) {
self.unlockAchievement('trainer');
}
};
self.unlockAchievement = function (id) {
self.achievements[id].unlocked = true;
// Flatten achievements for storage
var flatAchievements = {};
for (var key in self.achievements) {
flatAchievements[key + '_unlocked'] = self.achievements[key].unlocked;
flatAchievements[key + '_name'] = self.achievements[key].name;
flatAchievements[key + '_description'] = self.achievements[key].description;
}
storage.achievements = flatAchievements;
LK.effects.flashScreen(0xffd700, 500);
};
return self;
});
var Help = Container.expand(function () {
var self = Container.call(this);
self.currentSection = 'overview';
self.sections = ['overview', 'horses', 'racing', 'breeding', 'economy', 'tips'];
self.sectionButtons = [];
self.contentText = [];
self.titleText = null;
self.backText = null;
self.helpContent = {
overview: {
en: "Welcome to Thoroughbred Legacy!\n\nThis is an elite horse racing simulation where you manage a stable of champion horses. Your goal is to build the most successful racing empire by breeding, training, and racing horses to victory.\n\nKey Features:\n• Breed and train thoroughbred horses\n• Compete in prestigious tournaments\n• Manage your stable's finances\n• Unlock achievements and upgrades\n• Experience dynamic weather effects",
tr: "Safkan Mirası'na Hoş Geldiniz!\n\nBu, şampiyon atlardan oluşan bir ahır yönettiğiniz elit bir at yarışı simülasyonudur. Amacınız, atları üreterek, eğiterek ve yarıştırarak en başarılı yarış imparatorluğunu kurmaktır.\n\nAna Özellikler:\n• Safkan atları üretin ve eğitin\n• Prestijli turnuvalarda yarışın\n• Ahırınızın finansmanını yönetin\n• Başarıları ve gelişmeleri açın\n• Dinamik hava etkilerini deneyimleyin",
ru: "Добро пожаловать в Наследие Чистокровных!\n\nЭто элитная симуляция скачек, где вы управляете конюшней чемпионских лошадей. Ваша цель - построить самую успешную скаковую империю, разводя, тренируя и участвуя в скачках.\n\nОсновные функции:\n• Разводите и тренируйте чистокровных лошадей\n• Участвуйте в престижных турнирах\n• Управляйте финансами конюшни\n• Открывайте достижения и улучшения\n• Испытайте динамические погодные эффекты"
},
horses: {
en: "Horse Management:\n\nEach horse has unique statistics:\n• Speed - Determines racing velocity\n• Stamina - Affects endurance in races\n• Temperament - Influences consistency\n• Energy - Current condition level\n• Age - Affects performance over time\n\nHorse Care:\n• Feed horses to restore energy\n• Visit veterinarian for health boosts\n• Train regularly to improve stats\n• Rest horses between races\n• Monitor aging effects on performance",
tr: "At Yönetimi:\n\nHer atın benzersiz istatistikleri vardır:\n• Hız - Yarış hızını belirler\n• Dayanıklılık - Yarışlarda dayanıklılığı etkiler\n• Mizaç - Tutarlılığı etkiler\n• Enerji - Mevcut kondisyon seviyesi\n• Yaş - Zaman içinde performansı etkiler\n\nAt Bakımı:\n• Enerjiyi yenilemek için atları besleyin\n• Sağlık artışı için veterinere gidin\n• İstatistikleri geliştirmek için düzenli eğitin\n• Yarışlar arasında atları dinlendirin\n• Yaşlanmanın performans üzerindeki etkilerini izleyin",
ru: "Управление лошадьми:\n\nКаждая лошадь имеет уникальную статистику:\n• Скорость - Определяет скорость в гонке\n• Выносливость - Влияет на выносливость в гонках\n• Темперамент - Влияет на стабильность\n• Энергия - Текущий уровень состояния\n• Возраст - Влияет на производительность со временем\n\nУход за лошадьми:\n• Кормите лошадей для восстановления энергии\n• Посещайте ветеринара для укрепления здоровья\n• Регулярно тренируйтесь для улучшения статистики\n• Давайте лошадям отдыхать между гонками\n• Следите за влиянием старения на производительность"
},
racing: {
en: "Racing System:\n\nRace Types:\n• Quick races for immediate rewards\n• Tournament competitions for big prizes\n• Championship events for prestige\n\nRace Mechanics:\n• Weather affects horse performance\n• Energy levels impact race results\n• Horse stats determine speed potential\n• Random events add excitement\n\nStrategy Tips:\n• Choose well-rested horses\n• Consider weather conditions\n• Match horse strengths to race type\n• Manage energy carefully",
tr: "Yarış Sistemi:\n\nYarış Türleri:\n• Hızlı ödüller için hızlı yarışlar\n• Büyük ödüller için turnuva yarışmaları\n• Prestij için şampiyonluk etkinlikleri\n\nYarış Mekanikleri:\n• Hava durumu at performansını etkiler\n• Enerji seviyeleri yarış sonuçlarını etkiler\n• At istatistikleri hız potansiyelini belirler\n• Rastgele olaylar heyecan katar\n\nStrateji İpuçları:\n• İyi dinlenmiş atları seçin\n• Hava koşullarını göz önünde bulundurun\n• At güçlerini yarış türüne uygun hale getirin\n• Enerjiyi dikkatli yönetin",
ru: "Система гонок:\n\nТипы гонок:\n• Быстрые гонки за немедленные награды\n• Турнирные соревнования за большие призы\n• Чемпионские события за престиж\n\nМеханика гонок:\n• Погода влияет на производительность лошадей\n• Уровни энергии влияют на результаты гонок\n• Статистика лошадей определяет скоростной потенциал\n• Случайные события добавляют волнения\n\nСтратегические советы:\n• Выбирайте отдохнувших лошадей\n• Учитывайте погодные условия\n• Сопоставляйте сильные стороны лошадей с типом гонки\n• Тщательно управляйте энергией"
},
breeding: {
en: "Breeding System:\n\nBreeding Basics:\n• Combine two horses to create offspring\n• Foals inherit parent characteristics\n• Stats are averaged with random variation\n• Better parents produce better foals\n\nBreeding Strategy:\n• Choose complementary parent stats\n• Consider age and performance history\n• Breed champions for superior offspring\n• Maintain genetic diversity\n\nBreeding Costs:\n• Breeding fee: $5,000\n• Veterinary care for pregnant mares\n• Training costs for young horses\n• Time investment for development",
tr: "Üretim Sistemi:\n\nÜretim Temelleri:\n• Yavru oluşturmak için iki atı birleştirin\n• Yavrular ebeveyn özelliklerini miras alır\n• İstatistikler rastgele varyasyonla ortalaması alınır\n• Daha iyi ebeveynler daha iyi yavrular üretir\n\nÜretim Stratejisi:\n• Tamamlayıcı ebeveyn istatistiklerini seçin\n• Yaş ve performans geçmişini göz önünde bulundurun\n• Üstün yavrular için şampiyonları üretin\n• Genetik çeşitliliği koruyun\n\nÜretim Maliyetleri:\n• Üretim ücreti: $5,000\n• Gebe kısraklar için veteriner bakımı\n• Genç atlar için eğitim maliyetleri\n• Gelişim için zaman yatırımı",
ru: "Система разведения:\n\nОсновы разведения:\n• Объедините двух лошадей для создания потомства\n• Жеребята наследуют характеристики родителей\n• Статистика усредняется со случайными вариациями\n• Лучшие родители производят лучших жеребят\n\nСтратегия разведения:\n• Выбирайте дополняющие родительские статистики\n• Учитывайте возраст и историю производительности\n• Разводите чемпионов для превосходного потомства\n• Поддерживайте генетическое разнообразие\n\nЗатраты на разведение:\n• Плата за разведение: $5,000\n• Ветеринарный уход за беременными кобылами\n• Расходы на обучение молодых лошадей\n• Временные инвестиции для развития"
},
economy: {
en: "Economic Management:\n\nIncome Sources:\n• Race winnings (varies by competition)\n• Tournament prizes ($25k - $200k)\n• Breeding services to other stables\n• Selling trained horses\n\nExpenses:\n• Horse training ($1,000 per session)\n• Veterinary care ($1,000 - $5,000)\n• Feeding costs ($500 per meal)\n• Equipment upgrades ($10,000+)\n• Breeding fees ($5,000)\n\nFinancial Tips:\n• Maintain cash reserves for opportunities\n• Invest in profitable horses\n• Balance training costs with results\n• Consider long-term breeding investments",
tr: "Ekonomik Yönetim:\n\nGelir Kaynakları:\n• Yarış kazançları (yarışmaya göre değişir)\n• Turnuva ödülleri ($25k - $200k)\n• Diğer ahırlara üretim hizmetleri\n• Eğitilmiş atları satma\n\nGiderler:\n• At eğitimi (seans başına $1,000)\n• Veteriner bakımı ($1,000 - $5,000)\n• Beslenme maliyetleri (öğün başına $500)\n• Ekipman geliştirmeleri ($10,000+)\n• Üretim ücretleri ($5,000)\n\nFinansal İpuçları:\n• Fırsatlar için nakit rezerv bulundurun\n• Karlı atlara yatırım yapın\n• Eğitim maliyetlerini sonuçlarla dengeleyin\n• Uzun vadeli üretim yatırımlarını düşünün",
ru: "Экономическое управление:\n\nИсточники дохода:\n• Выигрыши в гонках (варьируется в зависимости от соревнования)\n• Призы турниров ($25k - $200k)\n• Услуги разведения для других конюшен\n• Продажа обученных лошадей\n\nРасходы:\n• Тренировка лошадей ($1,000 за сессию)\n• Ветеринарная помощь ($1,000 - $5,000)\n• Расходы на кормление ($500 за прием пищи)\n• Обновления оборудования ($10,000+)\n• Плата за разведение ($5,000)\n\nФинансовые советы:\n• Поддерживайте денежные резервы для возможностей\n• Инвестируйте в прибыльных лошадей\n• Балансируйте затраты на обучение с результатами\n• Рассмотрите долгосрочные инвестиции в разведение"
},
tips: {
en: "Advanced Tips & Strategies:\n\nOptimal Training:\n• Train horses when energy is high\n• Focus on weak stats for balanced development\n• Don't overtrain - rest is important\n• Monitor age-related stat declines\n\nRace Strategy:\n• Save your best horses for tournaments\n• Consider weather effects on performance\n• Match horse types to race distances\n• Build experience gradually\n\nLong-term Success:\n• Invest in breeding superior bloodlines\n• Diversify your stable portfolio\n• Plan for horse retirement\n• Maintain steady income streams\n• Unlock all achievements for bonuses",
tr: "Gelişmiş İpuçları ve Stratejiler:\n\nOptimal Eğitim:\n• Enerji yüksekken atları eğitin\n• Dengeli gelişim için zayıf istatistiklere odaklanın\n• Aşırı eğitim yapmayın - dinlenme önemlidir\n• Yaşa bağlı istatistik düşüşlerini izleyin\n\nYarış Stratejisi:\n• En iyi atlarınızı turnuvalar için saklayın\n• Hava etkilerini performans üzerinde düşünün\n• At türlerini yarış mesafelerine uygun hale getirin\n• Deneyimi kademeli olarak artırın\n\nUzun vadeli Başarı:\n• Üstün kan hatlarını üretmeye yatırım yapın\n• Ahır portföyünüzü çeşitlendirin\n• At emekliliği için plan yapın\n• Sabit gelir akışları sürdürün\n• Bonuslar için tüm başarıları açın",
ru: "Продвинутые советы и стратегии:\n\nОптимальная тренировка:\n• Тренируйте лошадей при высокой энергии\n• Сосредоточьтесь на слабых статистиках для сбалансированного развития\n• Не перетренируйтесь - отдых важен\n• Следите за возрастными снижениями статистики\n\nСтратегия гонок:\n• Сохраните лучших лошадей для турниров\n• Учитывайте влияние погоды на производительность\n• Сопоставьте типы лошадей с дистанциями гонок\n• Постепенно накапливайте опыт\n\nДолгосрочный успех:\n• Инвестируйте в разведение превосходных родословных\n• Диверсифицируйте портфель конюшни\n• Планируйте выход лошадей на пенсию\n• Поддерживайте стабильные потоки доходов\n• Разблокируйте все достижения для бонусов"
}
};
self.setupUI = function () {
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
self.titleText = new Text2('', {
size: 80,
fill: '#ecf0f1'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 200;
self.addChild(self.titleText);
// Section buttons
for (var i = 0; i < self.sections.length; i++) {
var section = self.sections[i];
var sectionBtn = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 200 + i % 3 * 300,
y: 350 + Math.floor(i / 3) * 100
});
var sectionText = new Text2(section.toUpperCase(), {
size: 24,
fill: '#ffffff'
});
sectionText.anchor.set(0.5, 0.5);
sectionText.x = 200 + i % 3 * 300;
sectionText.y = 350 + Math.floor(i / 3) * 100;
sectionText.sectionId = section;
self.addChild(sectionText);
self.sectionButtons.push({
button: sectionBtn,
text: sectionText,
section: section,
x: 200 + i % 3 * 300,
y: 350 + Math.floor(i / 3) * 100
});
}
self.refreshContent();
self.backText = new Text2('', {
size: 45,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2500;
self.addChild(self.backText);
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2500
});
};
self.refreshContent = function () {
// Clear existing content
for (var i = 0; i < self.contentText.length; i++) {
if (self.contentText[i].destroy) {
self.contentText[i].destroy();
}
}
self.contentText = [];
var content = self.helpContent[self.currentSection][currentLanguage] || self.helpContent[self.currentSection]['en'];
var lines = content.split('\n');
var yPos = 600;
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
if (line.length === 0) {
yPos += 20;
continue;
}
// Handle long lines by wrapping text
var maxLineLength = 70;
if (line.length > maxLineLength && line.indexOf('•') !== 0) {
var words = line.split(' ');
var currentLine = '';
for (var w = 0; w < words.length; w++) {
if ((currentLine + words[w]).length > maxLineLength) {
if (currentLine.length > 0) {
var wrappedLine = new Text2(currentLine.trim(), {
size: 30,
fill: '#ffffff'
});
wrappedLine.anchor.set(0.5, 0.5);
wrappedLine.x = 1024;
wrappedLine.y = yPos;
self.addChild(wrappedLine);
self.contentText.push(wrappedLine);
yPos += 35;
}
currentLine = words[w] + ' ';
} else {
currentLine += words[w] + ' ';
}
}
if (currentLine.trim().length > 0) {
var finalLine = new Text2(currentLine.trim(), {
size: 30,
fill: '#ffffff'
});
finalLine.anchor.set(0.5, 0.5);
finalLine.x = 1024;
finalLine.y = yPos;
self.addChild(finalLine);
self.contentText.push(finalLine);
yPos += 35;
}
} else {
var fontSize = line.indexOf('•') === 0 ? 28 : line.indexOf(':') > 0 ? 34 : 30;
var textColor = line.indexOf(':') > 0 ? '#3498db' : '#ffffff';
var contentLine = new Text2(line, {
size: fontSize,
fill: textColor
});
contentLine.anchor.set(0.5, 0.5);
contentLine.x = 1024;
contentLine.y = yPos;
self.addChild(contentLine);
self.contentText.push(contentLine);
yPos += fontSize + 15;
}
}
};
self.updateLanguage = function () {
if (self.titleText) {
self.titleText.setText(translations[currentLanguage].help || 'HELP & GUIDE');
}
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'BACK');
}
self.refreshContent();
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check section buttons
for (var i = 0; i < self.sectionButtons.length; i++) {
var btn = self.sectionButtons[i];
if (localPos.x >= btn.x - 125 && localPos.x <= btn.x + 125 && localPos.y >= btn.y - 60 && localPos.y <= btn.y + 60) {
self.currentSection = btn.section;
self.refreshContent();
LK.getSound('buttonClick').play();
break;
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2440 && localPos.y <= 2560) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Horse = Container.expand(function (config) {
var self = Container.call(this);
config = config || {};
// Horse stats
self.name = config.name || 'Unnamed Horse';
self.speed = config.speed || Math.random() * 50 + 50;
self.stamina = config.stamina || Math.random() * 50 + 50;
self.temperament = config.temperament || Math.random() * 50 + 50;
self.age = config.age || 2;
self.raceWins = config.raceWins || 0;
self.value = config.value || 10000;
self.currentEnergy = 100;
self.maxEnergy = 100;
// Visual representation
var horseBody = self.attachAsset('horse', {
anchorX: 0.5,
anchorY: 0.5
});
var jockeySprite = self.attachAsset('jockey', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
});
// Racing properties
self.racePosition = 0;
self.raceSpeed = 0;
self.isRacing = false;
self.train = function (type) {
switch (type) {
case 'speed':
self.speed += Math.random() * 5 + 2;
break;
case 'stamina':
self.stamina += Math.random() * 5 + 2;
break;
case 'temperament':
self.temperament += Math.random() * 5 + 2;
break;
}
self.currentEnergy = Math.max(0, self.currentEnergy - 20);
};
self.rest = function () {
self.currentEnergy = Math.min(self.maxEnergy, self.currentEnergy + 30);
};
self.breed = function (partner) {
var offspring = new Horse({
speed: (self.speed + partner.speed) / 2 + (Math.random() - 0.5) * 20,
stamina: (self.stamina + partner.stamina) / 2 + (Math.random() - 0.5) * 20,
temperament: (self.temperament + partner.temperament) / 2 + (Math.random() - 0.5) * 20,
age: 0,
name: 'Foal ' + Math.floor(Math.random() * 1000)
});
breedingCount++;
if (breedingCount === 1 && achievementSystem) {
achievementSystem.achievements.firstBreed.unlocked = true;
}
return offspring;
};
self.getRaceSpeed = function () {
var energyFactor = self.currentEnergy / self.maxEnergy;
return (self.speed * 0.6 + self.stamina * 0.4) * energyFactor;
};
self.update = function () {
if (self.isRacing) {
self.raceSpeed = self.getRaceSpeed() * (0.8 + Math.random() * 0.4);
self.racePosition += self.raceSpeed * 0.1;
// Calculate circular track position for larger track
var trackCenterX = 1024;
var trackCenterY = 1366;
var trackRadius = 700; // Increased for larger track
// Convert linear race position to angle (0 to 2*PI for full lap)
var raceAngle = self.racePosition / 2000 * Math.PI * 2;
// Check for lap completion
var newLap = Math.floor(self.racePosition / 2000);
if (newLap > self.lapsCompleted) {
self.lapsCompleted = newLap;
}
// Calculate horse position with increased lane spacing
var laneOffset = self.laneNumber * 50; // Increased from 25 to 50px between lanes
var currentRadius = trackRadius + laneOffset;
// Add slight natural variation to make racing look more realistic
var naturalVariation = Math.sin(self.racePosition * 0.02) * 5;
currentRadius += naturalVariation;
self.x = trackCenterX + Math.cos(raceAngle) * currentRadius;
self.y = trackCenterY + Math.sin(raceAngle) * currentRadius;
// Adjust horse rotation to face direction of movement (tangent to circle)
self.rotation = raceAngle + Math.PI / 2;
// Simple energy drain during race
self.currentEnergy = Math.max(0, self.currentEnergy - 0.2);
}
};
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2('', {
size: 80,
fill: '#ffffff'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 500;
self.addChild(titleText);
var playBtn = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1000
});
var playText = new Text2('', {
size: 50,
fill: '#ffffff'
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = 1000;
self.addChild(playText);
var tournamentBtn = self.attachAsset('tournamentButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1150
});
var tournamentText = new Text2('', {
size: 45,
fill: '#ffffff'
});
tournamentText.anchor.set(0.5, 0.5);
tournamentText.x = 1024;
tournamentText.y = 1150;
self.addChild(tournamentText);
var shopBtn = self.attachAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1300
});
var shopText = new Text2('', {
size: 45,
fill: '#ffffff'
});
shopText.anchor.set(0.5, 0.5);
shopText.x = 1024;
shopText.y = 1300;
self.addChild(shopText);
var settingsBtn = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1450
});
var settingsText = new Text2('', {
size: 45,
fill: '#ffffff'
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = 1024;
settingsText.y = 1450;
self.addChild(settingsText);
var helpBtn = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1600
});
var helpText = new Text2('', {
size: 45,
fill: '#ffffff'
});
helpText.anchor.set(0.5, 0.5);
helpText.x = 1024;
helpText.y = 1600;
self.addChild(helpText);
self.updateLanguage = function () {
titleText.setText(translations[currentLanguage].title);
playText.setText(translations[currentLanguage].play);
tournamentText.setText(translations[currentLanguage].tournament);
shopText.setText(translations[currentLanguage].shop);
settingsText.setText(translations[currentLanguage].settings);
helpText.setText(translations[currentLanguage].help);
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check play button
if (localPos.x >= 774 && localPos.x <= 1274 && localPos.y >= 940 && localPos.y <= 1060) {
currentView = 'stable';
updateView();
LK.getSound('buttonClick').play();
}
// Check tournament button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1090 && localPos.y <= 1210) {
currentView = 'tournament';
updateView();
LK.getSound('buttonClick').play();
}
// Check shop button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1240 && localPos.y <= 1360) {
currentView = 'shop';
updateView();
LK.getSound('buttonClick').play();
}
// Check settings button
if (localPos.x >= 799 && localPos.x <= 1249 && localPos.y >= 1390 && localPos.y <= 1510) {
currentView = 'settings';
updateView();
LK.getSound('buttonClick').play();
}
// Check help button
if (localPos.x >= 799 && localPos.x <= 1249 && localPos.y >= 1540 && localPos.y <= 1660) {
currentView = 'help';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var RaceView = Container.expand(function () {
var self = Container.call(this);
// Create larger circular race track with improved visuals
var trackOuter = self.attachAsset('circularTrack', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.4,
scaleY: 1.4
});
var trackInner = self.attachAsset('trackInner', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.4,
scaleY: 1.4
});
// Add lane markers for better visual separation with increased spacing
for (var i = 1; i < 6; i++) {
var laneMarker = self.attachAsset('startFinishLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + (630 + i * 50),
// Increased spacing from 25 to 50
y: 1366
});
laneMarker.rotation = Math.PI / 2;
laneMarker.alpha = 0.3;
laneMarker.scaleY = 0.3;
}
var finishLine = self.attachAsset('startFinishLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + 700,
// Adjusted for larger track
y: 1366
});
finishLine.scaleY = 2;
finishLine.tint = 0xff0000; // Red finish line
var raceTitle = new Text2('RACE IN PROGRESS', {
size: 50,
fill: '#ffffff'
});
raceTitle.anchor.set(0.5, 0.5);
raceTitle.x = 1024;
raceTitle.y = 200;
self.addChild(raceTitle);
var trackInfo = new Text2('Championship Circular Track - Complete One Lap', {
size: 30,
fill: '#ffff00'
});
trackInfo.anchor.set(0.5, 0.5);
trackInfo.x = 1024;
trackInfo.y = 250;
self.addChild(trackInfo);
self.raceHorses = [];
self.setupRace = function () {
// Reset race state completely
self.raceFinished = false;
// Clear existing race horses
for (var i = 0; i < self.raceHorses.length; i++) {
if (self.raceHorses[i].destroy) {
self.raceHorses[i].destroy();
}
}
self.raceHorses = [];
// Add player's horses and AI horses
var raceHorsesList = [];
// Add selected player horse
if (horses.length > 0) {
var selectedHorse = horses[selectedHorseIndex || 0];
raceHorsesList.push(selectedHorse);
}
// Add AI horses to fill up to 6 total
while (raceHorsesList.length < 6) {
var aiHorse = new Horse({
name: 'AI Horse ' + (raceHorsesList.length + 1),
speed: Math.random() * 40 + 60,
stamina: Math.random() * 40 + 60,
temperament: Math.random() * 40 + 60
});
raceHorsesList.push(aiHorse);
}
// Position horses at start line on larger circular track
var trackCenterX = 1024;
var trackCenterY = 1366;
var trackRadius = 700; // Increased for larger track
for (var i = 0; i < raceHorsesList.length; i++) {
var horse = raceHorsesList[i];
// Assign lane number for proper spacing
horse.laneNumber = i;
horse.isPlayerHorse = false;
horse.lapsCompleted = 0;
// Check if this is a player horse
for (var j = 0; j < horses.length; j++) {
if (horses[j] === horse) {
horse.isPlayerHorse = true;
break;
}
}
// Position horses at starting line with increased lane spacing
var startRadius = trackRadius + i * 50; // Increased from 25 to 50px between lanes
horse.x = trackCenterX + startRadius;
horse.y = trackCenterY;
horse.racePosition = 0;
horse.isRacing = true;
horse.currentEnergy = horse.maxEnergy;
horse.rotation = Math.PI / 2; // Face forward initially
self.addChild(horse);
self.raceHorses.push(horse);
// Add yellow star marker for player horses
if (horse.isPlayerHorse) {
var marker = self.attachAsset('gemIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: horse.x,
y: horse.y - 80
});
marker.targetHorse = horse;
marker.tint = 0xFFD700; // Yellow star for player horse
marker.scaleX = 1.2;
marker.scaleY = 1.2;
self.raceHorses.push(marker);
}
}
};
self.checkRaceFinish = function () {
// Don't check if race is already finished
if (self.raceFinished) {
return true;
}
// Validate race horses array
if (!self.raceHorses || self.raceHorses.length === 0) {
return false;
}
for (var i = 0; i < self.raceHorses.length; i++) {
var horse = self.raceHorses[i];
// Only check actual horses, not markers, with validation
if (horse && horse.racePosition !== undefined && horse.racePosition >= 2000 && !self.raceFinished) {
// Race finished - single lap (2000)
try {
self.finishRace(horse);
return true;
} catch (e) {
// Handle race finish errors
self.raceFinished = true;
return true;
}
}
}
return false;
};
self.raceFinished = false;
self.finishRace = function (winner) {
// Prevent multiple race finish triggers
if (self.raceFinished) {
return;
}
self.raceFinished = true;
// Stop all horses
for (var i = 0; i < self.raceHorses.length; i++) {
self.raceHorses[i].isRacing = false;
}
// Check if winner is player's horse
var isPlayerWinner = false;
for (var i = 0; i < horses.length; i++) {
if (horses[i] === winner) {
isPlayerWinner = true;
winner.raceWins++;
break;
}
}
// Award money based on tournament or regular race - only once
var prize = 0;
if (tournamentSystem.currentTournament) {
if (isPlayerWinner) {
prize = tournamentSystem.currentTournament.prize;
tournamentSystem.completeTournament();
} else {
prize = Math.floor(tournamentSystem.currentTournament.prize * 0.1); // Small participation prize
}
} else {
if (isPlayerWinner) {
prize = 10000;
LK.setScore(LK.getScore() + 1);
LK.getSound('crowdCheer').play();
} else {
prize = 2000; // Participation prize
}
}
// Only award money once
money += prize;
totalEarnings += prize;
updateMoneyDisplay();
// Clear race state to prevent further money awards
for (var i = 0; i < self.raceHorses.length; i++) {
self.raceHorses[i].racePosition = 0;
}
// Return to stable after 3 seconds
LK.setTimeout(function () {
currentView = 'stable';
updateView();
}, 3000);
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('settingsBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var panel = self.attachAsset('settingsPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2('', {
size: 80,
fill: '#ecf0f1'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
self.addChild(titleText);
var languageLabel = new Text2('', {
size: 50,
fill: '#3498db'
});
languageLabel.anchor.set(0.5, 0.5);
languageLabel.x = 1024;
languageLabel.y = 500;
self.addChild(languageLabel);
// Language data with flag colors
var languages = [{
name: 'English',
code: 'en',
flag: 0xff0000
}, {
name: 'Русский',
code: 'ru',
flag: 0x0080ff
}, {
name: 'Français',
code: 'fr',
flag: 0x0000ff
}, {
name: 'Türkçe',
code: 'tr',
flag: 0xff0000
}, {
name: 'Español',
code: 'es',
flag: 0xffff00
}, {
name: 'Deutsch',
code: 'de',
flag: 0x000000
}, {
name: '中文',
code: 'zh',
flag: 0xff0000
}, {
name: '日本語',
code: 'ja',
flag: 0xff0000
}, {
name: 'Italiano',
code: 'it',
flag: 0x00ff00
}, {
name: 'Português',
code: 'pt',
flag: 0x00ff00
}];
self.languageButtons = [];
for (var i = 0; i < languages.length; i++) {
var lang = languages[i];
var isSelected = currentLanguage === lang.code;
var btnAsset = isSelected ? 'selectedLanguage' : 'languageButton';
var langBtn = self.attachAsset(btnAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 350 + i % 4 * 350,
y: 700 + Math.floor(i / 4) * 150
});
var flagIcon = self.attachAsset('languageFlag', {
anchorX: 0.5,
anchorY: 0.5,
x: 250 + i % 4 * 350,
y: 700 + Math.floor(i / 4) * 150
});
flagIcon.tint = lang.flag;
var langText = new Text2(lang.name, {
size: 26,
fill: isSelected ? '#f1c40f' : '#ffffff'
});
langText.anchor.set(0.5, 0.5);
langText.x = 380 + i % 4 * 350;
langText.y = 700 + Math.floor(i / 4) * 150;
langText.langCode = lang.code;
self.addChild(langText);
self.languageButtons.push({
button: langBtn,
flag: flagIcon,
text: langText,
code: lang.code,
x: 350 + i % 4 * 350,
y: 700 + Math.floor(i / 4) * 150
});
}
// Audio settings
var audioLabel = new Text2('Audio Settings', {
size: 45,
fill: '#e67e22'
});
audioLabel.anchor.set(0.5, 0.5);
audioLabel.x = 1024;
audioLabel.y = 1400;
self.addChild(audioLabel);
var volumeLabel = new Text2('Master Volume: 100%', {
size: 35,
fill: '#95a5a6'
});
volumeLabel.anchor.set(0.5, 0.5);
volumeLabel.x = 1024;
volumeLabel.y = 1500;
self.addChild(volumeLabel);
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1700
});
var backText = new Text2('', {
size: 40,
fill: '#ffffff'
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1700;
self.addChild(backText);
self.updateLanguage = function () {
titleText.setText(translations[currentLanguage].settings || 'SETTINGS');
languageLabel.setText(translations[currentLanguage].language || 'Choose Language:');
backText.setText(translations[currentLanguage].back || 'BACK');
// Update button selection
for (var i = 0; i < self.languageButtons.length; i++) {
var btn = self.languageButtons[i];
var isSelected = currentLanguage === btn.code;
btn.text.fill = isSelected ? '#f1c40f' : '#ffffff';
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check language buttons
for (var i = 0; i < self.languageButtons.length; i++) {
var btn = self.languageButtons[i];
if (localPos.x >= btn.x - 210 && localPos.x <= btn.x + 210 && localPos.y >= btn.y - 60 && localPos.y <= btn.y + 60) {
if (currentLanguage !== btn.code) {
currentLanguage = btn.code;
storage.language = currentLanguage;
updateAllLanguages();
LK.getSound('buttonClick').play();
LK.effects.flashScreen(0x3498db, 200);
// Refresh UI to update selection
currentView = 'settings';
updateView();
}
break;
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 1640 && localPos.y <= 1760) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
self.currentCategory = 'basic';
self.categories = ['basic', 'premium', 'legendary'];
self.categoryButtons = [];
self.itemButtons = [];
self.items = {
basic: {
feed: {
name: 'Premium Feed',
price: 5000,
effect: 'energy',
description: 'Restores horse energy',
icon: 'speedBoost'
},
medicine: {
name: 'Energy Boost',
price: 8000,
effect: 'health',
description: 'Increases max energy',
icon: 'healthBoost'
},
vitamins: {
name: 'Vitamins',
price: 10000,
effect: 'stamina',
description: 'Improves stamina',
icon: 'staminaBoost'
}
},
premium: {
equipment: {
name: 'Racing Equipment',
price: 15000,
effect: 'speed',
description: 'Professional racing gear',
icon: 'speedBoost'
},
training: {
name: 'Advanced Training',
price: 20000,
effect: 'training',
description: 'Elite training program',
icon: 'staminaBoost'
},
superFeed: {
name: 'Super Feed',
price: 25000,
effect: 'superEnergy',
description: 'Premium nutrition boost',
icon: 'healthBoost'
}
},
legendary: {
geneticBoost: {
name: 'Genetic Enhancement',
price: 100000,
effect: 'genetic',
description: 'Permanent stat boost',
icon: 'gemIcon'
},
championGear: {
name: 'Champion Gear',
price: 150000,
effect: 'champion',
description: 'Legendary equipment set',
icon: 'speedBoost'
},
immortalElixir: {
name: 'Immortal Elixir',
price: 200000,
effect: 'immortal',
description: 'Stops aging process',
icon: 'healthBoost'
}
}
};
self.setupUI = function () {
var background = self.attachAsset('shopBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2(translations[currentLanguage].shop || 'Elite Horse Shop', {
size: 90,
fill: '#ecf0f1'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 250;
self.addChild(titleText);
// Category buttons
for (var i = 0; i < self.categories.length; i++) {
var category = self.categories[i];
var categoryBtn = self.attachAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 400 + i * 400,
y: 400
});
var categoryText = new Text2(category.toUpperCase(), {
size: 35,
fill: '#ffffff'
});
categoryText.anchor.set(0.5, 0.5);
categoryText.x = 400 + i * 400;
categoryText.y = 400;
categoryText.categoryId = category;
self.addChild(categoryText);
self.categoryButtons.push({
button: categoryBtn,
text: categoryText,
category: category
});
}
self.refreshItems();
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
});
var backText = new Text2(translations[currentLanguage].back || 'Back', {
size: 45,
fill: '#ffffff'
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2400;
self.addChild(backText);
};
self.refreshItems = function () {
// Clear existing item buttons
for (var i = 0; i < self.itemButtons.length; i++) {
if (self.itemButtons[i].destroy) {
self.itemButtons[i].destroy();
}
}
self.itemButtons = [];
var items = self.items[self.currentCategory];
var yPos = 600;
var itemIndex = 0;
for (var itemId in items) {
var item = items[itemId];
var cardType = self.currentCategory === 'legendary' ? 'legendaryItem' : self.currentCategory === 'premium' ? 'premiumItem' : 'itemCard';
var itemCard = self.attachAsset(cardType, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos
});
var itemIcon = self.attachAsset(item.icon, {
anchorX: 0.5,
anchorY: 0.5,
x: 650,
y: yPos
});
var itemText = new Text2(item.name, {
size: 40,
fill: '#ffffff'
});
itemText.anchor.set(0, 0.5);
itemText.x = 750;
itemText.y = yPos - 30;
self.addChild(itemText);
var priceText = new Text2('$' + item.price, {
size: 35,
fill: '#f1c40f'
});
priceText.anchor.set(0, 0.5);
priceText.x = 750;
priceText.y = yPos;
self.addChild(priceText);
var descText = new Text2(item.description, {
size: 28,
fill: '#bdc3c7'
});
descText.anchor.set(0, 0.5);
descText.x = 750;
descText.y = yPos + 35;
self.addChild(descText);
self.itemButtons.push({
card: itemCard,
icon: itemIcon,
itemId: itemId,
y: yPos
});
yPos += 220;
itemIndex++;
}
};
self.purchaseItem = function (itemId) {
var item = self.items[self.currentCategory][itemId];
if (money >= item.price) {
money -= item.price;
totalEarnings += item.price;
self.applyItemEffect(item.effect, item);
updateMoneyDisplay();
LK.getSound('coinSound').play();
LK.effects.flashScreen(0x00ff00, 300);
return true;
}
return false;
};
self.applyItemEffect = function (effect, item) {
if (horses.length > 0) {
var horse = horses[selectedHorseIndex || 0];
switch (effect) {
case 'energy':
horse.currentEnergy = horse.maxEnergy;
break;
case 'health':
horse.maxEnergy += 15;
break;
case 'speed':
horse.speed += 8;
break;
case 'stamina':
horse.stamina += 8;
break;
case 'training':
horse.train('speed');
horse.train('stamina');
horse.train('temperament');
break;
case 'superEnergy':
horse.currentEnergy = horse.maxEnergy;
horse.maxEnergy += 25;
break;
case 'genetic':
horse.speed += 20;
horse.stamina += 20;
horse.temperament += 20;
break;
case 'champion':
horse.speed += 15;
horse.stamina += 15;
horse.value *= 2;
break;
case 'immortal':
horse.age = Math.max(2, horse.age - 5);
horse.maxEnergy += 50;
break;
}
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check category buttons
for (var i = 0; i < self.categoryButtons.length; i++) {
var btnX = 400 + i * 400;
var btnY = 400;
if (localPos.x >= btnX - 240 && localPos.x <= btnX + 240 && localPos.y >= btnY - 70 && localPos.y <= btnY + 70) {
self.currentCategory = self.categoryButtons[i].category;
self.refreshItems();
LK.getSound('buttonClick').play();
break;
}
}
// Check item buttons
for (var i = 0; i < self.itemButtons.length; i++) {
var item = self.itemButtons[i];
if (localPos.x >= 724 && localPos.x <= 1324 && localPos.y >= item.y - 100 && localPos.y <= item.y + 100) {
if (self.purchaseItem(item.itemId)) {
self.refreshItems();
}
break;
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2330 && localPos.y <= 2470) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var StableView = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('stableBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2('Your Stable', {
size: 60,
fill: '#ffffff'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
self.addChild(titleText);
// Action buttons - First row
var breedBtn = self.attachAsset('breedButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 512,
y: 1800
});
var breedText = new Text2('BREED', {
size: 35,
fill: '#ffffff'
});
breedText.anchor.set(0.5, 0.5);
breedText.x = 512;
breedText.y = 1800;
self.addChild(breedText);
var trainBtn = self.attachAsset('trainButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800
});
var trainText = new Text2('TRAIN', {
size: 35,
fill: '#ffffff'
});
trainText.anchor.set(0.5, 0.5);
trainText.x = 1024;
trainText.y = 1800;
self.addChild(trainText);
var raceBtn = self.attachAsset('raceButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1536,
y: 1800
});
var raceText = new Text2('RACE', {
size: 35,
fill: '#ffffff'
});
raceText.anchor.set(0.5, 0.5);
raceText.x = 1536;
raceText.y = 1800;
self.addChild(raceText);
// Action buttons - Second row
var vetBtn = self.attachAsset('vetButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 512,
y: 1950
});
var vetText = new Text2('VET', {
size: 35,
fill: '#ffffff'
});
vetText.anchor.set(0.5, 0.5);
vetText.x = 512;
vetText.y = 1950;
self.addChild(vetText);
var feedBtn = self.attachAsset('feedButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1950
});
var feedText = new Text2('FEED', {
size: 35,
fill: '#ffffff'
});
feedText.anchor.set(0.5, 0.5);
feedText.x = 1024;
feedText.y = 1950;
self.addChild(feedText);
var upgradeBtn = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1536,
y: 1950
});
var upgradeText = new Text2('UPGRADE', {
size: 35,
fill: '#ffffff'
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = 1536;
upgradeText.y = 1950;
self.addChild(upgradeText);
// Add back button to return to main menu
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
self.backText = new Text2('BACK TO MENU', {
size: 35,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2200;
self.addChild(self.backText);
self.horseIcons = [];
self.selectedHorseForRace = 0;
self.backText = null;
self.updateHorseDisplay = function () {
// Clear existing icons
for (var i = 0; i < self.horseIcons.length; i++) {
self.horseIcons[i].destroy();
}
self.horseIcons = [];
// Add current horses
for (var i = 0; i < horses.length; i++) {
var horse = horses[i];
var isSelected = i === self.selectedHorseForRace;
var icon = self.attachAsset('horseIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 600 + i % 3 * 200,
y: 500 + Math.floor(i / 3) * 120,
tint: isSelected ? 0xFFD700 : 0xFFFFFF
});
// Add selection star for selected horse
if (isSelected) {
var selectionStar = self.attachAsset('gemIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 600 + i % 3 * 200,
y: 460 + Math.floor(i / 3) * 120,
tint: 0xFFD700,
scaleX: 0.8,
scaleY: 0.8
});
self.horseIcons.push(selectionStar);
}
var nameText = new Text2(horse.name, {
size: 20,
fill: isSelected ? '#FFD700' : '#ffffff'
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 600 + i % 3 * 200;
nameText.y = 550 + Math.floor(i / 3) * 120;
self.addChild(nameText);
var energyPercent = Math.floor(horse.currentEnergy / horse.maxEnergy * 100);
var energyColor = energyPercent > 70 ? '#00FF00' : energyPercent > 30 ? '#FFFF00' : '#FF0000';
var statsText = new Text2('Speed: ' + Math.floor(horse.speed) + ' Energy: ' + energyPercent + '%', {
size: 16,
fill: energyColor
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 600 + i % 3 * 200;
statsText.y = 570 + Math.floor(i / 3) * 120;
self.addChild(statsText);
icon.horseIndex = i;
self.horseIcons.push(icon);
}
};
self.updateLanguage = function () {
titleText.setText(translations[currentLanguage].yourStable);
breedText.setText(translations[currentLanguage].breed);
trainText.setText(translations[currentLanguage].train);
raceText.setText(translations[currentLanguage].race);
vetText.setText(translations[currentLanguage].vet);
feedText.setText(translations[currentLanguage].feed);
upgradeText.setText(translations[currentLanguage].upgrade);
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'BACK TO MENU');
}
};
self.down = function (x, y, obj) {
// Safety check for obj.parent
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check breed button with validation
if (localPos.x >= 312 && localPos.x <= 712 && localPos.y >= 1740 && localPos.y <= 1860) {
if (horses && horses.length >= 2 && money >= 5000 && horses[0] && horses[1]) {
try {
var offspring = horses[0].breed(horses[1]);
if (offspring) {
horses.push(offspring);
money -= 5000;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('buttonClick').play();
}
} catch (e) {
// Handle breeding errors
LK.effects.flashScreen(0xff0000, 300);
}
} else if (money < 5000) {
LK.effects.flashScreen(0xff0000, 300);
} else if (horses.length < 2) {
LK.effects.flashScreen(0xff0000, 300);
}
}
// Check train button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1740 && localPos.y <= 1860) {
if (horses.length > 0 && money >= 1000) {
horses[selectedHorseIndex || 0].train('speed');
money -= 1000;
trainingCount++;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('training').play();
} else if (money < 1000) {
LK.effects.flashScreen(0xff0000, 300);
}
}
// Check horse selection
for (var i = 0; i < self.horseIcons.length; i++) {
var icon = self.horseIcons[i];
if (icon.horseIndex !== undefined) {
var horseX = 600 + icon.horseIndex % 3 * 200;
var horseY = 500 + Math.floor(icon.horseIndex / 3) * 120;
if (localPos.x >= horseX - 60 && localPos.x <= horseX + 60 && localPos.y >= horseY - 50 && localPos.y <= horseY + 50) {
self.selectedHorseForRace = icon.horseIndex;
selectedHorseIndex = icon.horseIndex;
self.updateHorseDisplay();
LK.getSound('buttonClick').play();
break;
}
}
}
// Check race button
if (localPos.x >= 1336 && localPos.x <= 1736 && localPos.y >= 1740 && localPos.y <= 1860) {
if (horses.length > 0) {
// Ensure selected horse has enough energy
var selectedHorse = horses[selectedHorseIndex || 0];
if (selectedHorse.currentEnergy >= 30) {
currentView = 'race';
updateView();
LK.getSound('buttonClick').play();
} else {
LK.effects.flashScreen(0xff0000, 300);
}
}
}
// Check vet button
if (localPos.x >= 312 && localPos.x <= 712 && localPos.y >= 1890 && localPos.y <= 2010) {
if (horses.length > 0) {
currentView = 'vet';
updateView();
LK.getSound('buttonClick').play();
}
}
// Check feed button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1890 && localPos.y <= 2010) {
if (horses.length > 0 && money >= 500) {
horses[0].currentEnergy = Math.min(horses[0].maxEnergy, horses[0].currentEnergy + 50);
money -= 500;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('buttonClick').play();
}
}
// Check upgrade button
if (localPos.x >= 1336 && localPos.x <= 1736 && localPos.y >= 1890 && localPos.y <= 2010) {
if (horses.length > 0 && money >= 10000) {
horses[0].speed += 5;
horses[0].stamina += 5;
money -= 10000;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('buttonClick').play();
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2140 && localPos.y <= 2260) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Tournament = Container.expand(function () {
var self = Container.call(this);
self.tournaments = [{
name: 'Spring Classic',
prize: 25000,
difficulty: 'easy',
entryFee: 2000
}, {
name: 'Summer Championship',
prize: 50000,
difficulty: 'medium',
entryFee: 5000
}, {
name: 'Grand Prix',
prize: 100000,
difficulty: 'hard',
entryFee: 10000
}, {
name: 'Ultimate Derby',
prize: 200000,
difficulty: 'extreme',
entryFee: 20000
}];
self.currentTournament = null;
self.tournamentProgress = 0;
self.titleText = null;
self.backText = null;
self.setupUI = function () {
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
self.titleText = new Text2(translations[currentLanguage].tournaments || 'Tournaments', {
size: 80,
fill: '#ffffff'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 300;
self.addChild(self.titleText);
var yPos = 600;
for (var i = 0; i < self.tournaments.length; i++) {
var tournament = self.tournaments[i];
var tournamentBtn = self.attachAsset('tournamentButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos
});
var tournamentText = new Text2(tournament.name + ' - Prize: $' + tournament.prize, {
size: 28,
fill: '#ffffff'
});
tournamentText.anchor.set(0.5, 0.5);
tournamentText.x = 1024;
tournamentText.y = yPos;
self.addChild(tournamentText);
yPos += 150;
}
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
self.backText = new Text2(translations[currentLanguage].back || 'Back', {
size: 40,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2200;
self.addChild(self.backText);
};
self.updateLanguage = function () {
if (self.titleText) {
self.titleText.setText(translations[currentLanguage].tournaments || 'Tournaments');
}
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'Back');
}
};
self.enterTournament = function (tournamentIndex) {
var tournament = self.tournaments[tournamentIndex];
if (money >= tournament.entryFee) {
money -= tournament.entryFee;
self.currentTournament = tournament;
self.tournamentProgress = 0;
updateMoneyDisplay();
return true;
}
return false;
};
self.completeTournament = function () {
if (self.currentTournament) {
money += self.currentTournament.prize;
totalEarnings += self.currentTournament.prize;
self.currentTournament = null;
updateMoneyDisplay();
LK.getSound('victory').play();
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check tournament buttons with validation
var yPos = 600;
for (var i = 0; i < self.tournaments.length; i++) {
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= yPos - 60 && localPos.y <= yPos + 60) {
// Validate tournament entry requirements
if (horses && horses.length > 0 && selectedHorseIndex < horses.length) {
var selectedHorse = horses[selectedHorseIndex || 0];
if (selectedHorse && selectedHorse.currentEnergy >= 50) {
if (self.enterTournament(i)) {
currentView = 'race';
updateView();
LK.getSound('buttonClick').play();
}
} else {
// Horse too tired for tournament
LK.effects.flashScreen(0xff0000, 300);
}
} else {
// No horses available
LK.effects.flashScreen(0xff0000, 300);
}
break;
}
yPos += 150;
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2140 && localPos.y <= 2260) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Veterinarian = Container.expand(function () {
var self = Container.call(this);
self.treatments = {
checkup: {
name: 'Health Checkup',
price: 1000,
effect: 'health'
},
energy: {
name: 'Energy Treatment',
price: 2000,
effect: 'energy'
},
performance: {
name: 'Performance Boost',
price: 5000,
effect: 'performance'
},
recovery: {
name: 'Recovery Therapy',
price: 3000,
effect: 'recovery'
}
};
self.titleText = null;
self.backText = null;
self.setupUI = function () {
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
self.titleText = new Text2(translations[currentLanguage].veterinarian || 'Veterinarian', {
size: 80,
fill: '#ffffff'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 300;
self.addChild(self.titleText);
var yPos = 600;
for (var treatmentId in self.treatments) {
var treatment = self.treatments[treatmentId];
var treatmentBtn = self.attachAsset('vetButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos
});
var treatmentText = new Text2(treatment.name + ' - $' + treatment.price, {
size: 30,
fill: '#ffffff'
});
treatmentText.anchor.set(0.5, 0.5);
treatmentText.x = 1024;
treatmentText.y = yPos;
self.addChild(treatmentText);
yPos += 150;
}
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
self.backText = new Text2(translations[currentLanguage].back || 'Back', {
size: 40,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2200;
self.addChild(self.backText);
};
self.updateLanguage = function () {
if (self.titleText) {
self.titleText.setText(translations[currentLanguage].veterinarian || 'Veterinarian');
}
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'Back');
}
};
self.performTreatment = function (treatmentId) {
var treatment = self.treatments[treatmentId];
if (money >= treatment.price && horses.length > 0) {
money -= treatment.price;
self.applyTreatment(treatment.effect);
updateMoneyDisplay();
return true;
}
return false;
};
self.applyTreatment = function (effect) {
if (horses.length > 0) {
var horse = horses[0];
switch (effect) {
case 'health':
horse.maxEnergy += 20;
break;
case 'energy':
horse.currentEnergy = horse.maxEnergy;
break;
case 'performance':
horse.speed += 10;
horse.stamina += 10;
break;
case 'recovery':
horse.currentEnergy = horse.maxEnergy;
horse.speed += 5;
break;
}
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check treatment buttons
var yPos = 600;
for (var treatmentId in self.treatments) {
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= yPos - 75 && localPos.y <= yPos + 75) {
if (self.performTreatment(treatmentId)) {
LK.getSound('buttonClick').play();
LK.effects.flashScreen(0x00ff00, 300);
}
break;
}
yPos += 150;
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2140 && localPos.y <= 2260) {
currentView = 'stable';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Weather = Container.expand(function () {
var self = Container.call(this);
self.conditions = ['sunny', 'rainy', 'cloudy', 'windy'];
self.currentWeather = 'sunny';
self.weatherIcon = null;
self.init = function () {
self.weatherIcon = self.attachAsset('weatherIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 150
});
self.updateWeather();
};
self.updateWeather = function () {
self.currentWeather = self.conditions[Math.floor(Math.random() * self.conditions.length)];
switch (self.currentWeather) {
case 'sunny':
self.weatherIcon.tint = 0xffff00;
break;
case 'rainy':
self.weatherIcon.tint = 0x0080ff;
break;
case 'cloudy':
self.weatherIcon.tint = 0x808080;
break;
case 'windy':
self.weatherIcon.tint = 0x90ee90;
break;
}
};
self.getSpeedModifier = function () {
switch (self.currentWeather) {
case 'sunny':
return 1.1;
case 'rainy':
return 0.9;
case 'cloudy':
return 1.0;
case 'windy':
return 0.95;
default:
return 1.0;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Language translations
var translations = {
en: {
title: 'Thoroughbred Legacy',
play: 'PLAY',
settings: 'SETTINGS',
language: 'Language:',
back: 'BACK',
yourStable: 'Your Stable',
breed: 'BREED',
train: 'TRAIN',
race: 'RACE',
money: 'Money: $',
wins: 'Wins: ',
help: 'HELP & GUIDE',
shop: 'SHOP',
tournament: 'TOURNAMENT',
vet: 'VETERINARIAN',
feed: 'FEED',
upgrade: 'UPGRADE'
},
ru: {
title: 'Наследие Чистокровных',
play: 'ИГРАТЬ',
settings: 'НАСТРОЙКИ',
language: 'Язык:',
back: 'НАЗАД',
yourStable: 'Ваша Конюшня',
breed: 'РАЗВЕДЕНИЕ',
train: 'ТРЕНИРОВКА',
race: 'ГОНКА',
money: 'Деньги: $',
wins: 'Побед: ',
help: 'ПОМОЩЬ И РУКОВОДСТВО'
},
fr: {
title: 'Héritage Pur-Sang',
play: 'JOUER',
settings: 'PARAMÈTRES',
language: 'Langue:',
back: 'RETOUR',
yourStable: 'Votre Écurie',
breed: 'ÉLEVAGE',
train: 'ENTRAÎNER',
race: 'COURSE',
money: 'Argent: $',
wins: 'Victoires: ',
help: 'AIDE ET GUIDE'
},
tr: {
title: 'Safkan Mirası',
play: 'OYNA',
settings: 'AYARLAR',
language: 'Dil Seçimi:',
back: 'GERİ',
yourStable: 'Ahırınız',
breed: 'ÜRETME',
train: 'EĞİTİM',
race: 'YARIŞ',
money: 'Para: $',
wins: 'Galibiyet: ',
upgrade: 'GELİŞTİRME',
shop: 'ELİT AT MAĞAZASI',
tournament: 'TURNUVA',
vet: 'VETERİNER',
feed: 'BESLENME',
weather: 'Hava Durumu',
achievements: 'Başarılar',
statistics: 'İstatistikler',
basic: 'TEMEL',
premium: 'PREMİUM',
legendary: 'EFSANEVİ',
audio: 'Ses Ayarları',
volume: 'Ana Ses: %',
tournaments: 'Turnuvalar',
veterinarian: 'Veteriner Hekim',
selectHorse: 'At Seçin',
horseStats: 'At İstatistikleri',
speed: 'Hız',
stamina: 'Dayanıklılık',
energy: 'Enerji',
age: 'Yaş',
value: 'Değer',
raceWins: 'Yarış Zaferleri',
temperament: 'Mizaç',
help: 'YARDIM VE KILAVUZ'
},
es: {
title: 'Legado Pura Sangre',
play: 'JUGAR',
settings: 'CONFIGURACIÓN',
language: 'Idioma:',
back: 'VOLVER',
yourStable: 'Tu Establo',
breed: 'CRIAR',
train: 'ENTRENAR',
race: 'CARRERA',
money: 'Dinero: $',
wins: 'Victorias: ',
upgrade: 'MEJORAR',
shop: 'TIENDA',
tournament: 'TORNEO',
vet: 'VETERINARIO',
feed: 'ALIMENTAR',
weather: 'Clima',
achievements: 'Logros',
statistics: 'Estadísticas',
help: 'AYUDA Y GUÍA'
},
de: {
title: 'Vollblut Erbe',
play: 'SPIELEN',
settings: 'EINSTELLUNGEN',
language: 'Sprache:',
back: 'ZURÜCK',
yourStable: 'Dein Stall',
breed: 'ZÜCHTEN',
train: 'TRAINIEREN',
race: 'RENNEN',
money: 'Geld: $',
wins: 'Siege: ',
upgrade: 'VERBESSERN',
shop: 'LADEN',
tournament: 'TURNIER',
vet: 'TIERARZT',
feed: 'FÜTTERN',
weather: 'Wetter',
achievements: 'Erfolge',
statistics: 'Statistiken',
help: 'HILFE UND ANLEITUNG'
},
zh: {
title: '纯血传承',
play: '开始游戏',
settings: '设置',
language: '语言:',
back: '返回',
yourStable: '你的马厩',
breed: '繁殖',
train: '训练',
race: '比赛',
money: '金钱: $',
wins: '胜利: ',
upgrade: '升级',
shop: '商店',
tournament: '锦标赛',
vet: '兽医',
feed: '喂养',
weather: '天气',
achievements: '成就',
statistics: '统计',
help: '帮助和指南'
},
ja: {
title: 'サラブレッドの遺産',
play: 'プレイ',
settings: '設定',
language: '言語:',
back: '戻る',
yourStable: 'あなたの厩舎',
breed: '繁殖',
train: '訓練',
race: 'レース',
money: 'お金: $',
wins: '勝利: ',
upgrade: 'アップグレード',
shop: 'ショップ',
tournament: 'トーナメント',
vet: '獣医',
feed: '餌やり',
weather: '天気',
achievements: '実績',
statistics: '統計',
help: 'ヘルプとガイド'
},
it: {
title: 'Eredità Purosangue',
play: 'GIOCA',
settings: 'IMPOSTAZIONI',
language: 'Lingua:',
back: 'INDIETRO',
yourStable: 'La Tua Scuderia',
breed: 'ALLEVARE',
train: 'ALLENARE',
race: 'CORSA',
money: 'Denaro: $',
wins: 'Vittorie: ',
upgrade: 'MIGLIORARE',
shop: 'NEGOZIO',
tournament: 'TORNEO',
vet: 'VETERINARIO',
feed: 'NUTRIRE',
weather: 'Tempo',
achievements: 'Risultati',
statistics: 'Statistiche',
help: 'AIUTO E GUIDA'
},
pt: {
title: 'Legado Puro Sangue',
play: 'JOGAR',
settings: 'CONFIGURAÇÕES',
language: 'Idioma:',
back: 'VOLTAR',
yourStable: 'Seu Estábulo',
breed: 'CRIAR',
train: 'TREINAR',
race: 'CORRIDA',
money: 'Dinheiro: $',
wins: 'Vitórias: ',
upgrade: 'MELHORAR',
shop: 'LOJA',
tournament: 'TORNEIO',
vet: 'VETERINÁRIO',
feed: 'ALIMENTAR',
weather: 'Tempo',
achievements: 'Conquistas',
statistics: 'Estatísticas',
help: 'AJUDA E GUIA'
}
};
// Load saved language or default to English
var currentLanguage = storage.language || 'en';
// Game state
var currentView = 'menu';
var horses = [];
var money = 50000;
var raceInProgress = false;
var totalEarnings = storage.totalEarnings || 0;
var trainingCount = storage.trainingCount || 0;
var breedingCount = storage.breedingCount || 0;
var selectedHorseIndex = 0;
var weatherSystem = null;
var achievementSystem = null;
var shopSystem = null;
var tournamentSystem = null;
var veterinarianSystem = null;
var helpSystem = null;
var currentWeather = 'sunny';
var gameTime = 0;
var seasonalBonus = 1.0;
// UI Elements
var moneyText = new Text2('Money: $' + money, {
size: 40,
fill: '#ffffff'
});
moneyText.anchor.set(0, 0);
moneyText.x = 150;
moneyText.y = 50;
LK.gui.topLeft.addChild(moneyText);
var scoreText = new Text2('Wins: ' + LK.getScore(), {
size: 40,
fill: '#ffffff'
});
scoreText.anchor.set(1, 0);
scoreText.x = -50;
scoreText.y = 50;
LK.gui.topRight.addChild(scoreText);
// Views
var mainMenu = new MainMenu();
var settingsMenu = new SettingsMenu();
var stableView = new StableView();
var raceView = new RaceView();
// Initialize game systems
weatherSystem = new Weather();
achievementSystem = new Achievement();
shopSystem = new Shop();
tournamentSystem = new Tournament();
veterinarianSystem = new Veterinarian();
helpSystem = new Help();
// Setup weather system
weatherSystem.init();
game.addChild(weatherSystem);
// Load achievements from storage
if (storage.achievements) {
// Reconstruct achievements from flattened storage
var flatAchievements = storage.achievements;
for (var key in achievementSystem.achievements) {
if (flatAchievements[key + '_unlocked'] !== undefined) {
achievementSystem.achievements[key].unlocked = flatAchievements[key + '_unlocked'];
}
if (flatAchievements[key + '_name'] !== undefined) {
achievementSystem.achievements[key].name = flatAchievements[key + '_name'];
}
if (flatAchievements[key + '_description'] !== undefined) {
achievementSystem.achievements[key].description = flatAchievements[key + '_description'];
}
}
}
// Initialize with starter horses
horses.push(new Horse({
name: 'Thunder',
speed: 70,
stamina: 65,
temperament: 60
}));
horses.push(new Horse({
name: 'Lightning',
speed: 60,
stamina: 70,
temperament: 65
}));
function updateMoneyDisplay() {
moneyText.setText(translations[currentLanguage].money + money);
scoreText.setText(translations[currentLanguage].wins + LK.getScore());
}
function updateAllLanguages() {
updateMoneyDisplay();
if (mainMenu.parent) {
mainMenu.updateLanguage();
}
if (settingsMenu.parent) {
settingsMenu.updateLanguage();
}
if (stableView.parent) {
stableView.updateLanguage();
}
}
function updateView() {
// Remove all views
if (mainMenu.parent) {
game.removeChild(mainMenu);
}
if (settingsMenu.parent) {
game.removeChild(settingsMenu);
}
if (stableView.parent) {
game.removeChild(stableView);
}
if (raceView.parent) {
game.removeChild(raceView);
}
if (shopSystem && shopSystem.parent) {
game.removeChild(shopSystem);
}
if (tournamentSystem && tournamentSystem.parent) {
game.removeChild(tournamentSystem);
}
if (veterinarianSystem && veterinarianSystem.parent) {
game.removeChild(veterinarianSystem);
}
if (helpSystem && helpSystem.parent) {
game.removeChild(helpSystem);
}
// Add current view
if (currentView === 'menu') {
game.addChild(mainMenu);
mainMenu.updateLanguage();
raceInProgress = false;
LK.playMusic('menuMusic');
} else if (currentView === 'settings') {
game.addChild(settingsMenu);
settingsMenu.updateLanguage();
raceInProgress = false;
} else if (currentView === 'stable') {
game.addChild(stableView);
stableView.updateHorseDisplay();
stableView.updateLanguage();
raceInProgress = false;
LK.playMusic('stableMusic');
} else if (currentView === 'race') {
game.addChild(raceView);
raceView.setupRace();
raceInProgress = true;
LK.getSound('hoofbeats').play();
LK.playMusic('raceMusic');
} else if (currentView === 'shop') {
shopSystem.setupUI();
game.addChild(shopSystem);
raceInProgress = false;
} else if (currentView === 'tournament') {
tournamentSystem.setupUI();
game.addChild(tournamentSystem);
if (tournamentSystem.updateLanguage) {
tournamentSystem.updateLanguage();
}
raceInProgress = false;
} else if (currentView === 'vet') {
veterinarianSystem.setupUI();
game.addChild(veterinarianSystem);
if (veterinarianSystem.updateLanguage) {
veterinarianSystem.updateLanguage();
}
raceInProgress = false;
} else if (currentView === 'help') {
helpSystem.setupUI();
game.addChild(helpSystem);
if (helpSystem.updateLanguage) {
helpSystem.updateLanguage();
}
raceInProgress = false;
}
}
function startRace() {
if (horses.length > 0) {
currentView = 'race';
updateView();
}
}
// Helper functions
function saveGameProgress() {
storage.money = money;
storage.totalEarnings = totalEarnings;
storage.trainingCount = trainingCount;
storage.breedingCount = breedingCount;
// Flatten achievements for storage
var flatAchievements = {};
for (var key in achievementSystem.achievements) {
flatAchievements[key + '_unlocked'] = achievementSystem.achievements[key].unlocked;
flatAchievements[key + '_name'] = achievementSystem.achievements[key].name;
flatAchievements[key + '_description'] = achievementSystem.achievements[key].description;
}
storage.achievements = flatAchievements;
// Flatten horse data for storage - create simple object structure
var flatHorseData = {};
for (var i = 0; i < horses.length; i++) {
var horse = horses[i];
flatHorseData['horse_' + i + '_name'] = horse.name || 'Unnamed Horse';
flatHorseData['horse_' + i + '_speed'] = Number(horse.speed) || 50;
flatHorseData['horse_' + i + '_stamina'] = Number(horse.stamina) || 50;
flatHorseData['horse_' + i + '_temperament'] = Number(horse.temperament) || 50;
flatHorseData['horse_' + i + '_age'] = Number(horse.age) || 2;
flatHorseData['horse_' + i + '_raceWins'] = Number(horse.raceWins) || 0;
flatHorseData['horse_' + i + '_value'] = Number(horse.value) || 10000;
flatHorseData['horse_' + i + '_currentEnergy'] = Number(horse.currentEnergy) || 100;
flatHorseData['horse_' + i + '_maxEnergy'] = Number(horse.maxEnergy) || 100;
}
flatHorseData['horseCount'] = horses.length;
storage.horseData = flatHorseData;
}
function loadGameProgress() {
if (storage.money) {
money = storage.money;
}
if (storage.totalEarnings) {
totalEarnings = storage.totalEarnings;
}
if (storage.trainingCount) {
trainingCount = storage.trainingCount;
}
if (storage.breedingCount) {
breedingCount = storage.breedingCount;
}
if (storage.achievements) {
// Reconstruct achievements from flattened storage
var flatAchievements = storage.achievements;
for (var key in achievementSystem.achievements) {
if (flatAchievements[key + '_unlocked'] !== undefined) {
achievementSystem.achievements[key].unlocked = flatAchievements[key + '_unlocked'];
}
if (flatAchievements[key + '_name'] !== undefined) {
achievementSystem.achievements[key].name = flatAchievements[key + '_name'];
}
if (flatAchievements[key + '_description'] !== undefined) {
achievementSystem.achievements[key].description = flatAchievements[key + '_description'];
}
}
}
if (storage.horseData && storage.horseData.horseCount) {
horses = [];
var horseCount = storage.horseData.horseCount;
for (var i = 0; i < horseCount; i++) {
horses.push(new Horse({
name: storage.horseData['horse_' + i + '_name'] || 'Unnamed Horse',
speed: storage.horseData['horse_' + i + '_speed'] || 50,
stamina: storage.horseData['horse_' + i + '_stamina'] || 50,
temperament: storage.horseData['horse_' + i + '_temperament'] || 50,
age: storage.horseData['horse_' + i + '_age'] || 2,
raceWins: storage.horseData['horse_' + i + '_raceWins'] || 0,
value: storage.horseData['horse_' + i + '_value'] || 10000,
currentEnergy: storage.horseData['horse_' + i + '_currentEnergy'] || 100,
maxEnergy: storage.horseData['horse_' + i + '_maxEnergy'] || 100
}));
}
}
}
function getWeatherBonus() {
return weatherSystem.getSpeedModifier() * seasonalBonus;
}
function generateRandomHorseName() {
var names = ['Thunder', 'Lightning', 'Storm', 'Blaze', 'Spirit', 'Shadow', 'Comet', 'Star', 'Flash', 'Dash', 'Wind', 'Fire', 'Rain', 'Snow', 'Frost', 'Dawn', 'Dusk', 'Moon', 'Sun', 'Sky'];
return names[Math.floor(Math.random() * names.length)] + ' ' + Math.floor(Math.random() * 1000);
}
// Load saved progress
loadGameProgress();
// Initialize view
updateView();
// Play background music
LK.playMusic('stableMusic');
// Main game loop with final optimizations
game.update = function () {
gameTime++;
// Validate game state integrity
if (!horses || horses.length < 0) {
horses = [];
}
if (isNaN(money) || money < 0) {
money = 0;
}
if (isNaN(selectedHorseIndex) || selectedHorseIndex >= horses.length) {
selectedHorseIndex = 0;
}
// Update weather every 30 seconds (1800 ticks)
if (gameTime % 1800 === 0) {
if (weatherSystem && weatherSystem.updateWeather) {
weatherSystem.updateWeather();
currentWeather = weatherSystem.currentWeather;
}
}
// Update seasonal bonus
seasonalBonus = Math.sin(gameTime / 10800) * 0.2 + 1.0;
// Race processing with error handling
if (raceInProgress && raceView && raceView.parent) {
try {
// Update player horse markers
for (var i = 0; i < raceView.raceHorses.length; i++) {
var item = raceView.raceHorses[i];
if (item && item.targetHorse && item.targetHorse.x !== undefined) {
// This is a marker, update its position to follow the horse
item.x = item.targetHorse.x;
item.y = item.targetHorse.y - 60;
}
}
// Check race completion
if (raceView.checkRaceFinish && !raceView.raceFinished) {
raceView.checkRaceFinish();
}
} catch (e) {
// Handle race errors gracefully
raceInProgress = false;
currentView = 'stable';
updateView();
}
}
// Auto-rest horses when not racing with validation
if (!raceInProgress && horses) {
for (var i = 0; i < horses.length; i++) {
var horse = horses[i];
if (horse && horse.currentEnergy !== undefined && horse.maxEnergy !== undefined) {
if (horse.currentEnergy < horse.maxEnergy) {
horse.currentEnergy = Math.min(horse.maxEnergy, horse.currentEnergy + 0.1);
}
}
}
}
// Update achievements with error handling
if (achievementSystem && achievementSystem.checkAchievements) {
try {
achievementSystem.checkAchievements();
} catch (e) {
// Ignore achievement errors to prevent game crashes
}
}
// Save progress every 10 seconds with validation
if (gameTime % 600 === 0) {
try {
saveGameProgress();
} catch (e) {
// Handle save errors gracefully
}
}
// Victory condition validation - 25 race wins
if (LK.getScore() >= 25) {
LK.showYouWin();
}
// Game over condition with proper validation
if (money <= 0 && horses.length === 0) {
LK.showGameOver();
}
// Random events with bounds checking
if (gameTime % 3600 === 0 && Math.random() < 0.1) {
// Random bonus money
var bonus = Math.floor(Math.random() * 5000) + 1000;
if (!isNaN(bonus) && bonus > 0) {
money += bonus;
totalEarnings += bonus;
updateMoneyDisplay();
}
}
// Performance optimization - cleanup unused objects
if (gameTime % 1200 === 0) {
// Periodic cleanup for better performance
for (var i = horses.length - 1; i >= 0; i--) {
var horse = horses[i];
if (!horse || horse.age > 30) {
// Remove very old horses to prevent memory issues
if (horse && horse.destroy) {
horse.destroy();
}
horses.splice(i, 1);
}
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Achievement = Container.expand(function () {
var self = Container.call(this);
self.achievements = {
firstWin: {
unlocked: false,
name: 'First Victory',
description: 'Win your first race'
},
tenWins: {
unlocked: false,
name: 'Champion',
description: 'Win 10 races'
},
firstBreed: {
unlocked: false,
name: 'Breeder',
description: 'Breed your first horse'
},
millionaire: {
unlocked: false,
name: 'Millionaire',
description: 'Earn $1,000,000'
},
collector: {
unlocked: false,
name: 'Collector',
description: 'Own 10 horses'
},
trainer: {
unlocked: false,
name: 'Master Trainer',
description: 'Train horses 50 times'
},
speedster: {
unlocked: false,
name: 'Speed Demon',
description: 'Have a horse with 100+ speed'
},
endurance: {
unlocked: false,
name: 'Endurance Master',
description: 'Have a horse with 100+ stamina'
}
};
self.checkAchievements = function () {
// Check first win
if (!self.achievements.firstWin.unlocked && LK.getScore() >= 1) {
self.unlockAchievement('firstWin');
}
// Check ten wins
if (!self.achievements.tenWins.unlocked && LK.getScore() >= 10) {
self.unlockAchievement('tenWins');
}
// Check millionaire
if (!self.achievements.millionaire.unlocked && totalEarnings >= 1000000) {
self.unlockAchievement('millionaire');
}
// Check collector
if (!self.achievements.collector.unlocked && horses.length >= 10) {
self.unlockAchievement('collector');
}
// Check trainer
if (!self.achievements.trainer.unlocked && trainingCount >= 50) {
self.unlockAchievement('trainer');
}
};
self.unlockAchievement = function (id) {
self.achievements[id].unlocked = true;
// Flatten achievements for storage
var flatAchievements = {};
for (var key in self.achievements) {
flatAchievements[key + '_unlocked'] = self.achievements[key].unlocked;
flatAchievements[key + '_name'] = self.achievements[key].name;
flatAchievements[key + '_description'] = self.achievements[key].description;
}
storage.achievements = flatAchievements;
LK.effects.flashScreen(0xffd700, 500);
};
return self;
});
var Help = Container.expand(function () {
var self = Container.call(this);
self.currentSection = 'overview';
self.sections = ['overview', 'horses', 'racing', 'breeding', 'economy', 'tips'];
self.sectionButtons = [];
self.contentText = [];
self.titleText = null;
self.backText = null;
self.helpContent = {
overview: {
en: "Welcome to Thoroughbred Legacy!\n\nThis is an elite horse racing simulation where you manage a stable of champion horses. Your goal is to build the most successful racing empire by breeding, training, and racing horses to victory.\n\nKey Features:\n• Breed and train thoroughbred horses\n• Compete in prestigious tournaments\n• Manage your stable's finances\n• Unlock achievements and upgrades\n• Experience dynamic weather effects",
tr: "Safkan Mirası'na Hoş Geldiniz!\n\nBu, şampiyon atlardan oluşan bir ahır yönettiğiniz elit bir at yarışı simülasyonudur. Amacınız, atları üreterek, eğiterek ve yarıştırarak en başarılı yarış imparatorluğunu kurmaktır.\n\nAna Özellikler:\n• Safkan atları üretin ve eğitin\n• Prestijli turnuvalarda yarışın\n• Ahırınızın finansmanını yönetin\n• Başarıları ve gelişmeleri açın\n• Dinamik hava etkilerini deneyimleyin",
ru: "Добро пожаловать в Наследие Чистокровных!\n\nЭто элитная симуляция скачек, где вы управляете конюшней чемпионских лошадей. Ваша цель - построить самую успешную скаковую империю, разводя, тренируя и участвуя в скачках.\n\nОсновные функции:\n• Разводите и тренируйте чистокровных лошадей\n• Участвуйте в престижных турнирах\n• Управляйте финансами конюшни\n• Открывайте достижения и улучшения\n• Испытайте динамические погодные эффекты"
},
horses: {
en: "Horse Management:\n\nEach horse has unique statistics:\n• Speed - Determines racing velocity\n• Stamina - Affects endurance in races\n• Temperament - Influences consistency\n• Energy - Current condition level\n• Age - Affects performance over time\n\nHorse Care:\n• Feed horses to restore energy\n• Visit veterinarian for health boosts\n• Train regularly to improve stats\n• Rest horses between races\n• Monitor aging effects on performance",
tr: "At Yönetimi:\n\nHer atın benzersiz istatistikleri vardır:\n• Hız - Yarış hızını belirler\n• Dayanıklılık - Yarışlarda dayanıklılığı etkiler\n• Mizaç - Tutarlılığı etkiler\n• Enerji - Mevcut kondisyon seviyesi\n• Yaş - Zaman içinde performansı etkiler\n\nAt Bakımı:\n• Enerjiyi yenilemek için atları besleyin\n• Sağlık artışı için veterinere gidin\n• İstatistikleri geliştirmek için düzenli eğitin\n• Yarışlar arasında atları dinlendirin\n• Yaşlanmanın performans üzerindeki etkilerini izleyin",
ru: "Управление лошадьми:\n\nКаждая лошадь имеет уникальную статистику:\n• Скорость - Определяет скорость в гонке\n• Выносливость - Влияет на выносливость в гонках\n• Темперамент - Влияет на стабильность\n• Энергия - Текущий уровень состояния\n• Возраст - Влияет на производительность со временем\n\nУход за лошадьми:\n• Кормите лошадей для восстановления энергии\n• Посещайте ветеринара для укрепления здоровья\n• Регулярно тренируйтесь для улучшения статистики\n• Давайте лошадям отдыхать между гонками\n• Следите за влиянием старения на производительность"
},
racing: {
en: "Racing System:\n\nRace Types:\n• Quick races for immediate rewards\n• Tournament competitions for big prizes\n• Championship events for prestige\n\nRace Mechanics:\n• Weather affects horse performance\n• Energy levels impact race results\n• Horse stats determine speed potential\n• Random events add excitement\n\nStrategy Tips:\n• Choose well-rested horses\n• Consider weather conditions\n• Match horse strengths to race type\n• Manage energy carefully",
tr: "Yarış Sistemi:\n\nYarış Türleri:\n• Hızlı ödüller için hızlı yarışlar\n• Büyük ödüller için turnuva yarışmaları\n• Prestij için şampiyonluk etkinlikleri\n\nYarış Mekanikleri:\n• Hava durumu at performansını etkiler\n• Enerji seviyeleri yarış sonuçlarını etkiler\n• At istatistikleri hız potansiyelini belirler\n• Rastgele olaylar heyecan katar\n\nStrateji İpuçları:\n• İyi dinlenmiş atları seçin\n• Hava koşullarını göz önünde bulundurun\n• At güçlerini yarış türüne uygun hale getirin\n• Enerjiyi dikkatli yönetin",
ru: "Система гонок:\n\nТипы гонок:\n• Быстрые гонки за немедленные награды\n• Турнирные соревнования за большие призы\n• Чемпионские события за престиж\n\nМеханика гонок:\n• Погода влияет на производительность лошадей\n• Уровни энергии влияют на результаты гонок\n• Статистика лошадей определяет скоростной потенциал\n• Случайные события добавляют волнения\n\nСтратегические советы:\n• Выбирайте отдохнувших лошадей\n• Учитывайте погодные условия\n• Сопоставляйте сильные стороны лошадей с типом гонки\n• Тщательно управляйте энергией"
},
breeding: {
en: "Breeding System:\n\nBreeding Basics:\n• Combine two horses to create offspring\n• Foals inherit parent characteristics\n• Stats are averaged with random variation\n• Better parents produce better foals\n\nBreeding Strategy:\n• Choose complementary parent stats\n• Consider age and performance history\n• Breed champions for superior offspring\n• Maintain genetic diversity\n\nBreeding Costs:\n• Breeding fee: $5,000\n• Veterinary care for pregnant mares\n• Training costs for young horses\n• Time investment for development",
tr: "Üretim Sistemi:\n\nÜretim Temelleri:\n• Yavru oluşturmak için iki atı birleştirin\n• Yavrular ebeveyn özelliklerini miras alır\n• İstatistikler rastgele varyasyonla ortalaması alınır\n• Daha iyi ebeveynler daha iyi yavrular üretir\n\nÜretim Stratejisi:\n• Tamamlayıcı ebeveyn istatistiklerini seçin\n• Yaş ve performans geçmişini göz önünde bulundurun\n• Üstün yavrular için şampiyonları üretin\n• Genetik çeşitliliği koruyun\n\nÜretim Maliyetleri:\n• Üretim ücreti: $5,000\n• Gebe kısraklar için veteriner bakımı\n• Genç atlar için eğitim maliyetleri\n• Gelişim için zaman yatırımı",
ru: "Система разведения:\n\nОсновы разведения:\n• Объедините двух лошадей для создания потомства\n• Жеребята наследуют характеристики родителей\n• Статистика усредняется со случайными вариациями\n• Лучшие родители производят лучших жеребят\n\nСтратегия разведения:\n• Выбирайте дополняющие родительские статистики\n• Учитывайте возраст и историю производительности\n• Разводите чемпионов для превосходного потомства\n• Поддерживайте генетическое разнообразие\n\nЗатраты на разведение:\n• Плата за разведение: $5,000\n• Ветеринарный уход за беременными кобылами\n• Расходы на обучение молодых лошадей\n• Временные инвестиции для развития"
},
economy: {
en: "Economic Management:\n\nIncome Sources:\n• Race winnings (varies by competition)\n• Tournament prizes ($25k - $200k)\n• Breeding services to other stables\n• Selling trained horses\n\nExpenses:\n• Horse training ($1,000 per session)\n• Veterinary care ($1,000 - $5,000)\n• Feeding costs ($500 per meal)\n• Equipment upgrades ($10,000+)\n• Breeding fees ($5,000)\n\nFinancial Tips:\n• Maintain cash reserves for opportunities\n• Invest in profitable horses\n• Balance training costs with results\n• Consider long-term breeding investments",
tr: "Ekonomik Yönetim:\n\nGelir Kaynakları:\n• Yarış kazançları (yarışmaya göre değişir)\n• Turnuva ödülleri ($25k - $200k)\n• Diğer ahırlara üretim hizmetleri\n• Eğitilmiş atları satma\n\nGiderler:\n• At eğitimi (seans başına $1,000)\n• Veteriner bakımı ($1,000 - $5,000)\n• Beslenme maliyetleri (öğün başına $500)\n• Ekipman geliştirmeleri ($10,000+)\n• Üretim ücretleri ($5,000)\n\nFinansal İpuçları:\n• Fırsatlar için nakit rezerv bulundurun\n• Karlı atlara yatırım yapın\n• Eğitim maliyetlerini sonuçlarla dengeleyin\n• Uzun vadeli üretim yatırımlarını düşünün",
ru: "Экономическое управление:\n\nИсточники дохода:\n• Выигрыши в гонках (варьируется в зависимости от соревнования)\n• Призы турниров ($25k - $200k)\n• Услуги разведения для других конюшен\n• Продажа обученных лошадей\n\nРасходы:\n• Тренировка лошадей ($1,000 за сессию)\n• Ветеринарная помощь ($1,000 - $5,000)\n• Расходы на кормление ($500 за прием пищи)\n• Обновления оборудования ($10,000+)\n• Плата за разведение ($5,000)\n\nФинансовые советы:\n• Поддерживайте денежные резервы для возможностей\n• Инвестируйте в прибыльных лошадей\n• Балансируйте затраты на обучение с результатами\n• Рассмотрите долгосрочные инвестиции в разведение"
},
tips: {
en: "Advanced Tips & Strategies:\n\nOptimal Training:\n• Train horses when energy is high\n• Focus on weak stats for balanced development\n• Don't overtrain - rest is important\n• Monitor age-related stat declines\n\nRace Strategy:\n• Save your best horses for tournaments\n• Consider weather effects on performance\n• Match horse types to race distances\n• Build experience gradually\n\nLong-term Success:\n• Invest in breeding superior bloodlines\n• Diversify your stable portfolio\n• Plan for horse retirement\n• Maintain steady income streams\n• Unlock all achievements for bonuses",
tr: "Gelişmiş İpuçları ve Stratejiler:\n\nOptimal Eğitim:\n• Enerji yüksekken atları eğitin\n• Dengeli gelişim için zayıf istatistiklere odaklanın\n• Aşırı eğitim yapmayın - dinlenme önemlidir\n• Yaşa bağlı istatistik düşüşlerini izleyin\n\nYarış Stratejisi:\n• En iyi atlarınızı turnuvalar için saklayın\n• Hava etkilerini performans üzerinde düşünün\n• At türlerini yarış mesafelerine uygun hale getirin\n• Deneyimi kademeli olarak artırın\n\nUzun vadeli Başarı:\n• Üstün kan hatlarını üretmeye yatırım yapın\n• Ahır portföyünüzü çeşitlendirin\n• At emekliliği için plan yapın\n• Sabit gelir akışları sürdürün\n• Bonuslar için tüm başarıları açın",
ru: "Продвинутые советы и стратегии:\n\nОптимальная тренировка:\n• Тренируйте лошадей при высокой энергии\n• Сосредоточьтесь на слабых статистиках для сбалансированного развития\n• Не перетренируйтесь - отдых важен\n• Следите за возрастными снижениями статистики\n\nСтратегия гонок:\n• Сохраните лучших лошадей для турниров\n• Учитывайте влияние погоды на производительность\n• Сопоставьте типы лошадей с дистанциями гонок\n• Постепенно накапливайте опыт\n\nДолгосрочный успех:\n• Инвестируйте в разведение превосходных родословных\n• Диверсифицируйте портфель конюшни\n• Планируйте выход лошадей на пенсию\n• Поддерживайте стабильные потоки доходов\n• Разблокируйте все достижения для бонусов"
}
};
self.setupUI = function () {
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
self.titleText = new Text2('', {
size: 80,
fill: '#ecf0f1'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 200;
self.addChild(self.titleText);
// Section buttons
for (var i = 0; i < self.sections.length; i++) {
var section = self.sections[i];
var sectionBtn = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 200 + i % 3 * 300,
y: 350 + Math.floor(i / 3) * 100
});
var sectionText = new Text2(section.toUpperCase(), {
size: 24,
fill: '#ffffff'
});
sectionText.anchor.set(0.5, 0.5);
sectionText.x = 200 + i % 3 * 300;
sectionText.y = 350 + Math.floor(i / 3) * 100;
sectionText.sectionId = section;
self.addChild(sectionText);
self.sectionButtons.push({
button: sectionBtn,
text: sectionText,
section: section,
x: 200 + i % 3 * 300,
y: 350 + Math.floor(i / 3) * 100
});
}
self.refreshContent();
self.backText = new Text2('', {
size: 45,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2500;
self.addChild(self.backText);
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2500
});
};
self.refreshContent = function () {
// Clear existing content
for (var i = 0; i < self.contentText.length; i++) {
if (self.contentText[i].destroy) {
self.contentText[i].destroy();
}
}
self.contentText = [];
var content = self.helpContent[self.currentSection][currentLanguage] || self.helpContent[self.currentSection]['en'];
var lines = content.split('\n');
var yPos = 600;
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
if (line.length === 0) {
yPos += 20;
continue;
}
// Handle long lines by wrapping text
var maxLineLength = 70;
if (line.length > maxLineLength && line.indexOf('•') !== 0) {
var words = line.split(' ');
var currentLine = '';
for (var w = 0; w < words.length; w++) {
if ((currentLine + words[w]).length > maxLineLength) {
if (currentLine.length > 0) {
var wrappedLine = new Text2(currentLine.trim(), {
size: 30,
fill: '#ffffff'
});
wrappedLine.anchor.set(0.5, 0.5);
wrappedLine.x = 1024;
wrappedLine.y = yPos;
self.addChild(wrappedLine);
self.contentText.push(wrappedLine);
yPos += 35;
}
currentLine = words[w] + ' ';
} else {
currentLine += words[w] + ' ';
}
}
if (currentLine.trim().length > 0) {
var finalLine = new Text2(currentLine.trim(), {
size: 30,
fill: '#ffffff'
});
finalLine.anchor.set(0.5, 0.5);
finalLine.x = 1024;
finalLine.y = yPos;
self.addChild(finalLine);
self.contentText.push(finalLine);
yPos += 35;
}
} else {
var fontSize = line.indexOf('•') === 0 ? 28 : line.indexOf(':') > 0 ? 34 : 30;
var textColor = line.indexOf(':') > 0 ? '#3498db' : '#ffffff';
var contentLine = new Text2(line, {
size: fontSize,
fill: textColor
});
contentLine.anchor.set(0.5, 0.5);
contentLine.x = 1024;
contentLine.y = yPos;
self.addChild(contentLine);
self.contentText.push(contentLine);
yPos += fontSize + 15;
}
}
};
self.updateLanguage = function () {
if (self.titleText) {
self.titleText.setText(translations[currentLanguage].help || 'HELP & GUIDE');
}
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'BACK');
}
self.refreshContent();
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check section buttons
for (var i = 0; i < self.sectionButtons.length; i++) {
var btn = self.sectionButtons[i];
if (localPos.x >= btn.x - 125 && localPos.x <= btn.x + 125 && localPos.y >= btn.y - 60 && localPos.y <= btn.y + 60) {
self.currentSection = btn.section;
self.refreshContent();
LK.getSound('buttonClick').play();
break;
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2440 && localPos.y <= 2560) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Horse = Container.expand(function (config) {
var self = Container.call(this);
config = config || {};
// Horse stats
self.name = config.name || 'Unnamed Horse';
self.speed = config.speed || Math.random() * 50 + 50;
self.stamina = config.stamina || Math.random() * 50 + 50;
self.temperament = config.temperament || Math.random() * 50 + 50;
self.age = config.age || 2;
self.raceWins = config.raceWins || 0;
self.value = config.value || 10000;
self.currentEnergy = 100;
self.maxEnergy = 100;
// Visual representation
var horseBody = self.attachAsset('horse', {
anchorX: 0.5,
anchorY: 0.5
});
var jockeySprite = self.attachAsset('jockey', {
anchorX: 0.5,
anchorY: 0.5,
y: -20
});
// Racing properties
self.racePosition = 0;
self.raceSpeed = 0;
self.isRacing = false;
self.train = function (type) {
switch (type) {
case 'speed':
self.speed += Math.random() * 5 + 2;
break;
case 'stamina':
self.stamina += Math.random() * 5 + 2;
break;
case 'temperament':
self.temperament += Math.random() * 5 + 2;
break;
}
self.currentEnergy = Math.max(0, self.currentEnergy - 20);
};
self.rest = function () {
self.currentEnergy = Math.min(self.maxEnergy, self.currentEnergy + 30);
};
self.breed = function (partner) {
var offspring = new Horse({
speed: (self.speed + partner.speed) / 2 + (Math.random() - 0.5) * 20,
stamina: (self.stamina + partner.stamina) / 2 + (Math.random() - 0.5) * 20,
temperament: (self.temperament + partner.temperament) / 2 + (Math.random() - 0.5) * 20,
age: 0,
name: 'Foal ' + Math.floor(Math.random() * 1000)
});
breedingCount++;
if (breedingCount === 1 && achievementSystem) {
achievementSystem.achievements.firstBreed.unlocked = true;
}
return offspring;
};
self.getRaceSpeed = function () {
var energyFactor = self.currentEnergy / self.maxEnergy;
return (self.speed * 0.6 + self.stamina * 0.4) * energyFactor;
};
self.update = function () {
if (self.isRacing) {
self.raceSpeed = self.getRaceSpeed() * (0.8 + Math.random() * 0.4);
self.racePosition += self.raceSpeed * 0.1;
// Calculate circular track position for larger track
var trackCenterX = 1024;
var trackCenterY = 1366;
var trackRadius = 700; // Increased for larger track
// Convert linear race position to angle (0 to 2*PI for full lap)
var raceAngle = self.racePosition / 2000 * Math.PI * 2;
// Check for lap completion
var newLap = Math.floor(self.racePosition / 2000);
if (newLap > self.lapsCompleted) {
self.lapsCompleted = newLap;
}
// Calculate horse position with increased lane spacing
var laneOffset = self.laneNumber * 50; // Increased from 25 to 50px between lanes
var currentRadius = trackRadius + laneOffset;
// Add slight natural variation to make racing look more realistic
var naturalVariation = Math.sin(self.racePosition * 0.02) * 5;
currentRadius += naturalVariation;
self.x = trackCenterX + Math.cos(raceAngle) * currentRadius;
self.y = trackCenterY + Math.sin(raceAngle) * currentRadius;
// Adjust horse rotation to face direction of movement (tangent to circle)
self.rotation = raceAngle + Math.PI / 2;
// Simple energy drain during race
self.currentEnergy = Math.max(0, self.currentEnergy - 0.2);
}
};
return self;
});
var MainMenu = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2('', {
size: 80,
fill: '#ffffff'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 500;
self.addChild(titleText);
var playBtn = self.attachAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1000
});
var playText = new Text2('', {
size: 50,
fill: '#ffffff'
});
playText.anchor.set(0.5, 0.5);
playText.x = 1024;
playText.y = 1000;
self.addChild(playText);
var tournamentBtn = self.attachAsset('tournamentButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1150
});
var tournamentText = new Text2('', {
size: 45,
fill: '#ffffff'
});
tournamentText.anchor.set(0.5, 0.5);
tournamentText.x = 1024;
tournamentText.y = 1150;
self.addChild(tournamentText);
var shopBtn = self.attachAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1300
});
var shopText = new Text2('', {
size: 45,
fill: '#ffffff'
});
shopText.anchor.set(0.5, 0.5);
shopText.x = 1024;
shopText.y = 1300;
self.addChild(shopText);
var settingsBtn = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1450
});
var settingsText = new Text2('', {
size: 45,
fill: '#ffffff'
});
settingsText.anchor.set(0.5, 0.5);
settingsText.x = 1024;
settingsText.y = 1450;
self.addChild(settingsText);
var helpBtn = self.attachAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1600
});
var helpText = new Text2('', {
size: 45,
fill: '#ffffff'
});
helpText.anchor.set(0.5, 0.5);
helpText.x = 1024;
helpText.y = 1600;
self.addChild(helpText);
self.updateLanguage = function () {
titleText.setText(translations[currentLanguage].title);
playText.setText(translations[currentLanguage].play);
tournamentText.setText(translations[currentLanguage].tournament);
shopText.setText(translations[currentLanguage].shop);
settingsText.setText(translations[currentLanguage].settings);
helpText.setText(translations[currentLanguage].help);
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check play button
if (localPos.x >= 774 && localPos.x <= 1274 && localPos.y >= 940 && localPos.y <= 1060) {
currentView = 'stable';
updateView();
LK.getSound('buttonClick').play();
}
// Check tournament button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1090 && localPos.y <= 1210) {
currentView = 'tournament';
updateView();
LK.getSound('buttonClick').play();
}
// Check shop button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1240 && localPos.y <= 1360) {
currentView = 'shop';
updateView();
LK.getSound('buttonClick').play();
}
// Check settings button
if (localPos.x >= 799 && localPos.x <= 1249 && localPos.y >= 1390 && localPos.y <= 1510) {
currentView = 'settings';
updateView();
LK.getSound('buttonClick').play();
}
// Check help button
if (localPos.x >= 799 && localPos.x <= 1249 && localPos.y >= 1540 && localPos.y <= 1660) {
currentView = 'help';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var RaceView = Container.expand(function () {
var self = Container.call(this);
// Create larger circular race track with improved visuals
var trackOuter = self.attachAsset('circularTrack', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.4,
scaleY: 1.4
});
var trackInner = self.attachAsset('trackInner', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 1.4,
scaleY: 1.4
});
// Add lane markers for better visual separation with increased spacing
for (var i = 1; i < 6; i++) {
var laneMarker = self.attachAsset('startFinishLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + (630 + i * 50),
// Increased spacing from 25 to 50
y: 1366
});
laneMarker.rotation = Math.PI / 2;
laneMarker.alpha = 0.3;
laneMarker.scaleY = 0.3;
}
var finishLine = self.attachAsset('startFinishLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024 + 700,
// Adjusted for larger track
y: 1366
});
finishLine.scaleY = 2;
finishLine.tint = 0xff0000; // Red finish line
var raceTitle = new Text2('RACE IN PROGRESS', {
size: 50,
fill: '#ffffff'
});
raceTitle.anchor.set(0.5, 0.5);
raceTitle.x = 1024;
raceTitle.y = 200;
self.addChild(raceTitle);
var trackInfo = new Text2('Championship Circular Track - Complete One Lap', {
size: 30,
fill: '#ffff00'
});
trackInfo.anchor.set(0.5, 0.5);
trackInfo.x = 1024;
trackInfo.y = 250;
self.addChild(trackInfo);
self.raceHorses = [];
self.setupRace = function () {
// Reset race state completely
self.raceFinished = false;
// Clear existing race horses
for (var i = 0; i < self.raceHorses.length; i++) {
if (self.raceHorses[i].destroy) {
self.raceHorses[i].destroy();
}
}
self.raceHorses = [];
// Add player's horses and AI horses
var raceHorsesList = [];
// Add selected player horse
if (horses.length > 0) {
var selectedHorse = horses[selectedHorseIndex || 0];
raceHorsesList.push(selectedHorse);
}
// Add AI horses to fill up to 6 total
while (raceHorsesList.length < 6) {
var aiHorse = new Horse({
name: 'AI Horse ' + (raceHorsesList.length + 1),
speed: Math.random() * 40 + 60,
stamina: Math.random() * 40 + 60,
temperament: Math.random() * 40 + 60
});
raceHorsesList.push(aiHorse);
}
// Position horses at start line on larger circular track
var trackCenterX = 1024;
var trackCenterY = 1366;
var trackRadius = 700; // Increased for larger track
for (var i = 0; i < raceHorsesList.length; i++) {
var horse = raceHorsesList[i];
// Assign lane number for proper spacing
horse.laneNumber = i;
horse.isPlayerHorse = false;
horse.lapsCompleted = 0;
// Check if this is a player horse
for (var j = 0; j < horses.length; j++) {
if (horses[j] === horse) {
horse.isPlayerHorse = true;
break;
}
}
// Position horses at starting line with increased lane spacing
var startRadius = trackRadius + i * 50; // Increased from 25 to 50px between lanes
horse.x = trackCenterX + startRadius;
horse.y = trackCenterY;
horse.racePosition = 0;
horse.isRacing = true;
horse.currentEnergy = horse.maxEnergy;
horse.rotation = Math.PI / 2; // Face forward initially
self.addChild(horse);
self.raceHorses.push(horse);
// Add yellow star marker for player horses
if (horse.isPlayerHorse) {
var marker = self.attachAsset('gemIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: horse.x,
y: horse.y - 80
});
marker.targetHorse = horse;
marker.tint = 0xFFD700; // Yellow star for player horse
marker.scaleX = 1.2;
marker.scaleY = 1.2;
self.raceHorses.push(marker);
}
}
};
self.checkRaceFinish = function () {
// Don't check if race is already finished
if (self.raceFinished) {
return true;
}
// Validate race horses array
if (!self.raceHorses || self.raceHorses.length === 0) {
return false;
}
for (var i = 0; i < self.raceHorses.length; i++) {
var horse = self.raceHorses[i];
// Only check actual horses, not markers, with validation
if (horse && horse.racePosition !== undefined && horse.racePosition >= 2000 && !self.raceFinished) {
// Race finished - single lap (2000)
try {
self.finishRace(horse);
return true;
} catch (e) {
// Handle race finish errors
self.raceFinished = true;
return true;
}
}
}
return false;
};
self.raceFinished = false;
self.finishRace = function (winner) {
// Prevent multiple race finish triggers
if (self.raceFinished) {
return;
}
self.raceFinished = true;
// Stop all horses
for (var i = 0; i < self.raceHorses.length; i++) {
self.raceHorses[i].isRacing = false;
}
// Check if winner is player's horse
var isPlayerWinner = false;
for (var i = 0; i < horses.length; i++) {
if (horses[i] === winner) {
isPlayerWinner = true;
winner.raceWins++;
break;
}
}
// Award money based on tournament or regular race - only once
var prize = 0;
if (tournamentSystem.currentTournament) {
if (isPlayerWinner) {
prize = tournamentSystem.currentTournament.prize;
tournamentSystem.completeTournament();
} else {
prize = Math.floor(tournamentSystem.currentTournament.prize * 0.1); // Small participation prize
}
} else {
if (isPlayerWinner) {
prize = 10000;
LK.setScore(LK.getScore() + 1);
LK.getSound('crowdCheer').play();
} else {
prize = 2000; // Participation prize
}
}
// Only award money once
money += prize;
totalEarnings += prize;
updateMoneyDisplay();
// Clear race state to prevent further money awards
for (var i = 0; i < self.raceHorses.length; i++) {
self.raceHorses[i].racePosition = 0;
}
// Return to stable after 3 seconds
LK.setTimeout(function () {
currentView = 'stable';
updateView();
}, 3000);
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('settingsBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var panel = self.attachAsset('settingsPanel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2('', {
size: 80,
fill: '#ecf0f1'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
self.addChild(titleText);
var languageLabel = new Text2('', {
size: 50,
fill: '#3498db'
});
languageLabel.anchor.set(0.5, 0.5);
languageLabel.x = 1024;
languageLabel.y = 500;
self.addChild(languageLabel);
// Language data with flag colors
var languages = [{
name: 'English',
code: 'en',
flag: 0xff0000
}, {
name: 'Русский',
code: 'ru',
flag: 0x0080ff
}, {
name: 'Français',
code: 'fr',
flag: 0x0000ff
}, {
name: 'Türkçe',
code: 'tr',
flag: 0xff0000
}, {
name: 'Español',
code: 'es',
flag: 0xffff00
}, {
name: 'Deutsch',
code: 'de',
flag: 0x000000
}, {
name: '中文',
code: 'zh',
flag: 0xff0000
}, {
name: '日本語',
code: 'ja',
flag: 0xff0000
}, {
name: 'Italiano',
code: 'it',
flag: 0x00ff00
}, {
name: 'Português',
code: 'pt',
flag: 0x00ff00
}];
self.languageButtons = [];
for (var i = 0; i < languages.length; i++) {
var lang = languages[i];
var isSelected = currentLanguage === lang.code;
var btnAsset = isSelected ? 'selectedLanguage' : 'languageButton';
var langBtn = self.attachAsset(btnAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 350 + i % 4 * 350,
y: 700 + Math.floor(i / 4) * 150
});
var flagIcon = self.attachAsset('languageFlag', {
anchorX: 0.5,
anchorY: 0.5,
x: 250 + i % 4 * 350,
y: 700 + Math.floor(i / 4) * 150
});
flagIcon.tint = lang.flag;
var langText = new Text2(lang.name, {
size: 26,
fill: isSelected ? '#f1c40f' : '#ffffff'
});
langText.anchor.set(0.5, 0.5);
langText.x = 380 + i % 4 * 350;
langText.y = 700 + Math.floor(i / 4) * 150;
langText.langCode = lang.code;
self.addChild(langText);
self.languageButtons.push({
button: langBtn,
flag: flagIcon,
text: langText,
code: lang.code,
x: 350 + i % 4 * 350,
y: 700 + Math.floor(i / 4) * 150
});
}
// Audio settings
var audioLabel = new Text2('Audio Settings', {
size: 45,
fill: '#e67e22'
});
audioLabel.anchor.set(0.5, 0.5);
audioLabel.x = 1024;
audioLabel.y = 1400;
self.addChild(audioLabel);
var volumeLabel = new Text2('Master Volume: 100%', {
size: 35,
fill: '#95a5a6'
});
volumeLabel.anchor.set(0.5, 0.5);
volumeLabel.x = 1024;
volumeLabel.y = 1500;
self.addChild(volumeLabel);
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1700
});
var backText = new Text2('', {
size: 40,
fill: '#ffffff'
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1700;
self.addChild(backText);
self.updateLanguage = function () {
titleText.setText(translations[currentLanguage].settings || 'SETTINGS');
languageLabel.setText(translations[currentLanguage].language || 'Choose Language:');
backText.setText(translations[currentLanguage].back || 'BACK');
// Update button selection
for (var i = 0; i < self.languageButtons.length; i++) {
var btn = self.languageButtons[i];
var isSelected = currentLanguage === btn.code;
btn.text.fill = isSelected ? '#f1c40f' : '#ffffff';
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check language buttons
for (var i = 0; i < self.languageButtons.length; i++) {
var btn = self.languageButtons[i];
if (localPos.x >= btn.x - 210 && localPos.x <= btn.x + 210 && localPos.y >= btn.y - 60 && localPos.y <= btn.y + 60) {
if (currentLanguage !== btn.code) {
currentLanguage = btn.code;
storage.language = currentLanguage;
updateAllLanguages();
LK.getSound('buttonClick').play();
LK.effects.flashScreen(0x3498db, 200);
// Refresh UI to update selection
currentView = 'settings';
updateView();
}
break;
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 1640 && localPos.y <= 1760) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Shop = Container.expand(function () {
var self = Container.call(this);
self.currentCategory = 'basic';
self.categories = ['basic', 'premium', 'legendary'];
self.categoryButtons = [];
self.itemButtons = [];
self.items = {
basic: {
feed: {
name: 'Premium Feed',
price: 5000,
effect: 'energy',
description: 'Restores horse energy',
icon: 'speedBoost'
},
medicine: {
name: 'Energy Boost',
price: 8000,
effect: 'health',
description: 'Increases max energy',
icon: 'healthBoost'
},
vitamins: {
name: 'Vitamins',
price: 10000,
effect: 'stamina',
description: 'Improves stamina',
icon: 'staminaBoost'
}
},
premium: {
equipment: {
name: 'Racing Equipment',
price: 15000,
effect: 'speed',
description: 'Professional racing gear',
icon: 'speedBoost'
},
training: {
name: 'Advanced Training',
price: 20000,
effect: 'training',
description: 'Elite training program',
icon: 'staminaBoost'
},
superFeed: {
name: 'Super Feed',
price: 25000,
effect: 'superEnergy',
description: 'Premium nutrition boost',
icon: 'healthBoost'
}
},
legendary: {
geneticBoost: {
name: 'Genetic Enhancement',
price: 100000,
effect: 'genetic',
description: 'Permanent stat boost',
icon: 'gemIcon'
},
championGear: {
name: 'Champion Gear',
price: 150000,
effect: 'champion',
description: 'Legendary equipment set',
icon: 'speedBoost'
},
immortalElixir: {
name: 'Immortal Elixir',
price: 200000,
effect: 'immortal',
description: 'Stops aging process',
icon: 'healthBoost'
}
}
};
self.setupUI = function () {
var background = self.attachAsset('shopBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2(translations[currentLanguage].shop || 'Elite Horse Shop', {
size: 90,
fill: '#ecf0f1'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 250;
self.addChild(titleText);
// Category buttons
for (var i = 0; i < self.categories.length; i++) {
var category = self.categories[i];
var categoryBtn = self.attachAsset('shopButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 400 + i * 400,
y: 400
});
var categoryText = new Text2(category.toUpperCase(), {
size: 35,
fill: '#ffffff'
});
categoryText.anchor.set(0.5, 0.5);
categoryText.x = 400 + i * 400;
categoryText.y = 400;
categoryText.categoryId = category;
self.addChild(categoryText);
self.categoryButtons.push({
button: categoryBtn,
text: categoryText,
category: category
});
}
self.refreshItems();
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2400
});
var backText = new Text2(translations[currentLanguage].back || 'Back', {
size: 45,
fill: '#ffffff'
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2400;
self.addChild(backText);
};
self.refreshItems = function () {
// Clear existing item buttons
for (var i = 0; i < self.itemButtons.length; i++) {
if (self.itemButtons[i].destroy) {
self.itemButtons[i].destroy();
}
}
self.itemButtons = [];
var items = self.items[self.currentCategory];
var yPos = 600;
var itemIndex = 0;
for (var itemId in items) {
var item = items[itemId];
var cardType = self.currentCategory === 'legendary' ? 'legendaryItem' : self.currentCategory === 'premium' ? 'premiumItem' : 'itemCard';
var itemCard = self.attachAsset(cardType, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos
});
var itemIcon = self.attachAsset(item.icon, {
anchorX: 0.5,
anchorY: 0.5,
x: 650,
y: yPos
});
var itemText = new Text2(item.name, {
size: 40,
fill: '#ffffff'
});
itemText.anchor.set(0, 0.5);
itemText.x = 750;
itemText.y = yPos - 30;
self.addChild(itemText);
var priceText = new Text2('$' + item.price, {
size: 35,
fill: '#f1c40f'
});
priceText.anchor.set(0, 0.5);
priceText.x = 750;
priceText.y = yPos;
self.addChild(priceText);
var descText = new Text2(item.description, {
size: 28,
fill: '#bdc3c7'
});
descText.anchor.set(0, 0.5);
descText.x = 750;
descText.y = yPos + 35;
self.addChild(descText);
self.itemButtons.push({
card: itemCard,
icon: itemIcon,
itemId: itemId,
y: yPos
});
yPos += 220;
itemIndex++;
}
};
self.purchaseItem = function (itemId) {
var item = self.items[self.currentCategory][itemId];
if (money >= item.price) {
money -= item.price;
totalEarnings += item.price;
self.applyItemEffect(item.effect, item);
updateMoneyDisplay();
LK.getSound('coinSound').play();
LK.effects.flashScreen(0x00ff00, 300);
return true;
}
return false;
};
self.applyItemEffect = function (effect, item) {
if (horses.length > 0) {
var horse = horses[selectedHorseIndex || 0];
switch (effect) {
case 'energy':
horse.currentEnergy = horse.maxEnergy;
break;
case 'health':
horse.maxEnergy += 15;
break;
case 'speed':
horse.speed += 8;
break;
case 'stamina':
horse.stamina += 8;
break;
case 'training':
horse.train('speed');
horse.train('stamina');
horse.train('temperament');
break;
case 'superEnergy':
horse.currentEnergy = horse.maxEnergy;
horse.maxEnergy += 25;
break;
case 'genetic':
horse.speed += 20;
horse.stamina += 20;
horse.temperament += 20;
break;
case 'champion':
horse.speed += 15;
horse.stamina += 15;
horse.value *= 2;
break;
case 'immortal':
horse.age = Math.max(2, horse.age - 5);
horse.maxEnergy += 50;
break;
}
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check category buttons
for (var i = 0; i < self.categoryButtons.length; i++) {
var btnX = 400 + i * 400;
var btnY = 400;
if (localPos.x >= btnX - 240 && localPos.x <= btnX + 240 && localPos.y >= btnY - 70 && localPos.y <= btnY + 70) {
self.currentCategory = self.categoryButtons[i].category;
self.refreshItems();
LK.getSound('buttonClick').play();
break;
}
}
// Check item buttons
for (var i = 0; i < self.itemButtons.length; i++) {
var item = self.itemButtons[i];
if (localPos.x >= 724 && localPos.x <= 1324 && localPos.y >= item.y - 100 && localPos.y <= item.y + 100) {
if (self.purchaseItem(item.itemId)) {
self.refreshItems();
}
break;
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2330 && localPos.y <= 2470) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var StableView = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('stableBox', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
var titleText = new Text2('Your Stable', {
size: 60,
fill: '#ffffff'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 300;
self.addChild(titleText);
// Action buttons - First row
var breedBtn = self.attachAsset('breedButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 512,
y: 1800
});
var breedText = new Text2('BREED', {
size: 35,
fill: '#ffffff'
});
breedText.anchor.set(0.5, 0.5);
breedText.x = 512;
breedText.y = 1800;
self.addChild(breedText);
var trainBtn = self.attachAsset('trainButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1800
});
var trainText = new Text2('TRAIN', {
size: 35,
fill: '#ffffff'
});
trainText.anchor.set(0.5, 0.5);
trainText.x = 1024;
trainText.y = 1800;
self.addChild(trainText);
var raceBtn = self.attachAsset('raceButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1536,
y: 1800
});
var raceText = new Text2('RACE', {
size: 35,
fill: '#ffffff'
});
raceText.anchor.set(0.5, 0.5);
raceText.x = 1536;
raceText.y = 1800;
self.addChild(raceText);
// Action buttons - Second row
var vetBtn = self.attachAsset('vetButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 512,
y: 1950
});
var vetText = new Text2('VET', {
size: 35,
fill: '#ffffff'
});
vetText.anchor.set(0.5, 0.5);
vetText.x = 512;
vetText.y = 1950;
self.addChild(vetText);
var feedBtn = self.attachAsset('feedButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1950
});
var feedText = new Text2('FEED', {
size: 35,
fill: '#ffffff'
});
feedText.anchor.set(0.5, 0.5);
feedText.x = 1024;
feedText.y = 1950;
self.addChild(feedText);
var upgradeBtn = self.attachAsset('upgradeButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1536,
y: 1950
});
var upgradeText = new Text2('UPGRADE', {
size: 35,
fill: '#ffffff'
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = 1536;
upgradeText.y = 1950;
self.addChild(upgradeText);
// Add back button to return to main menu
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
self.backText = new Text2('BACK TO MENU', {
size: 35,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2200;
self.addChild(self.backText);
self.horseIcons = [];
self.selectedHorseForRace = 0;
self.backText = null;
self.updateHorseDisplay = function () {
// Clear existing icons
for (var i = 0; i < self.horseIcons.length; i++) {
self.horseIcons[i].destroy();
}
self.horseIcons = [];
// Add current horses
for (var i = 0; i < horses.length; i++) {
var horse = horses[i];
var isSelected = i === self.selectedHorseForRace;
var icon = self.attachAsset('horseIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 600 + i % 3 * 200,
y: 500 + Math.floor(i / 3) * 120,
tint: isSelected ? 0xFFD700 : 0xFFFFFF
});
// Add selection star for selected horse
if (isSelected) {
var selectionStar = self.attachAsset('gemIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 600 + i % 3 * 200,
y: 460 + Math.floor(i / 3) * 120,
tint: 0xFFD700,
scaleX: 0.8,
scaleY: 0.8
});
self.horseIcons.push(selectionStar);
}
var nameText = new Text2(horse.name, {
size: 20,
fill: isSelected ? '#FFD700' : '#ffffff'
});
nameText.anchor.set(0.5, 0.5);
nameText.x = 600 + i % 3 * 200;
nameText.y = 550 + Math.floor(i / 3) * 120;
self.addChild(nameText);
var energyPercent = Math.floor(horse.currentEnergy / horse.maxEnergy * 100);
var energyColor = energyPercent > 70 ? '#00FF00' : energyPercent > 30 ? '#FFFF00' : '#FF0000';
var statsText = new Text2('Speed: ' + Math.floor(horse.speed) + ' Energy: ' + energyPercent + '%', {
size: 16,
fill: energyColor
});
statsText.anchor.set(0.5, 0.5);
statsText.x = 600 + i % 3 * 200;
statsText.y = 570 + Math.floor(i / 3) * 120;
self.addChild(statsText);
icon.horseIndex = i;
self.horseIcons.push(icon);
}
};
self.updateLanguage = function () {
titleText.setText(translations[currentLanguage].yourStable);
breedText.setText(translations[currentLanguage].breed);
trainText.setText(translations[currentLanguage].train);
raceText.setText(translations[currentLanguage].race);
vetText.setText(translations[currentLanguage].vet);
feedText.setText(translations[currentLanguage].feed);
upgradeText.setText(translations[currentLanguage].upgrade);
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'BACK TO MENU');
}
};
self.down = function (x, y, obj) {
// Safety check for obj.parent
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check breed button with validation
if (localPos.x >= 312 && localPos.x <= 712 && localPos.y >= 1740 && localPos.y <= 1860) {
if (horses && horses.length >= 2 && money >= 5000 && horses[0] && horses[1]) {
try {
var offspring = horses[0].breed(horses[1]);
if (offspring) {
horses.push(offspring);
money -= 5000;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('buttonClick').play();
}
} catch (e) {
// Handle breeding errors
LK.effects.flashScreen(0xff0000, 300);
}
} else if (money < 5000) {
LK.effects.flashScreen(0xff0000, 300);
} else if (horses.length < 2) {
LK.effects.flashScreen(0xff0000, 300);
}
}
// Check train button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1740 && localPos.y <= 1860) {
if (horses.length > 0 && money >= 1000) {
horses[selectedHorseIndex || 0].train('speed');
money -= 1000;
trainingCount++;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('training').play();
} else if (money < 1000) {
LK.effects.flashScreen(0xff0000, 300);
}
}
// Check horse selection
for (var i = 0; i < self.horseIcons.length; i++) {
var icon = self.horseIcons[i];
if (icon.horseIndex !== undefined) {
var horseX = 600 + icon.horseIndex % 3 * 200;
var horseY = 500 + Math.floor(icon.horseIndex / 3) * 120;
if (localPos.x >= horseX - 60 && localPos.x <= horseX + 60 && localPos.y >= horseY - 50 && localPos.y <= horseY + 50) {
self.selectedHorseForRace = icon.horseIndex;
selectedHorseIndex = icon.horseIndex;
self.updateHorseDisplay();
LK.getSound('buttonClick').play();
break;
}
}
}
// Check race button
if (localPos.x >= 1336 && localPos.x <= 1736 && localPos.y >= 1740 && localPos.y <= 1860) {
if (horses.length > 0) {
// Ensure selected horse has enough energy
var selectedHorse = horses[selectedHorseIndex || 0];
if (selectedHorse.currentEnergy >= 30) {
currentView = 'race';
updateView();
LK.getSound('buttonClick').play();
} else {
LK.effects.flashScreen(0xff0000, 300);
}
}
}
// Check vet button
if (localPos.x >= 312 && localPos.x <= 712 && localPos.y >= 1890 && localPos.y <= 2010) {
if (horses.length > 0) {
currentView = 'vet';
updateView();
LK.getSound('buttonClick').play();
}
}
// Check feed button
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= 1890 && localPos.y <= 2010) {
if (horses.length > 0 && money >= 500) {
horses[0].currentEnergy = Math.min(horses[0].maxEnergy, horses[0].currentEnergy + 50);
money -= 500;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('buttonClick').play();
}
}
// Check upgrade button
if (localPos.x >= 1336 && localPos.x <= 1736 && localPos.y >= 1890 && localPos.y <= 2010) {
if (horses.length > 0 && money >= 10000) {
horses[0].speed += 5;
horses[0].stamina += 5;
money -= 10000;
self.updateHorseDisplay();
updateMoneyDisplay();
LK.getSound('buttonClick').play();
}
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2140 && localPos.y <= 2260) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Tournament = Container.expand(function () {
var self = Container.call(this);
self.tournaments = [{
name: 'Spring Classic',
prize: 25000,
difficulty: 'easy',
entryFee: 2000
}, {
name: 'Summer Championship',
prize: 50000,
difficulty: 'medium',
entryFee: 5000
}, {
name: 'Grand Prix',
prize: 100000,
difficulty: 'hard',
entryFee: 10000
}, {
name: 'Ultimate Derby',
prize: 200000,
difficulty: 'extreme',
entryFee: 20000
}];
self.currentTournament = null;
self.tournamentProgress = 0;
self.titleText = null;
self.backText = null;
self.setupUI = function () {
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
self.titleText = new Text2(translations[currentLanguage].tournaments || 'Tournaments', {
size: 80,
fill: '#ffffff'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 300;
self.addChild(self.titleText);
var yPos = 600;
for (var i = 0; i < self.tournaments.length; i++) {
var tournament = self.tournaments[i];
var tournamentBtn = self.attachAsset('tournamentButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos
});
var tournamentText = new Text2(tournament.name + ' - Prize: $' + tournament.prize, {
size: 28,
fill: '#ffffff'
});
tournamentText.anchor.set(0.5, 0.5);
tournamentText.x = 1024;
tournamentText.y = yPos;
self.addChild(tournamentText);
yPos += 150;
}
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
self.backText = new Text2(translations[currentLanguage].back || 'Back', {
size: 40,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2200;
self.addChild(self.backText);
};
self.updateLanguage = function () {
if (self.titleText) {
self.titleText.setText(translations[currentLanguage].tournaments || 'Tournaments');
}
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'Back');
}
};
self.enterTournament = function (tournamentIndex) {
var tournament = self.tournaments[tournamentIndex];
if (money >= tournament.entryFee) {
money -= tournament.entryFee;
self.currentTournament = tournament;
self.tournamentProgress = 0;
updateMoneyDisplay();
return true;
}
return false;
};
self.completeTournament = function () {
if (self.currentTournament) {
money += self.currentTournament.prize;
totalEarnings += self.currentTournament.prize;
self.currentTournament = null;
updateMoneyDisplay();
LK.getSound('victory').play();
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check tournament buttons with validation
var yPos = 600;
for (var i = 0; i < self.tournaments.length; i++) {
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= yPos - 60 && localPos.y <= yPos + 60) {
// Validate tournament entry requirements
if (horses && horses.length > 0 && selectedHorseIndex < horses.length) {
var selectedHorse = horses[selectedHorseIndex || 0];
if (selectedHorse && selectedHorse.currentEnergy >= 50) {
if (self.enterTournament(i)) {
currentView = 'race';
updateView();
LK.getSound('buttonClick').play();
}
} else {
// Horse too tired for tournament
LK.effects.flashScreen(0xff0000, 300);
}
} else {
// No horses available
LK.effects.flashScreen(0xff0000, 300);
}
break;
}
yPos += 150;
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2140 && localPos.y <= 2260) {
currentView = 'menu';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Veterinarian = Container.expand(function () {
var self = Container.call(this);
self.treatments = {
checkup: {
name: 'Health Checkup',
price: 1000,
effect: 'health'
},
energy: {
name: 'Energy Treatment',
price: 2000,
effect: 'energy'
},
performance: {
name: 'Performance Boost',
price: 5000,
effect: 'performance'
},
recovery: {
name: 'Recovery Therapy',
price: 3000,
effect: 'recovery'
}
};
self.titleText = null;
self.backText = null;
self.setupUI = function () {
var background = self.attachAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
self.titleText = new Text2(translations[currentLanguage].veterinarian || 'Veterinarian', {
size: 80,
fill: '#ffffff'
});
self.titleText.anchor.set(0.5, 0.5);
self.titleText.x = 1024;
self.titleText.y = 300;
self.addChild(self.titleText);
var yPos = 600;
for (var treatmentId in self.treatments) {
var treatment = self.treatments[treatmentId];
var treatmentBtn = self.attachAsset('vetButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: yPos
});
var treatmentText = new Text2(treatment.name + ' - $' + treatment.price, {
size: 30,
fill: '#ffffff'
});
treatmentText.anchor.set(0.5, 0.5);
treatmentText.x = 1024;
treatmentText.y = yPos;
self.addChild(treatmentText);
yPos += 150;
}
var backBtn = self.attachAsset('backButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 2200
});
self.backText = new Text2(translations[currentLanguage].back || 'Back', {
size: 40,
fill: '#ffffff'
});
self.backText.anchor.set(0.5, 0.5);
self.backText.x = 1024;
self.backText.y = 2200;
self.addChild(self.backText);
};
self.updateLanguage = function () {
if (self.titleText) {
self.titleText.setText(translations[currentLanguage].veterinarian || 'Veterinarian');
}
if (self.backText) {
self.backText.setText(translations[currentLanguage].back || 'Back');
}
};
self.performTreatment = function (treatmentId) {
var treatment = self.treatments[treatmentId];
if (money >= treatment.price && horses.length > 0) {
money -= treatment.price;
self.applyTreatment(treatment.effect);
updateMoneyDisplay();
return true;
}
return false;
};
self.applyTreatment = function (effect) {
if (horses.length > 0) {
var horse = horses[0];
switch (effect) {
case 'health':
horse.maxEnergy += 20;
break;
case 'energy':
horse.currentEnergy = horse.maxEnergy;
break;
case 'performance':
horse.speed += 10;
horse.stamina += 10;
break;
case 'recovery':
horse.currentEnergy = horse.maxEnergy;
horse.speed += 5;
break;
}
}
};
self.down = function (x, y, obj) {
if (!obj || !obj.parent || !obj.parent.toGlobal) {
var localPos = {
x: x,
y: y
};
} else {
var localPos = self.toLocal(obj.parent.toGlobal(obj.position));
}
// Check treatment buttons
var yPos = 600;
for (var treatmentId in self.treatments) {
if (localPos.x >= 824 && localPos.x <= 1224 && localPos.y >= yPos - 75 && localPos.y <= yPos + 75) {
if (self.performTreatment(treatmentId)) {
LK.getSound('buttonClick').play();
LK.effects.flashScreen(0x00ff00, 300);
}
break;
}
yPos += 150;
}
// Check back button
if (localPos.x >= 874 && localPos.x <= 1174 && localPos.y >= 2140 && localPos.y <= 2260) {
currentView = 'stable';
updateView();
LK.getSound('buttonClick').play();
}
};
return self;
});
var Weather = Container.expand(function () {
var self = Container.call(this);
self.conditions = ['sunny', 'rainy', 'cloudy', 'windy'];
self.currentWeather = 'sunny';
self.weatherIcon = null;
self.init = function () {
self.weatherIcon = self.attachAsset('weatherIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 150
});
self.updateWeather();
};
self.updateWeather = function () {
self.currentWeather = self.conditions[Math.floor(Math.random() * self.conditions.length)];
switch (self.currentWeather) {
case 'sunny':
self.weatherIcon.tint = 0xffff00;
break;
case 'rainy':
self.weatherIcon.tint = 0x0080ff;
break;
case 'cloudy':
self.weatherIcon.tint = 0x808080;
break;
case 'windy':
self.weatherIcon.tint = 0x90ee90;
break;
}
};
self.getSpeedModifier = function () {
switch (self.currentWeather) {
case 'sunny':
return 1.1;
case 'rainy':
return 0.9;
case 'cloudy':
return 1.0;
case 'windy':
return 0.95;
default:
return 1.0;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Language translations
var translations = {
en: {
title: 'Thoroughbred Legacy',
play: 'PLAY',
settings: 'SETTINGS',
language: 'Language:',
back: 'BACK',
yourStable: 'Your Stable',
breed: 'BREED',
train: 'TRAIN',
race: 'RACE',
money: 'Money: $',
wins: 'Wins: ',
help: 'HELP & GUIDE',
shop: 'SHOP',
tournament: 'TOURNAMENT',
vet: 'VETERINARIAN',
feed: 'FEED',
upgrade: 'UPGRADE'
},
ru: {
title: 'Наследие Чистокровных',
play: 'ИГРАТЬ',
settings: 'НАСТРОЙКИ',
language: 'Язык:',
back: 'НАЗАД',
yourStable: 'Ваша Конюшня',
breed: 'РАЗВЕДЕНИЕ',
train: 'ТРЕНИРОВКА',
race: 'ГОНКА',
money: 'Деньги: $',
wins: 'Побед: ',
help: 'ПОМОЩЬ И РУКОВОДСТВО'
},
fr: {
title: 'Héritage Pur-Sang',
play: 'JOUER',
settings: 'PARAMÈTRES',
language: 'Langue:',
back: 'RETOUR',
yourStable: 'Votre Écurie',
breed: 'ÉLEVAGE',
train: 'ENTRAÎNER',
race: 'COURSE',
money: 'Argent: $',
wins: 'Victoires: ',
help: 'AIDE ET GUIDE'
},
tr: {
title: 'Safkan Mirası',
play: 'OYNA',
settings: 'AYARLAR',
language: 'Dil Seçimi:',
back: 'GERİ',
yourStable: 'Ahırınız',
breed: 'ÜRETME',
train: 'EĞİTİM',
race: 'YARIŞ',
money: 'Para: $',
wins: 'Galibiyet: ',
upgrade: 'GELİŞTİRME',
shop: 'ELİT AT MAĞAZASI',
tournament: 'TURNUVA',
vet: 'VETERİNER',
feed: 'BESLENME',
weather: 'Hava Durumu',
achievements: 'Başarılar',
statistics: 'İstatistikler',
basic: 'TEMEL',
premium: 'PREMİUM',
legendary: 'EFSANEVİ',
audio: 'Ses Ayarları',
volume: 'Ana Ses: %',
tournaments: 'Turnuvalar',
veterinarian: 'Veteriner Hekim',
selectHorse: 'At Seçin',
horseStats: 'At İstatistikleri',
speed: 'Hız',
stamina: 'Dayanıklılık',
energy: 'Enerji',
age: 'Yaş',
value: 'Değer',
raceWins: 'Yarış Zaferleri',
temperament: 'Mizaç',
help: 'YARDIM VE KILAVUZ'
},
es: {
title: 'Legado Pura Sangre',
play: 'JUGAR',
settings: 'CONFIGURACIÓN',
language: 'Idioma:',
back: 'VOLVER',
yourStable: 'Tu Establo',
breed: 'CRIAR',
train: 'ENTRENAR',
race: 'CARRERA',
money: 'Dinero: $',
wins: 'Victorias: ',
upgrade: 'MEJORAR',
shop: 'TIENDA',
tournament: 'TORNEO',
vet: 'VETERINARIO',
feed: 'ALIMENTAR',
weather: 'Clima',
achievements: 'Logros',
statistics: 'Estadísticas',
help: 'AYUDA Y GUÍA'
},
de: {
title: 'Vollblut Erbe',
play: 'SPIELEN',
settings: 'EINSTELLUNGEN',
language: 'Sprache:',
back: 'ZURÜCK',
yourStable: 'Dein Stall',
breed: 'ZÜCHTEN',
train: 'TRAINIEREN',
race: 'RENNEN',
money: 'Geld: $',
wins: 'Siege: ',
upgrade: 'VERBESSERN',
shop: 'LADEN',
tournament: 'TURNIER',
vet: 'TIERARZT',
feed: 'FÜTTERN',
weather: 'Wetter',
achievements: 'Erfolge',
statistics: 'Statistiken',
help: 'HILFE UND ANLEITUNG'
},
zh: {
title: '纯血传承',
play: '开始游戏',
settings: '设置',
language: '语言:',
back: '返回',
yourStable: '你的马厩',
breed: '繁殖',
train: '训练',
race: '比赛',
money: '金钱: $',
wins: '胜利: ',
upgrade: '升级',
shop: '商店',
tournament: '锦标赛',
vet: '兽医',
feed: '喂养',
weather: '天气',
achievements: '成就',
statistics: '统计',
help: '帮助和指南'
},
ja: {
title: 'サラブレッドの遺産',
play: 'プレイ',
settings: '設定',
language: '言語:',
back: '戻る',
yourStable: 'あなたの厩舎',
breed: '繁殖',
train: '訓練',
race: 'レース',
money: 'お金: $',
wins: '勝利: ',
upgrade: 'アップグレード',
shop: 'ショップ',
tournament: 'トーナメント',
vet: '獣医',
feed: '餌やり',
weather: '天気',
achievements: '実績',
statistics: '統計',
help: 'ヘルプとガイド'
},
it: {
title: 'Eredità Purosangue',
play: 'GIOCA',
settings: 'IMPOSTAZIONI',
language: 'Lingua:',
back: 'INDIETRO',
yourStable: 'La Tua Scuderia',
breed: 'ALLEVARE',
train: 'ALLENARE',
race: 'CORSA',
money: 'Denaro: $',
wins: 'Vittorie: ',
upgrade: 'MIGLIORARE',
shop: 'NEGOZIO',
tournament: 'TORNEO',
vet: 'VETERINARIO',
feed: 'NUTRIRE',
weather: 'Tempo',
achievements: 'Risultati',
statistics: 'Statistiche',
help: 'AIUTO E GUIDA'
},
pt: {
title: 'Legado Puro Sangue',
play: 'JOGAR',
settings: 'CONFIGURAÇÕES',
language: 'Idioma:',
back: 'VOLTAR',
yourStable: 'Seu Estábulo',
breed: 'CRIAR',
train: 'TREINAR',
race: 'CORRIDA',
money: 'Dinheiro: $',
wins: 'Vitórias: ',
upgrade: 'MELHORAR',
shop: 'LOJA',
tournament: 'TORNEIO',
vet: 'VETERINÁRIO',
feed: 'ALIMENTAR',
weather: 'Tempo',
achievements: 'Conquistas',
statistics: 'Estatísticas',
help: 'AJUDA E GUIA'
}
};
// Load saved language or default to English
var currentLanguage = storage.language || 'en';
// Game state
var currentView = 'menu';
var horses = [];
var money = 50000;
var raceInProgress = false;
var totalEarnings = storage.totalEarnings || 0;
var trainingCount = storage.trainingCount || 0;
var breedingCount = storage.breedingCount || 0;
var selectedHorseIndex = 0;
var weatherSystem = null;
var achievementSystem = null;
var shopSystem = null;
var tournamentSystem = null;
var veterinarianSystem = null;
var helpSystem = null;
var currentWeather = 'sunny';
var gameTime = 0;
var seasonalBonus = 1.0;
// UI Elements
var moneyText = new Text2('Money: $' + money, {
size: 40,
fill: '#ffffff'
});
moneyText.anchor.set(0, 0);
moneyText.x = 150;
moneyText.y = 50;
LK.gui.topLeft.addChild(moneyText);
var scoreText = new Text2('Wins: ' + LK.getScore(), {
size: 40,
fill: '#ffffff'
});
scoreText.anchor.set(1, 0);
scoreText.x = -50;
scoreText.y = 50;
LK.gui.topRight.addChild(scoreText);
// Views
var mainMenu = new MainMenu();
var settingsMenu = new SettingsMenu();
var stableView = new StableView();
var raceView = new RaceView();
// Initialize game systems
weatherSystem = new Weather();
achievementSystem = new Achievement();
shopSystem = new Shop();
tournamentSystem = new Tournament();
veterinarianSystem = new Veterinarian();
helpSystem = new Help();
// Setup weather system
weatherSystem.init();
game.addChild(weatherSystem);
// Load achievements from storage
if (storage.achievements) {
// Reconstruct achievements from flattened storage
var flatAchievements = storage.achievements;
for (var key in achievementSystem.achievements) {
if (flatAchievements[key + '_unlocked'] !== undefined) {
achievementSystem.achievements[key].unlocked = flatAchievements[key + '_unlocked'];
}
if (flatAchievements[key + '_name'] !== undefined) {
achievementSystem.achievements[key].name = flatAchievements[key + '_name'];
}
if (flatAchievements[key + '_description'] !== undefined) {
achievementSystem.achievements[key].description = flatAchievements[key + '_description'];
}
}
}
// Initialize with starter horses
horses.push(new Horse({
name: 'Thunder',
speed: 70,
stamina: 65,
temperament: 60
}));
horses.push(new Horse({
name: 'Lightning',
speed: 60,
stamina: 70,
temperament: 65
}));
function updateMoneyDisplay() {
moneyText.setText(translations[currentLanguage].money + money);
scoreText.setText(translations[currentLanguage].wins + LK.getScore());
}
function updateAllLanguages() {
updateMoneyDisplay();
if (mainMenu.parent) {
mainMenu.updateLanguage();
}
if (settingsMenu.parent) {
settingsMenu.updateLanguage();
}
if (stableView.parent) {
stableView.updateLanguage();
}
}
function updateView() {
// Remove all views
if (mainMenu.parent) {
game.removeChild(mainMenu);
}
if (settingsMenu.parent) {
game.removeChild(settingsMenu);
}
if (stableView.parent) {
game.removeChild(stableView);
}
if (raceView.parent) {
game.removeChild(raceView);
}
if (shopSystem && shopSystem.parent) {
game.removeChild(shopSystem);
}
if (tournamentSystem && tournamentSystem.parent) {
game.removeChild(tournamentSystem);
}
if (veterinarianSystem && veterinarianSystem.parent) {
game.removeChild(veterinarianSystem);
}
if (helpSystem && helpSystem.parent) {
game.removeChild(helpSystem);
}
// Add current view
if (currentView === 'menu') {
game.addChild(mainMenu);
mainMenu.updateLanguage();
raceInProgress = false;
LK.playMusic('menuMusic');
} else if (currentView === 'settings') {
game.addChild(settingsMenu);
settingsMenu.updateLanguage();
raceInProgress = false;
} else if (currentView === 'stable') {
game.addChild(stableView);
stableView.updateHorseDisplay();
stableView.updateLanguage();
raceInProgress = false;
LK.playMusic('stableMusic');
} else if (currentView === 'race') {
game.addChild(raceView);
raceView.setupRace();
raceInProgress = true;
LK.getSound('hoofbeats').play();
LK.playMusic('raceMusic');
} else if (currentView === 'shop') {
shopSystem.setupUI();
game.addChild(shopSystem);
raceInProgress = false;
} else if (currentView === 'tournament') {
tournamentSystem.setupUI();
game.addChild(tournamentSystem);
if (tournamentSystem.updateLanguage) {
tournamentSystem.updateLanguage();
}
raceInProgress = false;
} else if (currentView === 'vet') {
veterinarianSystem.setupUI();
game.addChild(veterinarianSystem);
if (veterinarianSystem.updateLanguage) {
veterinarianSystem.updateLanguage();
}
raceInProgress = false;
} else if (currentView === 'help') {
helpSystem.setupUI();
game.addChild(helpSystem);
if (helpSystem.updateLanguage) {
helpSystem.updateLanguage();
}
raceInProgress = false;
}
}
function startRace() {
if (horses.length > 0) {
currentView = 'race';
updateView();
}
}
// Helper functions
function saveGameProgress() {
storage.money = money;
storage.totalEarnings = totalEarnings;
storage.trainingCount = trainingCount;
storage.breedingCount = breedingCount;
// Flatten achievements for storage
var flatAchievements = {};
for (var key in achievementSystem.achievements) {
flatAchievements[key + '_unlocked'] = achievementSystem.achievements[key].unlocked;
flatAchievements[key + '_name'] = achievementSystem.achievements[key].name;
flatAchievements[key + '_description'] = achievementSystem.achievements[key].description;
}
storage.achievements = flatAchievements;
// Flatten horse data for storage - create simple object structure
var flatHorseData = {};
for (var i = 0; i < horses.length; i++) {
var horse = horses[i];
flatHorseData['horse_' + i + '_name'] = horse.name || 'Unnamed Horse';
flatHorseData['horse_' + i + '_speed'] = Number(horse.speed) || 50;
flatHorseData['horse_' + i + '_stamina'] = Number(horse.stamina) || 50;
flatHorseData['horse_' + i + '_temperament'] = Number(horse.temperament) || 50;
flatHorseData['horse_' + i + '_age'] = Number(horse.age) || 2;
flatHorseData['horse_' + i + '_raceWins'] = Number(horse.raceWins) || 0;
flatHorseData['horse_' + i + '_value'] = Number(horse.value) || 10000;
flatHorseData['horse_' + i + '_currentEnergy'] = Number(horse.currentEnergy) || 100;
flatHorseData['horse_' + i + '_maxEnergy'] = Number(horse.maxEnergy) || 100;
}
flatHorseData['horseCount'] = horses.length;
storage.horseData = flatHorseData;
}
function loadGameProgress() {
if (storage.money) {
money = storage.money;
}
if (storage.totalEarnings) {
totalEarnings = storage.totalEarnings;
}
if (storage.trainingCount) {
trainingCount = storage.trainingCount;
}
if (storage.breedingCount) {
breedingCount = storage.breedingCount;
}
if (storage.achievements) {
// Reconstruct achievements from flattened storage
var flatAchievements = storage.achievements;
for (var key in achievementSystem.achievements) {
if (flatAchievements[key + '_unlocked'] !== undefined) {
achievementSystem.achievements[key].unlocked = flatAchievements[key + '_unlocked'];
}
if (flatAchievements[key + '_name'] !== undefined) {
achievementSystem.achievements[key].name = flatAchievements[key + '_name'];
}
if (flatAchievements[key + '_description'] !== undefined) {
achievementSystem.achievements[key].description = flatAchievements[key + '_description'];
}
}
}
if (storage.horseData && storage.horseData.horseCount) {
horses = [];
var horseCount = storage.horseData.horseCount;
for (var i = 0; i < horseCount; i++) {
horses.push(new Horse({
name: storage.horseData['horse_' + i + '_name'] || 'Unnamed Horse',
speed: storage.horseData['horse_' + i + '_speed'] || 50,
stamina: storage.horseData['horse_' + i + '_stamina'] || 50,
temperament: storage.horseData['horse_' + i + '_temperament'] || 50,
age: storage.horseData['horse_' + i + '_age'] || 2,
raceWins: storage.horseData['horse_' + i + '_raceWins'] || 0,
value: storage.horseData['horse_' + i + '_value'] || 10000,
currentEnergy: storage.horseData['horse_' + i + '_currentEnergy'] || 100,
maxEnergy: storage.horseData['horse_' + i + '_maxEnergy'] || 100
}));
}
}
}
function getWeatherBonus() {
return weatherSystem.getSpeedModifier() * seasonalBonus;
}
function generateRandomHorseName() {
var names = ['Thunder', 'Lightning', 'Storm', 'Blaze', 'Spirit', 'Shadow', 'Comet', 'Star', 'Flash', 'Dash', 'Wind', 'Fire', 'Rain', 'Snow', 'Frost', 'Dawn', 'Dusk', 'Moon', 'Sun', 'Sky'];
return names[Math.floor(Math.random() * names.length)] + ' ' + Math.floor(Math.random() * 1000);
}
// Load saved progress
loadGameProgress();
// Initialize view
updateView();
// Play background music
LK.playMusic('stableMusic');
// Main game loop with final optimizations
game.update = function () {
gameTime++;
// Validate game state integrity
if (!horses || horses.length < 0) {
horses = [];
}
if (isNaN(money) || money < 0) {
money = 0;
}
if (isNaN(selectedHorseIndex) || selectedHorseIndex >= horses.length) {
selectedHorseIndex = 0;
}
// Update weather every 30 seconds (1800 ticks)
if (gameTime % 1800 === 0) {
if (weatherSystem && weatherSystem.updateWeather) {
weatherSystem.updateWeather();
currentWeather = weatherSystem.currentWeather;
}
}
// Update seasonal bonus
seasonalBonus = Math.sin(gameTime / 10800) * 0.2 + 1.0;
// Race processing with error handling
if (raceInProgress && raceView && raceView.parent) {
try {
// Update player horse markers
for (var i = 0; i < raceView.raceHorses.length; i++) {
var item = raceView.raceHorses[i];
if (item && item.targetHorse && item.targetHorse.x !== undefined) {
// This is a marker, update its position to follow the horse
item.x = item.targetHorse.x;
item.y = item.targetHorse.y - 60;
}
}
// Check race completion
if (raceView.checkRaceFinish && !raceView.raceFinished) {
raceView.checkRaceFinish();
}
} catch (e) {
// Handle race errors gracefully
raceInProgress = false;
currentView = 'stable';
updateView();
}
}
// Auto-rest horses when not racing with validation
if (!raceInProgress && horses) {
for (var i = 0; i < horses.length; i++) {
var horse = horses[i];
if (horse && horse.currentEnergy !== undefined && horse.maxEnergy !== undefined) {
if (horse.currentEnergy < horse.maxEnergy) {
horse.currentEnergy = Math.min(horse.maxEnergy, horse.currentEnergy + 0.1);
}
}
}
}
// Update achievements with error handling
if (achievementSystem && achievementSystem.checkAchievements) {
try {
achievementSystem.checkAchievements();
} catch (e) {
// Ignore achievement errors to prevent game crashes
}
}
// Save progress every 10 seconds with validation
if (gameTime % 600 === 0) {
try {
saveGameProgress();
} catch (e) {
// Handle save errors gracefully
}
}
// Victory condition validation - 25 race wins
if (LK.getScore() >= 25) {
LK.showYouWin();
}
// Game over condition with proper validation
if (money <= 0 && horses.length === 0) {
LK.showGameOver();
}
// Random events with bounds checking
if (gameTime % 3600 === 0 && Math.random() < 0.1) {
// Random bonus money
var bonus = Math.floor(Math.random() * 5000) + 1000;
if (!isNaN(bonus) && bonus > 0) {
money += bonus;
totalEarnings += bonus;
updateMoneyDisplay();
}
}
// Performance optimization - cleanup unused objects
if (gameTime % 1200 === 0) {
// Periodic cleanup for better performance
for (var i = horses.length - 1; i >= 0; i--) {
var horse = horses[i];
if (!horse || horse.age > 30) {
// Remove very old horses to prevent memory issues
if (horse && horse.destroy) {
horse.destroy();
}
horses.splice(i, 1);
}
}
}
};