113 lines
8.7 KiB
JavaScript
113 lines
8.7 KiB
JavaScript
// Campaign Worlds & 25 Levels Definition System
|
||
window.CampaignSystem = (function() {
|
||
const WORLDS = [
|
||
{ id: 1, name: 'Солнечный День', icon: '☀️', biome: 'day', range: '1-1 .. 1-5' },
|
||
{ id: 2, name: 'Ночной Двор', icon: '🌙', biome: 'night', range: '2-1 .. 2-5' },
|
||
{ id: 3, name: 'Бассейн', icon: '🏊', biome: 'pool', range: '3-1 .. 3-5' },
|
||
{ id: 4, name: 'Ночной Туман', icon: '🌫️', biome: 'fog', range: '4-1 .. 4-5' },
|
||
{ id: 5, name: 'Крыша Дома', icon: '🏠', biome: 'roof', range: '5-1 .. 5-5' }
|
||
];
|
||
|
||
const DAVE_DIALOGUES = {
|
||
'2-1': {
|
||
title: '🌙 Безумный Дэйв предупреждает:',
|
||
text: 'Эй, сосед! Ночью солнце с неба не падает! Обязательно возьми Солнцегриб!',
|
||
btnText: 'ДАЛЕЕ / В БОЙ ⚔️'
|
||
},
|
||
'3-1': {
|
||
title: '🏊 Безумный Дэйв спешит на помощь:',
|
||
text: 'Там бассейн! На воде растения тонут — сначала сажай Кувшинки (Lily Pad)!',
|
||
btnText: 'ДАЛЕЕ / В БОЙ ⚔️'
|
||
},
|
||
'4-1': {
|
||
title: '🌫️ Безумный Дэйв щурится во мгле:',
|
||
text: 'Ого, какой густой туман! Зомби крадутся в темноте, используй Плантерн и Вздуватель!',
|
||
btnText: 'ДАЛЕЕ / В БОЙ ⚔️'
|
||
},
|
||
'5-1': {
|
||
title: '🏠 Безумный Дэйв лезет на скат:',
|
||
text: 'Мы на крыше! Скаты мешают прямой стрельбе — используй Горшки и Катапульты!',
|
||
btnText: 'ДАЛЕЕ / В БОЙ ⚔️'
|
||
},
|
||
'5-5': {
|
||
title: '🤖 БЕЗУМИЕ ПОЛНОГО МАСШТАБА!',
|
||
text: 'БЕЗУМИЕ! Доктор Зомбосс выкатил своего гигантского робота! Держи оборону!',
|
||
btnText: 'ДАЛЕЕ / В БОЙ ⚔️'
|
||
}
|
||
};
|
||
|
||
const LEVELS = [
|
||
// World 1: Day (1-1 .. 1-5)
|
||
{ level: 1, world: 1, stage: 1, code: '1-1', title: 'Первые шаги', desc: 'Знакомство с садом и простыми зомби', waves: 3, biome: 'day', reward: 100 },
|
||
{ level: 2, world: 1, stage: 2, code: '1-2', title: 'Опасные конусы', desc: 'Появление стойких зомби с дорожными конусами', waves: 3, biome: 'day', reward: 120 },
|
||
{ level: 3, world: 1, stage: 3, code: '1-3', title: 'Картофельный рубеж', desc: 'Тактическая оборона с картофельными минами', waves: 4, biome: 'day', reward: 140 },
|
||
{ level: 4, world: 1, stage: 4, code: '1-4', title: 'Прыгуны с шестом', desc: 'Быстрые зомби легко перепрыгивают первые растения', waves: 4, biome: 'day', reward: 160 },
|
||
{ level: 5, world: 1, stage: 5, code: '1-5', title: 'Штурм Дня', desc: 'Финальная массивная волна зомби на солнечном газоне', waves: 4, biome: 'day', reward: 200 },
|
||
|
||
// World 2: Night (2-1 .. 2-5)
|
||
{ level: 6, world: 2, stage: 1, code: '2-1', title: 'Сгущаются сумерки', desc: 'Ночь без падающего солнца: солнцегрибы и надгробия', waves: 3, biome: 'night', reward: 150 },
|
||
{ level: 7, world: 2, stage: 2, code: '2-2', title: 'Ярость газетчика', desc: 'Разъярённые зомби с газетами ускоряются в бешенстве', waves: 4, biome: 'night', reward: 170 },
|
||
{ level: 8, world: 2, stage: 3, code: '2-3', title: 'Споровый шквал', desc: 'Дымогрибы пробивают плотные ряды врагов', waves: 4, biome: 'night', reward: 190 },
|
||
{ level: 9, world: 2, stage: 4, code: '2-4', title: 'Бронекаски', desc: 'Зомби с вёдрами штурмуют тёмный двор', waves: 4, biome: 'night', reward: 210 },
|
||
{ level: 10, world: 2, stage: 5, code: '2-5', title: 'Полночный кошмар', desc: 'Зомби восстают прямо из могил в финальной волне', waves: 5, biome: 'night', reward: 250 },
|
||
|
||
// World 3: Pool (3-1 .. 3-5)
|
||
{ level: 11, world: 3, stage: 1, code: '3-1', title: 'Водная гладь', desc: '6 дорожек газона, кувшинки и зомби на утках', waves: 3, biome: 'pool', reward: 200 },
|
||
{ level: 12, world: 3, stage: 2, code: '3-2', title: 'Заплыв с шестом', desc: 'Прыгуны на суше и быстрые пловцы на воде', waves: 4, biome: 'pool', reward: 220 },
|
||
{ level: 13, world: 3, stage: 3, code: '3-3', title: 'Зубастики у воды', desc: 'Хищные зубастики против бронированных уток', waves: 4, biome: 'pool', reward: 240 },
|
||
{ level: 14, world: 3, stage: 4, code: '3-4', title: 'Футбольный матч', desc: 'Мощные футболисты прорывают береговую линию', waves: 4, biome: 'pool', reward: 260 },
|
||
{ level: 15, world: 3, stage: 5, code: '3-5', title: 'Водный шквал', desc: 'Штурм всех 6 дорожек с очистителями бассейна', waves: 5, biome: 'pool', reward: 300 },
|
||
|
||
// World 4: Fog (4-1 .. 4-5)
|
||
{ level: 16, world: 4, stage: 1, code: '4-1', title: 'Плотная мгла', desc: 'Густой туман скрывает правую половину поля', waves: 4, biome: 'fog', reward: 250 },
|
||
{ level: 17, world: 4, stage: 2, code: '4-2', title: 'Невидимая угроза', desc: 'Внезапные появления врагов прямо из белой пелены', waves: 4, biome: 'fog', reward: 270 },
|
||
{ level: 18, world: 4, stage: 3, code: '4-3', title: 'Туманный бассейн', desc: 'Водные линии скрыты во мраке ночного тумана', waves: 4, biome: 'fog', reward: 290 },
|
||
{ level: 19, world: 4, stage: 4, code: '4-4', title: 'Спринт сквозь мглу', desc: 'Футболисты и прыгуны выскакивают из тумана', waves: 5, biome: 'fog', reward: 310 },
|
||
{ level: 20, world: 4, stage: 5, code: '4-5', title: 'Штормовой туман', desc: 'Финальный прорыв орды через непроглядную пелену', waves: 5, biome: 'fog', reward: 350 },
|
||
|
||
// World 5: Roof (5-1 .. 5-5)
|
||
{ level: 21, world: 5, stage: 1, code: '5-1', title: 'Черепичный скат', desc: 'Крыша дома, цветочные горшки и капустопульты', waves: 4, biome: 'roof', reward: 300 },
|
||
{ level: 22, world: 5, stage: 2, code: '5-2', title: 'Арбузный гром', desc: 'Тяжёлые арбузопульты со сплэш-уроном по площади', waves: 4, biome: 'roof', reward: 320 },
|
||
{ level: 23, world: 5, stage: 3, code: '5-3', title: 'Опасные верхолазы', desc: 'Бронезомби карабкаются по скользкому скату крыши', waves: 4, biome: 'roof', reward: 350 },
|
||
{ level: 24, world: 5, stage: 4, code: '5-4', title: 'Осада дымохода', desc: 'Генеральный штурм перед чердаком дома', waves: 5, biome: 'roof', reward: 400 },
|
||
{ level: 25, world: 5, stage: 5, code: '5-5', title: 'Доктор Зомбосс!', desc: 'Финальная битва против шагающего робота Zombot!', waves: 1, biome: 'roof', isBoss: true, reward: 1000 }
|
||
];
|
||
|
||
return {
|
||
WORLDS,
|
||
LEVELS,
|
||
DAVE_DIALOGUES,
|
||
getDaveDialogue(levelNum, mode = 'adventure') {
|
||
if (mode === 'boss' || mode === 'bossrush') {
|
||
return DAVE_DIALOGUES['5-5'];
|
||
}
|
||
const num = parseInt(levelNum, 10) || 1;
|
||
const levelObj = LEVELS.find(l => l.level === num);
|
||
if (levelObj && DAVE_DIALOGUES[levelObj.code]) {
|
||
return DAVE_DIALOGUES[levelObj.code];
|
||
}
|
||
return null;
|
||
},
|
||
getLevel(levelNum) {
|
||
const num = parseInt(levelNum, 10) || 1;
|
||
return LEVELS.find(l => l.level === num) || LEVELS[0];
|
||
},
|
||
getWorld(worldId) {
|
||
return WORLDS.find(w => w.id === worldId) || WORLDS[0];
|
||
},
|
||
getLevelsByWorld(worldId) {
|
||
return LEVELS.filter(l => l.world === worldId);
|
||
},
|
||
formatLevel(levelNum) {
|
||
const item = this.getLevel(levelNum);
|
||
const world = this.getWorld(item.world);
|
||
return {
|
||
...item,
|
||
worldName: world.name,
|
||
worldIcon: world.icon,
|
||
fullLabel: `${item.code} (${world.icon} ${world.name})`
|
||
};
|
||
}
|
||
};
|
||
})();
|