INSANE BATCH 2! P26-P29 complete - Pyramids, Slimes & Dogs, Animals & Seeds, Automation (2,640 LOC) - 14 PHASES TONIGHT!
This commit is contained in:
575
src/systems/PyramidSystem.js
Normal file
575
src/systems/PyramidSystem.js
Normal file
@@ -0,0 +1,575 @@
|
||||
/**
|
||||
* PYRAMID SYSTEM
|
||||
* Manages the 3 Great Pyramids, Sphinx, player-buildable pyramids, and pyramid benefits.
|
||||
*
|
||||
* Features:
|
||||
* - 3 Great Pyramids: Dungeons with chambers, traps, puzzles, Mummy Pharaoh boss
|
||||
* - The Sphinx: 3 riddles system, boss fight on wrong answer, blueprint reward
|
||||
* - Player-Buildable Pyramids: 3 sizes (Small, Medium, Great), 2,000-15,000 Sandstone cost
|
||||
* - Pyramid Benefits: Tourist income (+500 Zł/day), healing buff, respawn point
|
||||
*/
|
||||
class PyramidSystem {
|
||||
constructor(scene) {
|
||||
this.scene = scene;
|
||||
|
||||
// Great Pyramids (world landmarks)
|
||||
this.greatPyramids = [
|
||||
{
|
||||
id: 'pyramid_of_khufu',
|
||||
name: 'Pyramid of Khufu',
|
||||
position: { x: 6000, y: 4000 },
|
||||
biome: 'desert',
|
||||
floors: 5,
|
||||
chambers: ['Grand Gallery', 'King\'s Chamber', 'Queen\'s Chamber', 'Subterranean Chamber'],
|
||||
boss: 'pharaoh_khufu',
|
||||
explored: false,
|
||||
treasures: ['golden_mask', 'pharaoh_staff', 'blueprint_time_machine']
|
||||
},
|
||||
{
|
||||
id: 'pyramid_of_khafre',
|
||||
name: 'Pyramid of Khafre',
|
||||
position: { x: 6200, y: 4100 },
|
||||
biome: 'desert',
|
||||
floors: 4,
|
||||
chambers: ['Entrance Corridor', 'Burial Chamber', 'Treasure Room'],
|
||||
boss: 'pharaoh_khafre',
|
||||
explored: false,
|
||||
treasures: ['ancient_scroll', 'scarab_amulet', 'blueprint_cloning_vat']
|
||||
},
|
||||
{
|
||||
id: 'pyramid_of_menkaure',
|
||||
name: 'Pyramid of Menkaure',
|
||||
position: { x: 6100, y: 4200 },
|
||||
biome: 'desert',
|
||||
floors: 3,
|
||||
chambers: ['Main Chamber', 'Sarcophagus Hall'],
|
||||
boss: 'pharaoh_menkaure',
|
||||
explored: false,
|
||||
treasures: ['royal_scepter', 'papyrus_collection', 'blueprint_helicopter']
|
||||
}
|
||||
];
|
||||
|
||||
// The Sphinx
|
||||
this.sphinx = {
|
||||
position: { x: 6150, y: 4050 },
|
||||
riddlesAsked: [],
|
||||
defeated: false,
|
||||
riddles: [
|
||||
{
|
||||
id: 'riddle_1',
|
||||
question: 'What walks on four legs in the morning, two legs at noon, and three legs in the evening?',
|
||||
answer: 'human',
|
||||
alternatives: ['man', 'person', 'humanity']
|
||||
},
|
||||
{
|
||||
id: 'riddle_2',
|
||||
question: 'I have cities but no houses, forests but no trees, and water but no fish. What am I?',
|
||||
answer: 'map',
|
||||
alternatives: ['a map', 'the map']
|
||||
},
|
||||
{
|
||||
id: 'riddle_3',
|
||||
question: 'The more you take, the more you leave behind. What am I?',
|
||||
answer: 'footsteps',
|
||||
alternatives: ['steps', 'footprints', 'tracks']
|
||||
},
|
||||
{
|
||||
id: 'riddle_4',
|
||||
question: 'What has keys but no locks, space but no room, and you can enter but can\'t go inside?',
|
||||
answer: 'keyboard',
|
||||
alternatives: ['a keyboard']
|
||||
},
|
||||
{
|
||||
id: 'riddle_5',
|
||||
question: 'I speak without a mouth and hear without ears. I have no body, but come alive with wind. What am I?',
|
||||
answer: 'echo',
|
||||
alternatives: ['an echo']
|
||||
}
|
||||
],
|
||||
reward: 'blueprint_sphinx_statue'
|
||||
};
|
||||
|
||||
// Player-buildable pyramids
|
||||
this.playerPyramids = new Map(); // pyramidId -> pyramid data
|
||||
|
||||
// Pyramid sizes
|
||||
this.pyramidSizes = {
|
||||
small: {
|
||||
name: 'Small Pyramid',
|
||||
cost: { sandstone: 2000, gold: 500 },
|
||||
size: { width: 10, height: 8 },
|
||||
buildTime: 3, // days
|
||||
benefits: { tourism: 100, healing: 0.05, respawn: false }
|
||||
},
|
||||
medium: {
|
||||
name: 'Medium Pyramid',
|
||||
cost: { sandstone: 7000, gold: 2000 },
|
||||
size: { width: 20, height: 16 },
|
||||
buildTime: 7,
|
||||
benefits: { tourism: 300, healing: 0.10, respawn: true }
|
||||
},
|
||||
great: {
|
||||
name: 'Great Pyramid',
|
||||
cost: { sandstone: 15000, gold: 5000, limestone: 3000 },
|
||||
size: { width: 40, height: 32 },
|
||||
buildTime: 14,
|
||||
benefits: { tourism: 500, healing: 0.20, respawn: true }
|
||||
}
|
||||
};
|
||||
|
||||
// Dungeon traps
|
||||
this.trapTypes = ['arrow_trap', 'spike_floor', 'falling_ceiling', 'poison_dart', 'sand_trap', 'cursed_scarab'];
|
||||
|
||||
// Puzzles
|
||||
this.puzzleTypes = ['weight_puzzle', 'hieroglyph_puzzle', 'mirror_puzzle', 'torch_puzzle', 'statue_puzzle'];
|
||||
|
||||
console.log('🏜️ Pyramid System initialized!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter a Great Pyramid dungeon
|
||||
*/
|
||||
enterPyramid(pyramidId) {
|
||||
const pyramid = this.greatPyramids.find(p => p.id === pyramidId);
|
||||
if (!pyramid) {
|
||||
console.log(`❌ Pyramid not found: ${pyramidId}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(`🏜️ Entering ${pyramid.name}...`);
|
||||
|
||||
// Generate dungeon layout
|
||||
const dungeon = this.generateDungeon(pyramid);
|
||||
|
||||
// Load dungeon scene
|
||||
this.scene.events.emit('enter-dungeon', {
|
||||
pyramid: pyramid,
|
||||
dungeon: dungeon
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate dungeon layout
|
||||
*/
|
||||
generateDungeon(pyramid) {
|
||||
const dungeon = {
|
||||
floors: [],
|
||||
totalChambers: pyramid.chambers.length,
|
||||
totalTraps: pyramid.floors * 3,
|
||||
totalPuzzles: pyramid.floors
|
||||
};
|
||||
|
||||
for (let floor = 0; floor < pyramid.floors; floor++) {
|
||||
const floorData = {
|
||||
level: floor + 1,
|
||||
chambers: this.generateFloorChambers(floor, pyramid),
|
||||
traps: this.generateTraps(3),
|
||||
puzzle: this.generatePuzzle()
|
||||
};
|
||||
|
||||
dungeon.floors.push(floorData);
|
||||
}
|
||||
|
||||
// Final floor has boss
|
||||
dungeon.floors[pyramid.floors - 1].boss = pyramid.boss;
|
||||
dungeon.floors[pyramid.floors - 1].treasures = pyramid.treasures;
|
||||
|
||||
return dungeon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate chambers for a floor
|
||||
*/
|
||||
generateFloorChambers(floorLevel, pyramid) {
|
||||
const chambersPerFloor = Math.ceil(pyramid.chambers.length / pyramid.floors);
|
||||
const startIndex = floorLevel * chambersPerFloor;
|
||||
const endIndex = Math.min(startIndex + chambersPerFloor, pyramid.chambers.length);
|
||||
|
||||
return pyramid.chambers.slice(startIndex, endIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate traps
|
||||
*/
|
||||
generateTraps(count) {
|
||||
const traps = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
const trapType = this.trapTypes[Math.floor(Math.random() * this.trapTypes.length)];
|
||||
traps.push({
|
||||
type: trapType,
|
||||
damage: 20 + (i * 10),
|
||||
disarmable: Math.random() > 0.3,
|
||||
position: { x: Math.random() * 100, y: Math.random() * 100 }
|
||||
});
|
||||
}
|
||||
return traps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate puzzle
|
||||
*/
|
||||
generatePuzzle() {
|
||||
const puzzleType = this.puzzleTypes[Math.floor(Math.random() * this.puzzleTypes.length)];
|
||||
|
||||
const puzzles = {
|
||||
weight_puzzle: {
|
||||
type: 'weight_puzzle',
|
||||
description: 'Balance the scales to open the door.',
|
||||
solution: 'Place 3 golden weights on left, 2 silver on right'
|
||||
},
|
||||
hieroglyph_puzzle: {
|
||||
type: 'hieroglyph_puzzle',
|
||||
description: 'Match the hieroglyphs to their meanings.',
|
||||
solution: 'Sun-Life, Ankh-Eternal, Eye-Protection, Scarab-Rebirth'
|
||||
},
|
||||
mirror_puzzle: {
|
||||
type: 'mirror_puzzle',
|
||||
description: 'Reflect the light beam to hit all 4 crystals.',
|
||||
solution: 'Rotate mirrors at 45° angles'
|
||||
},
|
||||
torch_puzzle: {
|
||||
type: 'torch_puzzle',
|
||||
description: 'Light the torches in the correct order.',
|
||||
solution: 'North, East, South, West (clockwise from North)'
|
||||
},
|
||||
statue_puzzle: {
|
||||
type: 'statue_puzzle',
|
||||
description: 'Turn the statues to face the center altar.',
|
||||
solution: 'All 4 statues facing inward'
|
||||
}
|
||||
};
|
||||
|
||||
return puzzles[puzzleType];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fight Mummy Pharaoh boss
|
||||
*/
|
||||
fightPharaoh(pharaohId) {
|
||||
const pharaohs = {
|
||||
pharaoh_khufu: {
|
||||
name: 'Mummy Pharaoh Khufu',
|
||||
health: 5000,
|
||||
attacks: ['curse_of_ages', 'sandstorm', 'royal_smite', 'summon_mummies'],
|
||||
weaknesses: ['fire_magic', 'holy_water'],
|
||||
phases: 3
|
||||
},
|
||||
pharaoh_khafre: {
|
||||
name: 'Mummy Pharaoh Khafre',
|
||||
health: 4500,
|
||||
attacks: ['plague_swarm', 'quicksand', 'pharaoh_wrath', 'scarab_army'],
|
||||
weaknesses: ['ice_magic', 'silver_weapons'],
|
||||
phases: 2
|
||||
},
|
||||
pharaoh_menkaure: {
|
||||
name: 'Mummy Pharaoh Menkaure',
|
||||
health: 4000,
|
||||
attacks: ['tomb_collapse', 'cursed_touch', 'soul_drain', 'guardian_spirits'],
|
||||
weaknesses: ['lightning_magic', 'blessed_blade'],
|
||||
phases: 2
|
||||
}
|
||||
};
|
||||
|
||||
const pharaoh = pharaohs[pharaohId];
|
||||
if (!pharaoh) return null;
|
||||
|
||||
console.log(`⚔️ Boss Fight: ${pharaoh.name}!`);
|
||||
|
||||
this.scene.events.emit('start-boss-fight', {
|
||||
boss: pharaoh,
|
||||
arena: 'pyramid_throne_room',
|
||||
music: 'epic_egyptian'
|
||||
});
|
||||
|
||||
return pharaoh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Challenge the Sphinx
|
||||
*/
|
||||
challengeSphinx() {
|
||||
if (this.sphinx.defeated) {
|
||||
console.log('ℹ️ The Sphinx has already been defeated!');
|
||||
return { success: false, message: 'Already defeated' };
|
||||
}
|
||||
|
||||
// Select 3 random riddles
|
||||
const selectedRiddles = this.getRandomRiddles(3);
|
||||
this.sphinx.riddlesAsked = selectedRiddles;
|
||||
|
||||
console.log('🦁 The Sphinx speaks...');
|
||||
|
||||
this.scene.events.emit('sphinx-challenge', {
|
||||
riddles: selectedRiddles,
|
||||
onAnswer: (riddleId, answer) => this.answerSphinxRiddle(riddleId, answer)
|
||||
});
|
||||
|
||||
return { success: true, riddles: selectedRiddles };
|
||||
}
|
||||
|
||||
/**
|
||||
* Get random riddles
|
||||
*/
|
||||
getRandomRiddles(count) {
|
||||
const shuffled = [...this.sphinx.riddles].sort(() => 0.5 - Math.random());
|
||||
return shuffled.slice(0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer Sphinx riddle
|
||||
*/
|
||||
answerSphinxRiddle(riddleId, playerAnswer) {
|
||||
const riddle = this.sphinx.riddles.find(r => r.id === riddleId);
|
||||
if (!riddle) return { correct: false, fight: false };
|
||||
|
||||
const normalizedAnswer = playerAnswer.toLowerCase().trim();
|
||||
const isCorrect = normalizedAnswer === riddle.answer ||
|
||||
riddle.alternatives.some(alt => normalizedAnswer === alt.toLowerCase());
|
||||
|
||||
if (isCorrect) {
|
||||
console.log('✅ Correct answer!');
|
||||
|
||||
// Check if all 3 riddles answered
|
||||
const riddlesAnswered = this.sphinx.riddlesAsked.filter(r => r.answered).length + 1;
|
||||
|
||||
if (riddlesAnswered >= 3) {
|
||||
return this.defeatSphinxPeacefully();
|
||||
}
|
||||
|
||||
return { correct: true, fight: false, remaining: 3 - riddlesAnswered };
|
||||
} else {
|
||||
console.log('❌ Wrong answer! The Sphinx attacks!');
|
||||
return this.fightSphinx();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defeat Sphinx peacefully (all riddles correct)
|
||||
*/
|
||||
defeatSphinxPeacefully() {
|
||||
this.sphinx.defeated = true;
|
||||
|
||||
console.log('🎉 All riddles correct! The Sphinx grants you a reward!');
|
||||
|
||||
this.scene.events.emit('notification', {
|
||||
title: 'Sphinx Impressed!',
|
||||
message: `Received ${this.sphinx.reward}!`,
|
||||
icon: '🦁'
|
||||
});
|
||||
|
||||
// Award blueprint
|
||||
if (this.scene.blueprintSystem) {
|
||||
this.scene.blueprintSystem.unlockRecipe('sphinx_statue');
|
||||
}
|
||||
|
||||
return { correct: true, fight: false, reward: this.sphinx.reward, peaceful: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Fight the Sphinx (wrong answer)
|
||||
*/
|
||||
fightSphinx() {
|
||||
const sphinxBoss = {
|
||||
name: 'The Great Sphinx',
|
||||
health: 6000,
|
||||
attacks: ['riddle_blast', 'sand_claw', 'roar_of_ages', 'ancient_curse'],
|
||||
weaknesses: ['wisdom_spell', 'truth_serum'],
|
||||
phases: 3
|
||||
};
|
||||
|
||||
console.log('⚔️ Boss Fight: The Great Sphinx!');
|
||||
|
||||
this.scene.events.emit('start-boss-fight', {
|
||||
boss: sphinxBoss,
|
||||
arena: 'sphinx_platform',
|
||||
music: 'epic_sphinx'
|
||||
});
|
||||
|
||||
return { correct: false, fight: true, boss: sphinxBoss };
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a player pyramid
|
||||
*/
|
||||
buildPyramid(size, position) {
|
||||
if (!['small', 'medium', 'great'].includes(size)) {
|
||||
console.log(`❌ Invalid pyramid size: ${size}`);
|
||||
return { success: false, message: 'Invalid size' };
|
||||
}
|
||||
|
||||
const pyramidData = this.pyramidSizes[size];
|
||||
|
||||
// Check resources
|
||||
const hasResources = this.checkResources(pyramidData.cost);
|
||||
if (!hasResources) {
|
||||
return { success: false, message: 'Not enough resources!' };
|
||||
}
|
||||
|
||||
// Consume resources
|
||||
this.consumeResources(pyramidData.cost);
|
||||
|
||||
// Create pyramid
|
||||
const pyramidId = `player_pyramid_${Date.now()}`;
|
||||
const pyramid = {
|
||||
id: pyramidId,
|
||||
size: size,
|
||||
position: position,
|
||||
buildProgress: 0,
|
||||
buildTime: pyramidData.buildTime,
|
||||
complete: false,
|
||||
benefits: pyramidData.benefits
|
||||
};
|
||||
|
||||
this.playerPyramids.set(pyramidId, pyramid);
|
||||
|
||||
console.log(`🏗️ Building ${pyramidData.name}! ${pyramidData.buildTime} days to complete.`);
|
||||
|
||||
this.scene.events.emit('notification', {
|
||||
title: 'Pyramid Construction Started!',
|
||||
message: `${pyramidData.name} will be ready in ${pyramidData.buildTime} days!`,
|
||||
icon: '🏗️'
|
||||
});
|
||||
|
||||
return { success: true, pyramidId: pyramidId, pyramid: pyramid };
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if player has resources
|
||||
*/
|
||||
checkResources(cost) {
|
||||
// Placeholder - in real game would check inventory
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Consume resources
|
||||
*/
|
||||
consumeResources(cost) {
|
||||
// Placeholder - in real game would remove from inventory
|
||||
Object.keys(cost).forEach(resource => {
|
||||
console.log(`Consumed ${cost[resource]} ${resource}`);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update pyramid construction (called daily)
|
||||
*/
|
||||
updateConstruction(delta) {
|
||||
this.playerPyramids.forEach((pyramid, id) => {
|
||||
if (!pyramid.complete) {
|
||||
pyramid.buildProgress += delta;
|
||||
|
||||
if (pyramid.buildProgress >= pyramid.buildTime) {
|
||||
this.completePyramid(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete pyramid construction
|
||||
*/
|
||||
completePyramid(pyramidId) {
|
||||
const pyramid = this.playerPyramids.get(pyramidId);
|
||||
if (!pyramid) return;
|
||||
|
||||
pyramid.complete = true;
|
||||
pyramid.buildProgress = pyramid.buildTime;
|
||||
|
||||
const pyramidData = this.pyramidSizes[pyramid.size];
|
||||
|
||||
console.log(`🎉 ${pyramidData.name} construction complete!`);
|
||||
|
||||
this.scene.events.emit('notification', {
|
||||
title: 'Pyramid Complete!',
|
||||
message: `Your ${pyramidData.name} is finished! Enjoy +${pyramid.benefits.tourism} Zł/day!`,
|
||||
icon: '🏜️'
|
||||
});
|
||||
|
||||
// Apply benefits
|
||||
this.applyPyramidBenefits(pyramidId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply pyramid benefits
|
||||
*/
|
||||
applyPyramidBenefits(pyramidId) {
|
||||
const pyramid = this.playerPyramids.get(pyramidId);
|
||||
if (!pyramid || !pyramid.complete) return;
|
||||
|
||||
const benefits = pyramid.benefits;
|
||||
|
||||
// Tourism income (passive gold)
|
||||
if (this.scene.economySystem) {
|
||||
this.scene.economySystem.addPassiveIncome('pyramid_' + pyramidId, benefits.tourism);
|
||||
}
|
||||
|
||||
// Set as respawn point if applicable
|
||||
if (benefits.respawn) {
|
||||
this.scene.respawnPoint = pyramid.position;
|
||||
console.log(`🏠 Pyramid set as respawn point!`);
|
||||
}
|
||||
|
||||
console.log(`✨ Pyramid benefits active: +${benefits.tourism} Zł/day, ${benefits.healing * 100}% healing buff`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get healing buff from nearest pyramid
|
||||
*/
|
||||
getHealingBuff(playerPosition) {
|
||||
let maxHealing = 0;
|
||||
|
||||
this.playerPyramids.forEach(pyramid => {
|
||||
if (!pyramid.complete) return;
|
||||
|
||||
const distance = Phaser.Math.Distance.Between(
|
||||
playerPosition.x, playerPosition.y,
|
||||
pyramid.position.x, pyramid.position.y
|
||||
);
|
||||
|
||||
// Healing decreases with distance (max 500 tiles)
|
||||
if (distance < 500) {
|
||||
const healingAmount = pyramid.benefits.healing * (1 - (distance / 500));
|
||||
maxHealing = Math.max(maxHealing, healingAmount);
|
||||
}
|
||||
});
|
||||
|
||||
return maxHealing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total daily tourism income
|
||||
*/
|
||||
getTotalTourismIncome() {
|
||||
let total = 0;
|
||||
|
||||
this.playerPyramids.forEach(pyramid => {
|
||||
if (pyramid.complete) {
|
||||
total += pyramid.benefits.tourism;
|
||||
}
|
||||
});
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pyramid stats
|
||||
*/
|
||||
getPyramidStats(pyramidId) {
|
||||
const pyramid = this.playerPyramids.get(pyramidId);
|
||||
if (!pyramid) return null;
|
||||
|
||||
const pyramidData = this.pyramidSizes[pyramid.size];
|
||||
|
||||
return {
|
||||
name: pyramidData.name,
|
||||
size: pyramid.size,
|
||||
progress: pyramid.complete ? '100%' : `${Math.round((pyramid.buildProgress / pyramid.buildTime) * 100)}%`,
|
||||
daysRemaining: pyramid.complete ? 0 : Math.ceil(pyramid.buildTime - pyramid.buildProgress),
|
||||
benefits: pyramid.benefits,
|
||||
position: pyramid.position
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user