Files
novafarma/src/systems/PortalRepairSystem.js

481 lines
14 KiB
JavaScript

/**
* PortalRepairSystem.js
* ======================
* KRVAVA ŽETEV - Portal Repair & Construction (Phase 20)
*
* Features:
* - 18 portal locations across biomes
* - Repair mechanics with materials
* - 1-8 day construction time
* - Defend from attacks during repair
* - Lv8+ zombie builders (independent work!)
* - Portal network benefits
* - Portable Personal Portal (endgame!)
*
* @author NovaFarma Team
* @date 2025-12-23
*/
class PortalRepairSystem {
constructor(scene) {
this.scene = scene;
// Portal registry
this.portals = new Map();
// Repair progress
this.activeRepairs = new Map();
// Network status
this.networkActive = false;
this.portalsRepaired = 0;
this.totalPortals = 18;
// Personal portal (endgame unlock)
this.hasPersonalPortal = false;
console.log('🌀 PortalRepairSystem initialized');
// Register all portals
this.registerPortals();
}
/**
* Register all 18 portals
*/
registerPortals() {
const portals = [
// Tier 1 - Easy (1-2 days)
{
id: 'grassland_portal', name: 'Grassland Portal', biome: 'grassland',
materials: { stone: 100, crystal: 10 }, days: 1, difficulty: 'easy'
},
{
id: 'forest_portal', name: 'Forest Portal', biome: 'forest',
materials: { wood: 200, crystal: 15 }, days: 2, difficulty: 'easy'
},
// Tier 2 - Medium (3-4 days)
{
id: 'desert_portal', name: 'Desert Portal', biome: 'desert',
materials: { sandstone: 300, crystal: 20, gold: 10 }, days: 3, difficulty: 'medium'
},
{
id: 'swamp_portal', name: 'Swamp Portal', biome: 'swamp',
materials: { clay: 250, crystal: 25 }, days: 3, difficulty: 'medium'
},
{
id: 'beach_portal', name: 'Beach Portal', biome: 'beach',
materials: { coral: 200, crystal: 20, pearl: 5 }, days: 3, difficulty: 'medium'
},
{
id: 'mountain_portal', name: 'Mountain Portal', biome: 'mountain',
materials: { stone: 400, iron: 50, crystal: 30 }, days: 4, difficulty: 'medium'
},
// Tier 3 - Hard (5-6 days)
{
id: 'frozen_portal', name: 'Frozen Portal', biome: 'frozen',
materials: { ice: 500, crystal: 40, diamond: 5 }, days: 5, difficulty: 'hard'
},
{
id: 'volcanic_portal', name: 'Volcanic Portal', biome: 'volcanic',
materials: { obsidian: 400, crystal: 50, ruby: 10 }, days: 5, difficulty: 'hard'
},
{
id: 'wasteland_portal', name: 'Wasteland Portal', biome: 'wasteland',
materials: { scrap: 600, uranium: 20, crystal: 60 }, days: 6, difficulty: 'hard'
},
{
id: 'jungle_portal', name: 'Jungle Portal', biome: 'jungle',
materials: { vine: 300, emerald: 15, crystal: 45 }, days: 5, difficulty: 'hard'
},
// Tier 4 - Very Hard (7-8 days)
{
id: 'egypt_portal', name: 'Egypt Portal', biome: 'egypt',
materials: { sandstone: 800, gold: 100, crystal: 80 }, days: 7, difficulty: 'very_hard'
},
{
id: 'atlantis_portal', name: 'Atlantis Portal', biome: 'underwater',
materials: { orichalcum: 200, pearl: 50, crystal: 100 }, days: 8, difficulty: 'very_hard'
},
{
id: 'lochness_portal', name: 'Loch Ness Portal', biome: 'lochness',
materials: { stone: 1000, emerald: 20, crystal: 90 }, days: 7, difficulty: 'very_hard'
},
{
id: 'chernobyl_portal', name: 'Chernobyl Portal', biome: 'chernobyl',
materials: { concrete: 900, uranium: 50, crystal: 100 }, days: 8, difficulty: 'very_hard'
},
{
id: 'amazon_portal', name: 'Amazon Portal', biome: 'amazon',
materials: { wood: 1000, vine: 500, crystal: 85 }, days: 7, difficulty: 'very_hard'
},
// Tier 5 - Legendary (8 days)
{
id: 'mythical_portal', name: 'Mythical Realm Portal', biome: 'mythical',
materials: { mythril: 100, dragon_scale: 20, crystal: 150 }, days: 8, difficulty: 'legendary'
},
{
id: 'anomaly_portal', name: 'Anomalous Zone Portal', biome: 'anomaly',
materials: { artifact: 50, uranium: 100, crystal: 200 }, days: 8, difficulty: 'legendary'
},
{
id: 'void_portal', name: 'The Void Portal', biome: 'void',
materials: { void_essence: 10, cosmic_dust: 50, crystal: 250 }, days: 8, difficulty: 'legendary'
}
];
portals.forEach(portal => {
this.portals.set(portal.id, {
...portal,
isRepaired: false,
repairProgress: 0,
isUnderAttack: false,
questCompleted: false
});
});
console.log(`✅ Registered ${this.portals.size} portals`);
}
/**
* Start portal repair
*/
startRepair(portalId, zombieBuilders = []) {
const portal = this.portals.get(portalId);
if (!portal) {
console.error(`Portal ${portalId} not found!`);
return false;
}
if (portal.isRepaired) {
console.log(`${portal.name} is already repaired!`);
return false;
}
// Check if quest is completed
if (!portal.questCompleted) {
console.log(`Complete the ${portal.name} quest first!`);
return false;
}
// Check materials
if (!this.hasMaterials(portal.materials)) {
console.log(`Not enough materials for ${portal.name}!`);
return false;
}
// Consume materials
this.consumeMaterials(portal.materials);
// Calculate repair time (zombie builders reduce time)
const builderBonus = this.calculateBuilderBonus(zombieBuilders);
const repairTime = portal.days * (1 - builderBonus);
// Start repair
const repair = {
portalId: portalId,
startTime: Date.now(),
duration: repairTime * 24 * 60 * 60 * 1000, // Days to ms
builders: zombieBuilders,
defendPhase: false
};
this.activeRepairs.set(portalId, repair);
portal.repairProgress = 0;
console.log(`🌀 Started repairing ${portal.name} (${repairTime} days with ${zombieBuilders.length} workers)`);
// Start defend events
this.scheduleDefendEvents(portalId, repairTime);
this.showNotification({
title: 'Portal Repair Started!',
text: `🌀 ${portal.name} - ${repairTime.toFixed(1)} days`,
icon: '🔨'
});
return true;
}
/**
* Calculate builder bonus
*/
calculateBuilderBonus(builders) {
if (builders.length === 0) return 0;
let bonus = 0;
builders.forEach(builder => {
// Lv8+ zombies are 50% faster
if (builder.level >= 8) {
bonus += 0.15; // 15% per Lv8+ zombie
} else {
bonus += 0.05; // 5% per lower level zombie
}
});
return Math.min(bonus, 0.6); // Max 60% reduction
}
/**
* Schedule defend events
*/
scheduleDefendEvents(portalId, repairDays) {
const portal = this.portals.get(portalId);
// Attack waves based on difficulty
const attackCount = {
easy: 1,
medium: 2,
hard: 3,
very_hard: 4,
legendary: 5
}[portal.difficulty] || 2;
// Schedule attacks at intervals
for (let i = 0; i < attackCount; i++) {
const attackTime = (repairDays / attackCount) * (i + 0.5);
setTimeout(() => {
this.triggerAttack(portalId);
}, attackTime * 24 * 60 * 60 * 1000);
}
}
/**
* Trigger attack on portal
*/
triggerAttack(portalId) {
const portal = this.portals.get(portalId);
const repair = this.activeRepairs.get(portalId);
if (!repair) return;
portal.isUnderAttack = true;
repair.defendPhase = true;
console.log(`⚔️ ${portal.name} is under attack!`);
this.showNotification({
title: 'PORTAL UNDER ATTACK!',
text: `⚔️ Defend ${portal.name}!`,
icon: '⚠️'
});
// TODO: Spawn enemies
// Attack ends after 5 minutes or all enemies defeated
setTimeout(() => {
portal.isUnderAttack = false;
repair.defendPhase = false;
console.log(`${portal.name} defended successfully!`);
}, 5 * 60 * 1000);
}
/**
* Complete portal repair
*/
completeRepair(portalId) {
const portal = this.portals.get(portalId);
if (!portal) return;
portal.isRepaired = true;
portal.repairProgress = 100;
this.portalsRepaired++;
this.activeRepairs.delete(portalId);
console.log(`${portal.name} repaired! (${this.portalsRepaired}/${this.totalPortals})`);
// Activate portal network if this is the first portal
if (this.portalsRepaired === 1) {
this.activateNetwork();
}
// Check for personal portal unlock
if (this.portalsRepaired === this.totalPortals) {
this.unlockPersonalPortal();
}
this.showNotification({
title: 'Portal Complete!',
text: `${portal.name} is now operational!`,
icon: '🌀'
});
}
/**
* Activate portal network
*/
activateNetwork() {
this.networkActive = true;
console.log('🌐 Portal Network activated!');
this.showNotification({
title: 'PORTAL NETWORK ONLINE!',
text: '🌐 Fast travel between portals unlocked!',
icon: '✨'
});
}
/**
* Unlock personal portal
*/
unlockPersonalPortal() {
this.hasPersonalPortal = true;
console.log('👑 PERSONAL PORTAL UNLOCKED!');
this.showNotification({
title: 'PERSONAL PORTAL!',
text: '👑 Portable portal unlocked! Teleport anywhere!',
icon: '🎊'
});
}
/**
* Use portal (teleport)
*/
usePortal(fromPortalId, toPortalId) {
if (!this.networkActive) {
console.log('Portal network is not active yet!');
return false;
}
const from = this.portals.get(fromPortalId);
const to = this.portals.get(toPortalId);
if (!from || !to) {
console.error('Portal not found!');
return false;
}
if (!from.isRepaired || !to.isRepaired) {
console.log('Both portals must be repaired!');
return false;
}
console.log(`🌀 Teleporting from ${from.name} to ${to.name}!`);
// Instant teleport
// TODO: Actual player teleport
// TODO: Can bring zombies for FREE (network benefit)
this.showNotification({
title: 'Teleported!',
text: `🌀 Arrived at ${to.name}`,
icon: '✨'
});
return true;
}
/**
* Check if Lv8+ zombie can work independently
*/
canWorkIndependently(zombie) {
return zombie.level >= 8;
}
/**
* Send Lv8+ zombie to repair portal alone
*/
sendIndependentBuilder(portalId, zombie) {
if (!this.canWorkIndependently(zombie)) {
console.log(`${zombie.name} must be Lv8+ to work alone!`);
return false;
}
console.log(`🤖 Sending ${zombie.name} (Lv${zombie.level}) to repair ${portalId} independently!`);
// Zombie travels, gathers materials, repairs portal autonomously!
this.startRepair(portalId, [zombie]);
this.showNotification({
title: 'Independent Builder!',
text: `🤖 ${zombie.name} will repair portal alone!`,
icon: '✨'
});
return true;
}
/**
* Check materials
*/
hasMaterials(required) {
// TODO: Check actual inventory
return true; // For now
}
/**
* Consume materials
*/
consumeMaterials(materials) {
// TODO: Remove from inventory
console.log('📦 Materials consumed:', materials);
}
/**
* Get repair progress
*/
getProgress() {
return {
repaired: this.portalsRepaired,
total: this.totalPortals,
percentage: ((this.portalsRepaired / this.totalPortals) * 100).toFixed(1),
networkActive: this.networkActive,
hasPersonalPortal: this.hasPersonalPortal
};
}
/**
* Get portal info
*/
getPortalInfo(portalId) {
return this.portals.get(portalId);
}
/**
* Get all portals
*/
getAllPortals() {
return Array.from(this.portals.values());
}
/**
* Update repair progress (called from game loop)
*/
update(delta) {
this.activeRepairs.forEach((repair, portalId) => {
const elapsed = Date.now() - repair.startTime;
const progress = (elapsed / repair.duration) * 100;
const portal = this.portals.get(portalId);
if (portal) {
portal.repairProgress = Math.min(100, progress);
}
// Check completion
if (progress >= 100) {
this.completeRepair(portalId);
}
});
}
/**
* Helper: Show notification
*/
showNotification(notification) {
console.log(`📢 ${notification.icon} ${notification.title}: ${notification.text}`);
const ui = this.scene.scene.get('UIScene');
if (ui && ui.showNotification) {
ui.showNotification(notification);
}
}
}