invulnerable

powerUpBoss & powerUpBossBaby go invulnerable for a second after they die
powerUpBossBaby is even smaller, and a bit slower
growBoss goes invulnerable for a second after one of it dies
shieldingBoss makes shields that are 50% stronger, shieldingBoss has 40% lower health
This commit is contained in:
landgreen
2021-12-14 18:22:08 -08:00
parent 498f867738
commit bd87000277
8 changed files with 224 additions and 143 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1929,10 +1929,11 @@ const b = {
y: best.who.velocity.y * 0.7
});
//draw mob damage circle
console.log(dmg)
simulation.drawList.push({
x: path[1].x,
y: path[1].y,
radius: 600 * dmg * best.who.damageReduction,
radius: Math.sqrt(2000 * dmg * best.who.damageReduction),
color: "rgba(255,0,255,0.2)",
time: simulation.drawTime * 4
});
@@ -2055,14 +2056,17 @@ const b = {
if (best.who.alive) {
best.who.damage(damage);
best.who.locatePlayer();
simulation.drawList.push({ //add dmg to draw queue
x: path[path.length - 1].x,
y: path[path.length - 1].y,
// radius: Math.sqrt(damage) * 100 * mob[k].damageReduction,
radius: 600 * damage * best.who.damageReduction,
color: tech.laserColorAlpha,
time: simulation.drawTime
});
if (best.who.damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: path[path.length - 1].x,
y: path[path.length - 1].y,
// radius: Math.sqrt(damage) * 100 * mob[k].damageReduction,
// radius: 600 * damage * best.who.damageReduction,
radius: Math.sqrt(2000 * damage * best.who.damageReduction) + 2,
color: tech.laserColorAlpha,
time: simulation.drawTime
});
}
if (tech.isLaserPush) { //push mobs away
const index = path.length - 1
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
@@ -3340,13 +3344,15 @@ const b = {
if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg, tech.isShieldPierce);
if (who.alive) who.foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40 * who.damageReduction,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
if (who.damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
}
}
}
@@ -3393,13 +3399,15 @@ const b = {
if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg, tech.isShieldPierce);
if (who.alive) who.foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40 * who.damageReduction,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
if (who.damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
}
}
}
@@ -3649,13 +3657,16 @@ const b = {
const dmg = 0.5 * b.dmgScale
q[i].damage(dmg);
if (q[i].alive) q[i].foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: 600 * dmg * q[i].damageReduction,
color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime
});
if (q[i].damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
// radius: 600 * dmg * q[i].damageReduction,
radius: Math.sqrt(2000 * dmg * q[i].damageReduction) + 2,
color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime
});
}
}
}
}
@@ -4202,14 +4213,17 @@ const b = {
y: best.who.velocity.y * 0.7
});
//draw mob damage circle
simulation.drawList.push({
x: path[1].x,
y: path[1].y,
// radius: Math.sqrt(dmg) * 50 * mob[k].damageReduction,
radius: 600 * dmg * best.who.damageReduction,
color: "rgba(255,0,255,0.2)",
time: simulation.drawTime * 4
});
if (best.who.damageReduction) {
simulation.drawList.push({
x: path[1].x,
y: path[1].y,
// radius: Math.sqrt(dmg) * 50 * mob[k].damageReduction,
// radius: 600 * dmg * best.who.damageReduction,
radius: Math.sqrt(2000 * dmg * best.who.damageReduction) + 2,
color: "rgba(255,0,255,0.2)",
time: simulation.drawTime * 4
});
}
} else if (!best.who.isStatic) {
//push blocks away
const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass)))
@@ -4296,13 +4310,16 @@ const b = {
const dmg = 0.4 * b.dmgScale * (this.isUpgraded ? 4 : 1) * (tech.isCrit ? 4 : 1)
q[i].damage(dmg);
if (q[i].alive) q[i].foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: 600 * dmg * q[i].damageReduction,
color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime
});
if (q[i].damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
// radius: 600 * dmg * q[i].damageReduction,
radius: Math.sqrt(2000 * dmg * q[i].damageReduction) + 2,
color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime
});
}
}
}
}
@@ -5210,13 +5227,15 @@ const b = {
Matter.Body.setVelocity(q[i], Vector.mult(q[i].velocity, 0.9))
this.endCycle = 0; //bullet ends cycle after doing damage
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40 * q[i].damageReduction,
color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime
});
if (q[i].damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(dmg + 1.1) * 40 * q[i].damageReduction + 3,
color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime
});
}
}
},
wiggle() {

View File

@@ -179,13 +179,15 @@ function collisionChecks(event) {
// console.log(dmg)
mob[k].damage(dmg);
if (mob[k].alive) mob[k].foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40 * mob[k].damageReduction,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
if (mob[k].damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(dmg + 1.1) * 40 * mob[k].damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
if (tech.isLessDamageReduction && !mob[k].shield) mob[k].damageReduction *= mob[k].isBoss ? 1.01 : 1.06
return;
}
@@ -214,13 +216,15 @@ function collisionChecks(event) {
obj.hasFragmented = true;
b.targetedNail(obj.position, tech.fragments * 4)
}
simulation.drawList.push({
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40 * mob[k].damageReduction,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
if (mob[k].damageReduction) {
simulation.drawList.push({
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(dmg + 1.1) * 40 * mob[k].damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
return;
}
}

View File

@@ -2344,8 +2344,8 @@ const level = {
// spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(3200, -500)
// spawn.powerUpBossBaby(3200, -500)
spawn.powerUpBoss(3200, -500)
spawn.powerUpBossBaby(3200, -500)
// spawn.snakeBoss(1700, -500)
// spawn.streamBoss(3200, -500)
// spawn.pulsarBoss(1700, -500)
@@ -2360,14 +2360,14 @@ const level = {
// spawn.blinkBoss(3200, -500)
// spawn.mantisBoss(1700, -500)
// spawn.tetherBoss(1700, -500) //go to actual level?
spawn.revolutionBoss(1900, -500)
// spawn.revolutionBoss(1900, -500)
// spawn.bomberBoss(1400, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.shieldingBoss(1700, -500)
// spawn.launcherOne(1700, -500)
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
// spawn.pulsar(1900, -500)
spawn.pulsar(1900, -500)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
// mob[mob.length - 1].isShielded = true
// spawn.nodeGroup(1200, 0, "grenadier")

View File

@@ -59,7 +59,7 @@ const mobs = {
}
function applySlow(whom) {
if (!whom.shield && !whom.isShielded && !m.isBodiesAsleep && who.damageReduction > 0) {
if (!whom.shield && !whom.isShielded && !m.isBodiesAsleep) {
if (whom.isBoss) cycles = Math.floor(cycles * 0.25)
let i = whom.status.length
while (i--) {
@@ -98,7 +98,7 @@ const mobs = {
}
},
statusStun(who, cycles = 180) {
if (!who.shield && !who.isShielded && !m.isBodiesAsleep && who.damageReduction > 0) {
if (!who.shield && !who.isShielded && !m.isBodiesAsleep) {
Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.8,
y: who.velocity.y * 0.8
@@ -156,13 +156,15 @@ const mobs = {
if ((simulation.cycle - this.startCycle) % 30 === 0 && !m.isBodiesAsleep) {
let dmg = b.dmgScale * this.dmg
who.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue
x: who.position.x + (Math.random() - 0.5) * who.radius * 0.5,
y: who.position.y + (Math.random() - 0.5) * who.radius * 0.5,
radius: Math.log(2 * dmg + 1.1) * 40,
color: "rgba(0,80,80,0.9)",
time: simulation.drawTime
});
if (who.damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: who.position.x + (Math.random() - 0.5) * who.radius * 0.5,
y: who.position.y + (Math.random() - 0.5) * who.radius * 0.5,
radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3,
color: "rgba(0,80,80,0.9)",
time: simulation.drawTime
});
}
}
},
endEffect() {},

View File

@@ -3618,13 +3618,15 @@ const m = {
if (tech.isCrit && mob[k].isStunned) dmg *= 4
mob[k].damage(dmg);
if (mob[k].alive) mob[k].foundPlayer();
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
if (mob[k].damageReduction) {
simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(dmg + 1.1) * 40 * mob[k].damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
return;
}
//mob + body collisions
@@ -3652,13 +3654,15 @@ const m = {
obj.hasFragmented = true;
b.targetedNail(obj.position, tech.fragments * 4)
}
simulation.drawList.push({
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
if (mob[k].damageReduction) {
simulation.drawList.push({
x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(dmg + 1.1) * 40 * mob[k].damageReduction + 3,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
return;
}
}

View File

@@ -1102,11 +1102,9 @@ const spawn = {
mobs.spawn(x + Math.random(), y + Math.random(), 6, radius, "hsl(144, 15%, 50%)") //);
let me = mob[mob.length - 1];
me.isBoss = true;
me.isBuffBoss = true;
me.buffID = buffID
me.memory = Infinity;
// me.showHealthBar = false;
me.isVerticesChange = true
me.frictionAir = 0.012
me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
@@ -1118,14 +1116,16 @@ const spawn = {
me.accelMag = 0.00005 //* simulation.accelScale;
me.setBuffed = function() {
this.buffCount++
this.accelMag += 0.000035 //* Math.sqrt(simulation.accelScale)
// Matter.Body.setDensity(this, 0.001 + 0.0003 * this.buffCount) // normal density is 0.001 //+ 0.0005 * Math.sqrt(simulation.difficulty)
this.accelMag += 0.000024 //* Math.sqrt(simulation.accelScale)
this.fill = `hsl(144, ${5 + 10 * this.buffCount}%, 50%)`
const scale = 1.132;
const scale = 1.135;
Matter.Body.scale(this, scale, scale);
this.radius *= scale;
// this.health += 0.03
// if (this.health > 1) this.health = 1
this.isInvulnerable = true
if (this.damageReduction) this.startingDamageReduction = this.damageReduction
this.damageReduction = 0
this.invulnerabilityCountDown = simulation.difficulty * 2
}
me.onDeath = function() {
this.isBuffBoss = false;
@@ -1144,13 +1144,30 @@ const spawn = {
powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // manual power up spawn to avoid spawning too many tech with "symbiosis"
}
}
me.damageReduction = 0.18 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
//required setup for invulnerable
me.isInvulnerable = false
me.invulnerabilityCountDown = 0
me.do = function() {
// this.armor();
if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown--
ctx.beginPath();
let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20;
ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.stroke();
} else {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
}
this.alwaysSeePlayer();
this.checkStatus();
this.attraction();
// if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs
// const repelRange = 100 + 4 * this.radius
// const attractRange = 240
@@ -1168,17 +1185,17 @@ const spawn = {
// }
}
},
powerUpBossBaby(x, y, vertices = 9, radius = 70) {
mobs.spawn(x, y, vertices, radius, "transparent");
powerUpBossBaby(x, y, vertices = 9, radius = 60) {
mobs.spawn(x, y, vertices, radius, "rgba(225,240,245,0.4)"); //"rgba(120,140,150,0.4)"
let me = mob[mob.length - 1];
me.isBoss = true;
me.frictionAir = 0.006
me.seeAtDistance2 = 1000000;
me.accelMag = 0.0007 * simulation.accelScale;
Matter.Body.setDensity(me, 0.0008); //normal is 0.001
me.accelMag = 0.0004 + 0.0003 * simulation.accelScale;
// Matter.Body.setDensity(me, 0.001); //normal is 0.001
me.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map
me.memory = Infinity;
me.seePlayerFreq = 30
me.seePlayerFreq = 20
me.lockedOn = null;
if (vertices === 9) {
//on primary spawn
@@ -1188,6 +1205,11 @@ const spawn = {
} else if (!m.isCloak) {
me.foundPlayer();
}
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
me.invulnerabilityCountDown = 60 + simulation.difficulty * 2
me.onHit = function() { //run this function on hitting player
if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255");
@@ -1207,10 +1229,25 @@ const spawn = {
}
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
};
me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
// this.armor();
this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown--
ctx.beginPath();
let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20;
ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.stroke();
} else {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
}
// this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
// this.fill = `hsla(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%,0.3)`
//steal all power ups
for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
@@ -1246,6 +1283,13 @@ const spawn = {
} else if (!m.isCloak) {
me.foundPlayer();
}
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
me.invulnerabilityCountDown = 60 + simulation.difficulty * 2
me.onHit = function() { //run this function on hitting player
if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255");
@@ -1265,11 +1309,24 @@ const spawn = {
}
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
// this.armor();
if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown--
ctx.beginPath();
let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20;
ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.stroke();
} else {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
}
this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
//steal all power ups
for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
powerUp[i].collisionFilter.mask = 0
@@ -1279,7 +1336,6 @@ const spawn = {
y: 0
})
}
this.seePlayerCheckByDistance();
this.attraction();
this.checkStatus();
@@ -1926,7 +1982,7 @@ const spawn = {
this.invulnerabilityCountDown--
} else {
this.isInvulnerable = true
this.startingDamageReduction = this.damageReduction
if (this.damageReduction) this.startingDamageReduction = this.damageReduction
this.damageReduction = 0
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) {
@@ -3363,10 +3419,20 @@ const spawn = {
//invulnerable every other revolution
me.isInvulnerable = false
me.invulnerable = function() {
//draw trigger angle
// ctx.beginPath();
// ctx.moveTo(this.position.x, this.position.y);
// const a = this.angle + Math.PI / 2
// const unit = { x: Math.cos(a), y: Math.sin(a) }
// const edge = Vector.add(this.position, Vector.mult(unit, this.radius))
// ctx.lineTo(edge.x, edge.y);
// ctx.lineWidth = 5;
// ctx.strokeStyle = "#000";
// ctx.stroke();
if (this.laserAngle % (4 * Math.PI) > 2 * Math.PI) {
if (!this.isInvulnerable) {
this.isInvulnerable = true
this.startingDamageReduction = this.damageReduction
if (this.damageReduction) this.startingDamageReduction = this.damageReduction
this.damageReduction = 0
}
} else if (this.isInvulnerable) {
@@ -4397,7 +4463,7 @@ const spawn = {
me.onDamage = function() {
this.cycle = 0
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
// this.armor();
this.checkStatus();
@@ -4422,6 +4488,8 @@ const spawn = {
ctx.moveTo(this.position.x, this.position.y)
ctx.lineTo(mob[i].position.x, mob[i].position.y)
spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
// me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
mob[mob.length - 1].damageReduction = 0.5 * 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //shields are extra strong
}
}
if (!this.isShielded && this.alive) spawn.shield(this, this.position.x, this.position.y, 1, true);

View File

@@ -1,37 +1,20 @@
******************************************************** NEXT PATCH **************************************************
mantisBoss: 3 punching mobs, eject your ammo when you get punched
invulnerable except for 1 second after moving
powerUpBossBaby: smaller, cuter, faster, can't move through walls
slashBoss renamed revolutionBoss
invulnerable every other revolution of it's blades
new mob state: invulnerable - immune to damage and status effects (stun, dots, freeze)
damage and harm circle graphic size have been made more consistent
bug fixes
powerUpBoss & powerUpBossBaby go invulnerable for a second after they die
powerUpBossBaby is even smaller, and a bit slower
growBoss goes invulnerable for a second after one of it dies
shieldingBoss makes shields that are 50% stronger, shieldingBoss has 40% lower health
******************************************************** TODO ********************************************************
history vision messes up when drones hit boss?
for babypowerupboss
some boss mobs need invulnerability phases
powerUpBoss after death?
nerf powerup boss health or acceleration to balance
growboss
after one dies
tech: heal power ups spawn as research instead
research heals for 10 health
using research does 10 damage
electric motors: increases movement speed and jump height, but jumping and moving costs energy
overwrite the key event listeners?
JUNK tech?
make the shields that shieldBoss adds twice as damage resistant
mob that fires bullets in 4,5,6,7 different directions at once, no aiming
bug once: switching from shotgun to harpoon somehow set b.activeGun to not defined
@@ -515,6 +498,7 @@ possible names for tech
axial motor
hall effect thrusters
spaghettification
particle accelerator
a tutorial / lore intro
needs to be optional so it doesn't slow experienced players