phase 11 koncano
This commit is contained in:
@@ -43,6 +43,29 @@ class UIScene extends Phaser.Scene {
|
||||
localStorage.removeItem('novafarma_savefile');
|
||||
window.location.reload();
|
||||
});
|
||||
|
||||
// Collection (J)
|
||||
this.input.keyboard.on('keydown-J', () => {
|
||||
this.toggleCollectionMenu();
|
||||
});
|
||||
|
||||
// Skill Tree (K)
|
||||
this.input.keyboard.on('keydown-K', () => {
|
||||
this.toggleSkillTree();
|
||||
});
|
||||
|
||||
// Define Recipes
|
||||
this.craftingRecipes = [
|
||||
{ id: 'axe', name: 'Stone Axe', req: { 'wood': 3, 'stone': 3 }, output: 1, type: 'tool', desc: 'Used for chopping trees.' },
|
||||
{ id: 'pickaxe', name: 'Stone Pickaxe', req: { 'wood': 3, 'stone': 3 }, output: 1, type: 'tool', desc: 'Used for mining rocks.' },
|
||||
{ id: 'hoe', name: 'Stone Hoe', req: { 'wood': 2, 'stone': 2 }, output: 1, type: 'tool', desc: 'Prepares soil for planting.' },
|
||||
{ id: 'sword', name: 'Stone Sword', req: { 'wood': 5, 'stone': 2 }, output: 1, type: 'weapon', desc: 'Deals damage to zombies.' },
|
||||
{ id: 'fence', name: 'Wood Fence', req: { 'wood': 2 }, output: 1, type: 'building', desc: 'Simple barrier.' },
|
||||
{ id: 'chest', name: 'Wooden Chest', req: { 'wood': 20 }, output: 1, type: 'furniture', desc: 'Stores items.' },
|
||||
{ id: 'furnace', name: 'Furnace', req: { 'stone': 20 }, output: 1, type: 'machine', desc: 'Smelts ores into bars.' },
|
||||
{ id: 'mint', name: 'Mint', req: { 'stone': 50, 'iron_bar': 5 }, output: 1, type: 'machine', desc: 'Mints coins from bars.' },
|
||||
{ id: 'grave', name: 'Grave', req: { 'stone': 10 }, output: 1, type: 'furniture', desc: 'Resting place for zombies.' }
|
||||
];
|
||||
}
|
||||
|
||||
// ... (rest of class) ...
|
||||
@@ -64,90 +87,201 @@ class UIScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
createCraftingMenu() {
|
||||
const w = 300;
|
||||
const h = 250;
|
||||
const w = 600;
|
||||
const h = 400;
|
||||
const x = this.scale.width / 2;
|
||||
const y = this.scale.height / 2;
|
||||
|
||||
this.craftingContainer = this.add.container(x, y);
|
||||
this.craftingContainer.setDepth(2000); // Top of everything
|
||||
|
||||
// Bg
|
||||
// 1. Background (Main Window)
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x222222, 0.95);
|
||||
bg.fillStyle(0x1a1a2e, 0.98); // Dark Blue theme
|
||||
bg.fillRect(-w / 2, -h / 2, w, h);
|
||||
bg.lineStyle(2, 0x888888, 1);
|
||||
bg.lineStyle(2, 0x4e4e6e, 1);
|
||||
bg.strokeRect(-w / 2, -h / 2, w, h);
|
||||
this.craftingContainer.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(0, -h / 2 + 20, 'CRAFTING', { fontSize: '24px', fontStyle: 'bold', color: '#ffffff' }).setOrigin(0.5);
|
||||
// Header
|
||||
const titleBg = this.add.rectangle(0, -h / 2 + 25, w, 50, 0x16213e);
|
||||
this.craftingContainer.add(titleBg);
|
||||
const title = this.add.text(0, -h / 2 + 25, 'WORKBENCH', {
|
||||
fontSize: '24px', fontFamily: 'Courier New', fontStyle: 'bold', color: '#ffffff'
|
||||
}).setOrigin(0.5);
|
||||
this.craftingContainer.add(title);
|
||||
|
||||
// Recipes
|
||||
const recipes = [
|
||||
{ name: 'Axe', code: '1', req: '5 Wood', type: 'axe', cost: { wood: 5 } },
|
||||
{ name: 'Pickaxe', code: '2', req: '5 Wood, 2 Stone', type: 'pickaxe', cost: { wood: 5, stone: 2 } },
|
||||
{ name: 'Hoe', code: '3', req: '3 Wood, 2 Stone', type: 'hoe', cost: { wood: 3, stone: 2 } },
|
||||
{ name: 'Sword', code: '4', req: '10 Wood, 5 Stone', type: 'sword', cost: { wood: 10, stone: 5 } }
|
||||
];
|
||||
// Close Button
|
||||
const closeBtn = this.add.text(w / 2 - 20, -h / 2 + 25, 'X', {
|
||||
fontSize: '24px', color: '#ff4444', fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
closeBtn.setInteractive({ useHandCursor: true })
|
||||
.on('pointerdown', () => this.toggleCraftingMenu());
|
||||
this.craftingContainer.add(closeBtn);
|
||||
|
||||
recipes.forEach((r, i) => {
|
||||
const rowY = -h / 2 + 70 + (i * 40);
|
||||
// 2. Layout Containers
|
||||
// Left Panel (List)
|
||||
this.recipeListContainer = this.add.container(-w / 2 + 20, -h / 2 + 70);
|
||||
this.craftingContainer.add(this.recipeListContainer);
|
||||
|
||||
// Text
|
||||
const txt = this.add.text(-w / 2 + 20, rowY, `[${r.code}] ${r.name} (${r.req})`, {
|
||||
fontSize: '16px', color: '#eeeeee'
|
||||
});
|
||||
this.craftingContainer.add(txt);
|
||||
// Right Panel (Details)
|
||||
this.detailsContainer = this.add.container(20, -h / 2 + 70);
|
||||
this.craftingContainer.add(this.detailsContainer);
|
||||
|
||||
// Button Logic (Keyboard 1-4 works too via GameScene? No, let's localize input)
|
||||
});
|
||||
|
||||
// Instruction
|
||||
const instr = this.add.text(0, h / 2 - 20, 'Press number keys to craft', { fontSize: '12px', color: '#aaaaaa' }).setOrigin(0.5);
|
||||
this.craftingContainer.add(instr);
|
||||
|
||||
// Input listener for crafting
|
||||
this.input.keyboard.on('keydown', (e) => {
|
||||
if (!this.craftingContainer.visible) return;
|
||||
|
||||
const key = e.key;
|
||||
const recipe = recipes.find(r => r.code === key);
|
||||
if (recipe) {
|
||||
this.tryCraft(recipe);
|
||||
}
|
||||
});
|
||||
// Initial render
|
||||
this.selectedRecipe = null;
|
||||
this.refreshRecipeList();
|
||||
|
||||
this.craftingContainer.setVisible(false);
|
||||
}
|
||||
|
||||
refreshRecipeList() {
|
||||
this.recipeListContainer.removeAll(true);
|
||||
|
||||
// Filter recipes
|
||||
const unlocked = this.craftingRecipes.filter(r => {
|
||||
// Check Blueprint System
|
||||
if (this.gameScene.blueprintSystem) {
|
||||
return this.gameScene.blueprintSystem.isUnlocked(r.id);
|
||||
}
|
||||
return true; // Fallback
|
||||
});
|
||||
|
||||
let y = 0;
|
||||
unlocked.forEach((recipe, i) => {
|
||||
const btnBg = this.add.rectangle(130, y + 20, 260, 36, 0x2a2a3e);
|
||||
btnBg.setInteractive({ useHandCursor: true });
|
||||
|
||||
// Hover effect
|
||||
btnBg.on('pointerover', () => btnBg.setFillStyle(0x3a3a5e));
|
||||
btnBg.on('pointerout', () => {
|
||||
if (this.selectedRecipe !== recipe) btnBg.setFillStyle(0x2a2a3e);
|
||||
else btnBg.setFillStyle(0x4a4a6e);
|
||||
});
|
||||
|
||||
// Click
|
||||
btnBg.on('pointerdown', () => {
|
||||
this.selectedRecipe = recipe;
|
||||
this.refreshRecipeList(); // Redraw selection highlight
|
||||
this.showRecipeDetails(recipe);
|
||||
});
|
||||
|
||||
// Highlight selected
|
||||
if (this.selectedRecipe === recipe) {
|
||||
btnBg.setFillStyle(0x4a4a6e);
|
||||
btnBg.setStrokeStyle(1, 0xffff00);
|
||||
} else {
|
||||
btnBg.setStrokeStyle(1, 0x4e4e6e);
|
||||
}
|
||||
|
||||
const nameText = this.add.text(10, y + 10, recipe.name.toUpperCase(), {
|
||||
fontSize: '14px', fontFamily: 'monospace', fill: '#ffffff'
|
||||
});
|
||||
|
||||
this.recipeListContainer.add(btnBg);
|
||||
this.recipeListContainer.add(nameText);
|
||||
|
||||
y += 40;
|
||||
});
|
||||
|
||||
// Select first if none selected
|
||||
if (!this.selectedRecipe && unlocked.length > 0) {
|
||||
this.selectedRecipe = unlocked[0];
|
||||
this.showRecipeDetails(unlocked[0]);
|
||||
}
|
||||
}
|
||||
|
||||
showRecipeDetails(recipe) {
|
||||
this.detailsContainer.removeAll(true);
|
||||
if (!recipe) return;
|
||||
|
||||
// Title
|
||||
const title = this.add.text(0, 0, recipe.name, {
|
||||
fontSize: '22px', fontStyle: 'bold', fill: '#FFD700', stroke: '#000', strokeThickness: 2
|
||||
});
|
||||
this.detailsContainer.add(title);
|
||||
|
||||
// Description
|
||||
const desc = this.add.text(0, 35, recipe.desc, {
|
||||
fontSize: '14px', fill: '#aaaaaa', wordWrap: { width: 250 }
|
||||
});
|
||||
this.detailsContainer.add(desc);
|
||||
|
||||
// Requirements Header
|
||||
this.detailsContainer.add(this.add.text(0, 90, 'REQUIRED MATERIALS:', {
|
||||
fontSize: '14px', fill: '#ffffff', fontStyle: 'bold'
|
||||
}));
|
||||
|
||||
// Requirements List
|
||||
let y = 120;
|
||||
let canCraft = true;
|
||||
const inv = this.gameScene.inventorySystem;
|
||||
|
||||
for (const [item, count] of Object.entries(recipe.req)) {
|
||||
const has = inv ? inv.getItemCount(item) : 0;
|
||||
const hasEnough = has >= count;
|
||||
if (!hasEnough) canCraft = false;
|
||||
|
||||
const color = hasEnough ? '#55ff55' : '#ff5555';
|
||||
const icon = hasEnough ? '✓' : '✗';
|
||||
|
||||
const reqText = this.add.text(0, y,
|
||||
`${icon} ${count}x ${item.toUpperCase()} (Have: ${has})`,
|
||||
{ fontSize: '14px', fill: color, fontFamily: 'monospace' }
|
||||
);
|
||||
this.detailsContainer.add(reqText);
|
||||
y += 20;
|
||||
}
|
||||
|
||||
// CRAFT BUTTON
|
||||
const btnY = 300;
|
||||
const btnBg = this.add.rectangle(130, btnY, 200, 50, canCraft ? 0x00aa00 : 0x550000);
|
||||
|
||||
if (canCraft) {
|
||||
btnBg.setInteractive({ useHandCursor: true });
|
||||
btnBg.on('pointerover', () => btnBg.setFillStyle(0x00cc00));
|
||||
btnBg.on('pointerout', () => btnBg.setFillStyle(0x00aa00));
|
||||
btnBg.on('pointerdown', () => this.tryCraft(recipe));
|
||||
}
|
||||
|
||||
const btnText = this.add.text(130, btnY, 'CRAFT ITEM', {
|
||||
fontSize: '20px', fill: canCraft ? '#ffffff' : '#888888', fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
|
||||
this.detailsContainer.add(btnBg);
|
||||
this.detailsContainer.add(btnText);
|
||||
}
|
||||
|
||||
tryCraft(recipe) {
|
||||
if (!this.gameScene || !this.gameScene.inventorySystem) return;
|
||||
|
||||
const inv = this.gameScene.inventorySystem;
|
||||
|
||||
// Check cost
|
||||
if (recipe.cost.wood && !inv.hasItem('wood', recipe.cost.wood)) {
|
||||
console.log('Craft fail: Wood');
|
||||
return; // Add UI feedback "Need Wood"
|
||||
}
|
||||
if (recipe.cost.stone && !inv.hasItem('stone', recipe.cost.stone)) {
|
||||
console.log('Craft fail: Stone');
|
||||
return;
|
||||
// Double check cost
|
||||
for (const [item, count] of Object.entries(recipe.req)) {
|
||||
if (!inv.hasItem(item, count)) {
|
||||
console.log(`Craft fail: Missing ${item}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Consume
|
||||
if (recipe.cost.wood) inv.removeItem('wood', recipe.cost.wood);
|
||||
if (recipe.cost.stone) inv.removeItem('stone', recipe.cost.stone);
|
||||
for (const [item, count] of Object.entries(recipe.req)) {
|
||||
inv.removeItem(item, count);
|
||||
}
|
||||
|
||||
// Add Item
|
||||
inv.addItem(recipe.type, 1);
|
||||
inv.addItem(recipe.id, recipe.output);
|
||||
|
||||
console.log(`Crafted ${recipe.name}!`);
|
||||
|
||||
// Flash effect
|
||||
this.cameras.main.flash(200, 0, 255, 0); // Green flash
|
||||
this.craftingContainer.setVisible(false);
|
||||
// Sound & Visuals
|
||||
if (this.gameScene.soundManager) this.gameScene.soundManager.playSuccess();
|
||||
this.cameras.main.flash(200, 255, 255, 255);
|
||||
|
||||
// Refresh UI
|
||||
this.refreshRecipeList();
|
||||
this.showRecipeDetails(recipe);
|
||||
}
|
||||
|
||||
resize(gameSize) {
|
||||
@@ -975,4 +1109,340 @@ class UIScene extends Phaser.Scene {
|
||||
container.setScale(0);
|
||||
this.tweens.add({ targets: container, scale: 1, duration: 200, ease: 'Back.out' });
|
||||
}
|
||||
|
||||
toggleCollectionMenu() {
|
||||
if (!this.collectionContainer) this.createCollectionMenu();
|
||||
this.collectionContainer.setVisible(!this.collectionContainer.visible);
|
||||
if (this.collectionContainer.visible) {
|
||||
this.refreshCollection();
|
||||
}
|
||||
}
|
||||
|
||||
// --- SKILL TREE SYSTEM ---
|
||||
|
||||
toggleSkillTree() {
|
||||
if (!this.skillTreeContainer) this.createSkillTreeMenu();
|
||||
this.skillTreeContainer.setVisible(!this.skillTreeContainer.visible);
|
||||
if (this.skillTreeContainer.visible) {
|
||||
this.refreshSkillTree();
|
||||
}
|
||||
}
|
||||
|
||||
createSkillTreeMenu() {
|
||||
const w = 600;
|
||||
const h = 450;
|
||||
const x = this.scale.width / 2;
|
||||
const y = this.scale.height / 2;
|
||||
|
||||
this.skillTreeContainer = this.add.container(x, y);
|
||||
this.skillTreeContainer.setDepth(2200);
|
||||
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x002200, 0.95); // Dark Green Matrix style
|
||||
bg.fillRoundedRect(-w / 2, -h / 2, w, h, 15);
|
||||
bg.lineStyle(3, 0x00FF00, 1);
|
||||
bg.strokeRoundedRect(-w / 2, -h / 2, w, h, 15);
|
||||
this.skillTreeContainer.add(bg);
|
||||
|
||||
// Header
|
||||
const title = this.add.text(0, -h / 2 + 30, 'HYBRID DNA EVOLUTION', {
|
||||
fontSize: '24px', fontFamily: 'monospace', fontStyle: 'bold', color: '#00FF00'
|
||||
}).setOrigin(0.5);
|
||||
this.skillTreeContainer.add(title);
|
||||
|
||||
// Info Panel
|
||||
this.skillPointsText = this.add.text(0, -h / 2 + 60, 'Available Points: 0', {
|
||||
fontSize: '18px', fontFamily: 'monospace', color: '#FFFF00'
|
||||
}).setOrigin(0.5);
|
||||
this.skillTreeContainer.add(this.skillPointsText);
|
||||
|
||||
// Skills Container
|
||||
this.skillsGrid = this.add.container(-w / 2 + 50, -h / 2 + 100);
|
||||
this.skillTreeContainer.add(this.skillsGrid);
|
||||
|
||||
// Close Button
|
||||
const closeBtn = this.add.text(w / 2 - 30, -h / 2 + 30, 'X', {
|
||||
fontSize: '24px', color: '#FF0000', fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
closeBtn.setInteractive({ useHandCursor: true }).on('pointerdown', () => this.toggleSkillTree());
|
||||
this.skillTreeContainer.add(closeBtn);
|
||||
|
||||
this.skillTreeContainer.setVisible(false);
|
||||
}
|
||||
|
||||
refreshSkillTree() {
|
||||
if (!this.gameScene || !this.gameScene.hybridSkillSystem) return;
|
||||
|
||||
const sys = this.gameScene.hybridSkillSystem;
|
||||
this.skillPointsText.setText(`LEVEL: ${sys.level} | POINTS: ${sys.points}`);
|
||||
|
||||
this.skillsGrid.removeAll(true);
|
||||
|
||||
const skills = Object.entries(sys.skills);
|
||||
let y = 0;
|
||||
|
||||
skills.forEach(([id, skill]) => {
|
||||
// Bg
|
||||
const rowBg = this.add.rectangle(250, y + 25, 500, 50, 0x003300);
|
||||
this.skillsGrid.add(rowBg);
|
||||
|
||||
// Name & Level
|
||||
const nameText = this.add.text(0, y + 10, `${skill.name} (Lv ${skill.level}/${skill.max})`, {
|
||||
fontSize: '18px', fontFamily: 'monospace', color: '#00FF00', fontStyle: 'bold'
|
||||
});
|
||||
this.skillsGrid.add(nameText);
|
||||
|
||||
// Description
|
||||
const descText = this.add.text(0, y + 32, skill.desc, {
|
||||
fontSize: '12px', fontFamily: 'monospace', color: '#88FF88'
|
||||
});
|
||||
this.skillsGrid.add(descText);
|
||||
|
||||
// Upgrade Button
|
||||
if (skill.level < skill.max) {
|
||||
const canUpgrade = sys.points > 0;
|
||||
const btnX = 450;
|
||||
const btnColor = canUpgrade ? 0x00AA00 : 0x555555;
|
||||
|
||||
const btn = this.add.rectangle(btnX, y + 25, 80, 30, btnColor);
|
||||
if (canUpgrade) {
|
||||
btn.setInteractive({ useHandCursor: true });
|
||||
btn.on('pointerdown', () => {
|
||||
if (sys.tryUpgradeSkill(id)) {
|
||||
this.refreshSkillTree(); // Update UI
|
||||
}
|
||||
});
|
||||
}
|
||||
this.skillsGrid.add(btn);
|
||||
|
||||
const btnText = this.add.text(btnX, y + 25, 'UPGRADE', {
|
||||
fontSize: '14px', color: '#FFFFFF'
|
||||
}).setOrigin(0.5);
|
||||
this.skillsGrid.add(btnText);
|
||||
} else {
|
||||
const maxText = this.add.text(450, y + 25, 'MAXED', {
|
||||
fontSize: '14px', color: '#FFFF00', fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
this.skillsGrid.add(maxText);
|
||||
}
|
||||
|
||||
y += 60;
|
||||
});
|
||||
}
|
||||
|
||||
createCollectionMenu() {
|
||||
const w = 500;
|
||||
const h = 400;
|
||||
const x = this.scale.width / 2;
|
||||
const y = this.scale.height / 2;
|
||||
|
||||
this.collectionContainer = this.add.container(x, y);
|
||||
this.collectionContainer.setDepth(2100);
|
||||
|
||||
// Book Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x3e2723, 1); // Dark brown book
|
||||
bg.fillRoundedRect(-w / 2, -h / 2, w, h, 10);
|
||||
bg.lineStyle(4, 0xdec20b, 1); // Gold trim
|
||||
bg.strokeRoundedRect(-w / 2, -h / 2, w, h, 10);
|
||||
|
||||
// Pages
|
||||
bg.fillStyle(0xf5e6c8, 1); // Paper color
|
||||
bg.fillRoundedRect(-w / 2 + 20, -h / 2 + 20, w - 40, h - 40, 5);
|
||||
this.collectionContainer.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(0, -h / 2 + 40, 'COLLECTION ALBUM', {
|
||||
fontSize: '28px',
|
||||
fontFamily: 'serif',
|
||||
color: '#3e2723',
|
||||
fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
this.collectionContainer.add(title);
|
||||
|
||||
// Grid Container
|
||||
this.collectionGrid = this.add.container(-w / 2 + 40, -h / 2 + 80);
|
||||
this.collectionContainer.add(this.collectionGrid);
|
||||
|
||||
// Close Button
|
||||
const closeBtn = this.add.text(w / 2 - 40, -h / 2 + 40, 'X', {
|
||||
fontSize: '24px', color: '#ff0000', fontStyle: 'bold'
|
||||
}).setOrigin(0.5);
|
||||
closeBtn.setInteractive({ useHandCursor: true })
|
||||
.on('pointerdown', () => this.toggleCollectionMenu());
|
||||
this.collectionContainer.add(closeBtn);
|
||||
|
||||
this.collectionContainer.setVisible(false);
|
||||
}
|
||||
|
||||
refreshCollection() {
|
||||
if (!this.gameScene || !this.gameScene.collectionSystem) return;
|
||||
|
||||
this.collectionGrid.removeAll(true);
|
||||
const system = this.gameScene.collectionSystem;
|
||||
const items = Object.entries(system.items);
|
||||
|
||||
// Display stats
|
||||
const progress = system.getProgress();
|
||||
const statText = this.add.text(0, 340, `Collected: ${progress.unlocked} / ${progress.total} (${Math.round(progress.percent)}%)`, {
|
||||
fontSize: '16px', color: '#3e2723', fontStyle: 'italic'
|
||||
}).setOrigin(0.5);
|
||||
this.collectionContainer.add(statText); // Needs to be added to container, not grid
|
||||
|
||||
// Grid Layout
|
||||
let col = 0;
|
||||
let row = 0;
|
||||
const visibleCols = 6;
|
||||
const cellSize = 60;
|
||||
|
||||
items.forEach(([id, data]) => {
|
||||
const isUnlocked = system.has(id);
|
||||
const cx = col * cellSize;
|
||||
const cy = row * cellSize;
|
||||
|
||||
// Slot Bg
|
||||
const slot = this.add.rectangle(cx, cy, 50, 50, isUnlocked ? 0xccb08e : 0xaaaaaa);
|
||||
slot.setStrokeStyle(1, 0x8d6e63);
|
||||
|
||||
this.collectionGrid.add(slot);
|
||||
|
||||
if (isUnlocked) {
|
||||
// Icon
|
||||
const key = `item_${id}`;
|
||||
const tex = this.textures.exists(key) ? key : null;
|
||||
|
||||
if (tex) {
|
||||
const sprite = this.add.sprite(cx, cy, tex).setScale(1.2);
|
||||
this.collectionGrid.add(sprite);
|
||||
} else {
|
||||
this.collectionGrid.add(this.add.text(cx, cy, id.substr(0, 2), { fontSize: '12px', color: '#000' }).setOrigin(0.5));
|
||||
}
|
||||
|
||||
// Tooltip logic could go here (hover)
|
||||
slot.setInteractive();
|
||||
slot.on('pointerover', () => {
|
||||
this.showCollectionTooltip(cx, cy, data);
|
||||
});
|
||||
slot.on('pointerout', () => {
|
||||
this.hideCollectionTooltip();
|
||||
});
|
||||
|
||||
} else {
|
||||
// Locked
|
||||
this.collectionGrid.add(this.add.text(cx, cy, '?', { fontSize: '24px', color: '#555555' }).setOrigin(0.5));
|
||||
}
|
||||
|
||||
col++;
|
||||
if (col >= visibleCols) {
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showCollectionTooltip(x, y, data) {
|
||||
if (this.collectionTooltip) this.collectionTooltip.destroy();
|
||||
|
||||
this.collectionTooltip = this.add.container(this.collectionGrid.x + x + 30, this.collectionGrid.y + y);
|
||||
this.collectionContainer.add(this.collectionTooltip);
|
||||
|
||||
const bg = this.add.rectangle(0, 0, 150, 60, 0x000000, 0.8);
|
||||
const name = this.add.text(0, -15, data.name, { fontSize: '14px', fontStyle: 'bold', color: '#fff' }).setOrigin(0.5);
|
||||
const desc = this.add.text(0, 10, data.category, { fontSize: '12px', color: '#aaa' }).setOrigin(0.5);
|
||||
|
||||
this.collectionTooltip.add([bg, name, desc]);
|
||||
}
|
||||
|
||||
hideCollectionTooltip() {
|
||||
if (this.collectionTooltip) {
|
||||
this.collectionTooltip.destroy();
|
||||
this.collectionTooltip = null;
|
||||
}
|
||||
}
|
||||
|
||||
// --- WORKER MENU ---
|
||||
showWorkerMenu(zombie) {
|
||||
if (this.workerMenuContainer) this.workerMenuContainer.destroy();
|
||||
|
||||
const x = this.scale.width / 2;
|
||||
const y = this.scale.height / 2;
|
||||
const w = 300;
|
||||
const h = 350;
|
||||
|
||||
this.workerMenuContainer = this.add.container(x, y);
|
||||
this.workerMenuContainer.setDepth(2300);
|
||||
|
||||
// Background
|
||||
const bg = this.add.graphics();
|
||||
bg.fillStyle(0x333333, 0.95);
|
||||
bg.fillRoundedRect(-w / 2, -h / 2, w, h, 10);
|
||||
bg.lineStyle(2, 0x00FF00, 1);
|
||||
bg.strokeRoundedRect(-w / 2, -h / 2, w, h, 10);
|
||||
this.workerMenuContainer.add(bg);
|
||||
|
||||
// Title
|
||||
const title = this.add.text(0, -h / 2 + 25, 'ZOMBIE WORKER CONTROL', {
|
||||
fontSize: '20px', fontStyle: 'bold', color: '#00FF00'
|
||||
}).setOrigin(0.5);
|
||||
this.workerMenuContainer.add(title);
|
||||
|
||||
// Status
|
||||
const currentTask = zombie.workerData ? zombie.workerData.type : 'IDLE';
|
||||
const statusText = this.add.text(0, -h / 2 + 55, `Current Task: ${currentTask}`, {
|
||||
fontSize: '16px', color: '#FFFFFF'
|
||||
}).setOrigin(0.5);
|
||||
this.workerMenuContainer.add(statusText);
|
||||
|
||||
// Buttons
|
||||
const buttons = [
|
||||
{ label: 'FARM (Seeds/Harvest)', action: 'FARM', color: 0x8B4513 },
|
||||
{ label: 'MINE (Rocks)', action: 'MINE', color: 0x555555 },
|
||||
{ label: 'CLEAR ZONE (Trees/Debris)', action: 'CLEAR', color: 0xAA0000 },
|
||||
{ label: 'STOP / UNASSIGN', action: 'STOP', color: 0xFF5555 }
|
||||
];
|
||||
|
||||
let btnY = -h / 2 + 100;
|
||||
|
||||
buttons.forEach(btn => {
|
||||
const btnBg = this.add.rectangle(0, btnY, 250, 40, btn.color);
|
||||
btnBg.setInteractive({ useHandCursor: true });
|
||||
btnBg.on('pointerdown', () => {
|
||||
this.assignZombieTask(zombie, btn.action);
|
||||
this.workerMenuContainer.destroy();
|
||||
this.workerMenuContainer = null;
|
||||
});
|
||||
this.workerMenuContainer.add(btnBg);
|
||||
|
||||
const txt = this.add.text(0, btnY, btn.label, { fontSize: '16px', fontStyle: 'bold' }).setOrigin(0.5);
|
||||
this.workerMenuContainer.add(txt);
|
||||
|
||||
btnY += 50;
|
||||
});
|
||||
|
||||
// Close
|
||||
const closeBtn = this.add.text(w / 2 - 20, -h / 2 + 20, 'X', { fontSize: '20px', color: '#FF0000', fontStyle: 'bold' }).setOrigin(0.5);
|
||||
closeBtn.setInteractive({ useHandCursor: true }).on('pointerdown', () => {
|
||||
this.workerMenuContainer.destroy();
|
||||
this.workerMenuContainer = null;
|
||||
});
|
||||
this.workerMenuContainer.add(closeBtn);
|
||||
}
|
||||
|
||||
assignZombieTask(zombie, task) {
|
||||
if (!this.gameScene || !this.gameScene.zombieWorkerSystem) return;
|
||||
|
||||
if (task === 'STOP') {
|
||||
this.gameScene.zombieWorkerSystem.removeWorker(zombie);
|
||||
this.gameScene.events.emit('show-floating-text', {
|
||||
x: zombie.sprite.x, y: zombie.sprite.y - 50, text: 'Idling...', color: '#FFFFFF'
|
||||
});
|
||||
} else {
|
||||
// Assign with radius 6
|
||||
this.gameScene.zombieWorkerSystem.assignWork(zombie, task, 8);
|
||||
this.gameScene.events.emit('show-floating-text', {
|
||||
x: zombie.sprite.x, y: zombie.sprite.y - 50, text: `Task: ${task}`, color: '#00FF00'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user