feat(gameplay): add crazy dave casino and bank, and zombie mutation lab
This commit is contained in:
1 parent
d8be8f4366
commit
b8db5a123d
16 files changed
+2365
-135
No files matched your search
+179
-4
@@ -21,6 +21,13 @@ window.Plant = class Plant {
|
||||
this.recoilDps = 0;
|
||||
|
||||
switch (type) {
|
||||
case 'mega_sunflower':
|
||||
this.maxHealth = 5000;
|
||||
this.sunInterval = 5;
|
||||
this.sunAmount = 100;
|
||||
this.sunTimer = 2;
|
||||
this.isRaidBoss = true;
|
||||
break;
|
||||
case 'sunflower':
|
||||
this.sunInterval = this.level === 3 ? 9 : (this.level === 2 ? 10 : 13);
|
||||
this.sunAmount = this.level >= 2 ? 35 : 25;
|
||||
@@ -108,6 +115,17 @@ window.Plant = class Plant {
|
||||
this.shootTimer = 1.0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (window.PvZConfig) {
|
||||
const hpMult = window.PvZConfig.getPlantHpMult();
|
||||
const dmgMult = window.PvZConfig.getPlantDamageMult();
|
||||
const sunIntMult = window.PvZConfig.getSunIntervalMult();
|
||||
|
||||
this.maxHealth = Math.round(this.maxHealth * hpMult);
|
||||
this.damage = Math.round(this.damage * dmgMult);
|
||||
if (this.sunInterval) this.sunInterval = this.sunInterval * sunIntMult;
|
||||
}
|
||||
|
||||
this.health = this.maxHealth;
|
||||
}
|
||||
|
||||
@@ -119,15 +137,25 @@ window.Plant = class Plant {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Sunflower & Sun-shroom
|
||||
if (this.type === 'sunflower') {
|
||||
// 1. Sunflower, Mega Sunflower & Sun-shroom
|
||||
if (this.type === 'sunflower' || this.type === 'mega_sunflower') {
|
||||
this.sunTimer += dt;
|
||||
if (this.sunTimer >= this.sunInterval) {
|
||||
this.sunTimer = 0;
|
||||
gameState.spawnSun(this.x + (Math.random() * 20 - 10), this.y + (Math.random() * 20 - 10), this.sunAmount || 25, false);
|
||||
|
||||
// Tier 3: Heal neighboring plants!
|
||||
if (this.level === 3) {
|
||||
if (this.type === 'mega_sunflower') {
|
||||
// Raid Boss solar pulse: heal all plants on the lawn
|
||||
for (const p of gameState.plants) {
|
||||
if (p !== this && p.health > 0) {
|
||||
p.health = Math.min(p.maxHealth, p.health + 25);
|
||||
if (gameState.combat && gameState.combat.createSplash) {
|
||||
gameState.combat.createSplash(p.x, p.y, '#ffd54f', 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (this.level === 3) {
|
||||
// Tier 3: Heal neighboring plants!
|
||||
for (const p of gameState.plants) {
|
||||
if (p !== this && Math.abs(p.col - this.col) <= 1 && Math.abs(p.row - this.row) <= 1 && p.health > 0) {
|
||||
p.health = Math.min(p.maxHealth, p.health + 30);
|
||||
@@ -426,6 +454,9 @@ window.Plant = class Plant {
|
||||
case 'melonpult':
|
||||
this.drawMelonpult(ctx);
|
||||
break;
|
||||
case 'mega_sunflower':
|
||||
this.drawMegaSunflower(ctx);
|
||||
break;
|
||||
}
|
||||
|
||||
// Tier Stars (Level 2 & 3)
|
||||
@@ -494,6 +525,150 @@ window.Plant = class Plant {
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
drawMegaSunflower(ctx) {
|
||||
// Grand glowing aura
|
||||
const glowGradient = ctx.createRadialGradient(0, -10, 10, 0, -10, 60);
|
||||
glowGradient.addColorStop(0, 'rgba(255, 215, 0, 0.6)');
|
||||
glowGradient.addColorStop(0.7, 'rgba(255, 152, 0, 0.3)');
|
||||
glowGradient.addColorStop(1, 'rgba(255, 100, 0, 0)');
|
||||
ctx.fillStyle = glowGradient;
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, -10, 60, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Leaves / base
|
||||
ctx.fillStyle = '#2e7d32';
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(-26, 22, 22, 10, -0.4, 0, Math.PI * 2);
|
||||
ctx.ellipse(26, 22, 22, 10, 0.4, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Big stem
|
||||
ctx.strokeStyle = '#1b5e20';
|
||||
ctx.lineWidth = 10;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 32);
|
||||
ctx.quadraticCurveTo(-5, 12, 0, -5);
|
||||
ctx.stroke();
|
||||
|
||||
// 16 Petals with pulse and slow rotation
|
||||
const petalCount = 16;
|
||||
const pulse = 1 + Math.sin(this.animTime * 3) * 0.08;
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(0, -10);
|
||||
ctx.scale(pulse, pulse);
|
||||
|
||||
for (let i = 0; i < petalCount; i++) {
|
||||
const angle = (i * (Math.PI * 2) / petalCount) + this.animTime * 0.3;
|
||||
ctx.save();
|
||||
ctx.rotate(angle);
|
||||
|
||||
// Outer petal
|
||||
ctx.fillStyle = i % 2 === 0 ? '#ffca28' : '#ffa000';
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(0, -32, 11, 20, 0, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Inner petal highlight
|
||||
ctx.fillStyle = '#fff59d';
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(0, -30, 5, 12, 0, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
// Flower Center
|
||||
ctx.fillStyle = '#5d4037';
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 24, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.strokeStyle = '#8d6e63';
|
||||
ctx.lineWidth = 3;
|
||||
ctx.stroke();
|
||||
|
||||
// Smiling Face & Eyes
|
||||
ctx.fillStyle = '#212121';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-8, -4, 4, 0, Math.PI * 2);
|
||||
ctx.arc(8, -4, 4, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Eye sparkles
|
||||
ctx.fillStyle = '#ffffff';
|
||||
ctx.beginPath();
|
||||
ctx.arc(-9, -6, 1.5, 0, Math.PI * 2);
|
||||
ctx.arc(7, -6, 1.5, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
// Big Royal Smile
|
||||
ctx.strokeStyle = '#3e2723';
|
||||
ctx.lineWidth = 2.5;
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 5, 9, 0.2, Math.PI - 0.2);
|
||||
ctx.stroke();
|
||||
|
||||
// Royal Crown
|
||||
ctx.fillStyle = '#ffd700';
|
||||
ctx.strokeStyle = '#e65100';
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(-16, -22);
|
||||
ctx.lineTo(-14, -36);
|
||||
ctx.lineTo(-6, -26);
|
||||
ctx.lineTo(0, -40);
|
||||
ctx.lineTo(6, -26);
|
||||
ctx.lineTo(14, -36);
|
||||
ctx.lineTo(16, -22);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
|
||||
// Crown rubies
|
||||
ctx.fillStyle = '#e91e63';
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, -32, 2.5, 0, Math.PI * 2);
|
||||
ctx.arc(-10, -28, 2, 0, Math.PI * 2);
|
||||
ctx.arc(10, -28, 2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
|
||||
// Raid Boss Overhead Health Bar & Label
|
||||
const barWidth = 68;
|
||||
const barHeight = 8;
|
||||
const barX = -barWidth / 2;
|
||||
const barY = -54;
|
||||
const hpRatio = Math.max(0, this.health / this.maxHealth);
|
||||
|
||||
// Dark background
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.75)';
|
||||
ctx.fillRect(barX - 1, barY - 1, barWidth + 2, barHeight + 2);
|
||||
|
||||
// Health bar with gradient
|
||||
const hpGrad = ctx.createLinearGradient(barX, barY, barX + barWidth, barY);
|
||||
hpGrad.addColorStop(0, '#ffd700');
|
||||
hpGrad.addColorStop(1, '#ff3d00');
|
||||
ctx.fillStyle = hpGrad;
|
||||
ctx.fillRect(barX, barY, barWidth * hpRatio, barHeight);
|
||||
|
||||
// Border
|
||||
ctx.strokeStyle = '#ffffff';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeRect(barX - 1, barY - 1, barWidth + 2, barHeight + 2);
|
||||
|
||||
// Boss Title
|
||||
ctx.font = 'bold 9px sans-serif';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.fillStyle = '#ffe082';
|
||||
ctx.shadowColor = 'rgba(0, 0, 0, 0.8)';
|
||||
ctx.shadowBlur = 3;
|
||||
ctx.fillText(`👑 MEGA SUNFLOWER [${Math.ceil(this.health)}]`, 0, barY - 4);
|
||||
ctx.shadowBlur = 0;
|
||||
}
|
||||
|
||||
drawPeashooter(ctx, isSnow) {
|
||||
const mainColor = isSnow ? '#29b6f6' : '#4caf50';
|
||||
const darkColor = isSnow ? '#0288d1' : '#2e7d32';
|
||||
|
||||
Reference in new issue
Block a user