mantisBoss

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
This commit is contained in:
landgreen
2021-12-13 19:11:46 -08:00
parent 4137d719da
commit 498f867738
13 changed files with 555 additions and 125 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1932,7 +1932,7 @@ const b = {
simulation.drawList.push({ simulation.drawList.push({
x: path[1].x, x: path[1].x,
y: path[1].y, y: path[1].y,
radius: Math.sqrt(dmg) * 50, radius: 600 * dmg * best.who.damageReduction,
color: "rgba(255,0,255,0.2)", color: "rgba(255,0,255,0.2)",
time: simulation.drawTime * 4 time: simulation.drawTime * 4
}); });
@@ -2058,7 +2058,8 @@ const b = {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: path[path.length - 1].x, x: path[path.length - 1].x,
y: path[path.length - 1].y, y: path[path.length - 1].y,
radius: Math.sqrt(damage) * 100, // radius: Math.sqrt(damage) * 100 * mob[k].damageReduction,
radius: 600 * damage * best.who.damageReduction,
color: tech.laserColorAlpha, color: tech.laserColorAlpha,
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -2705,7 +2706,7 @@ const b = {
} }
}, },
onEnd() { onEnd() {
if (tech.isDroneRespawn) { if (tech.isDroneRespawn && b.inventory.length) {
const who = b.guns[b.activeGun] const who = b.guns[b.activeGun]
if (who.name === "drones" && who.ammo > 0 && mob.length) { if (who.name === "drones" && who.ammo > 0 && mob.length) {
b.drone({ x: this.position.x, y: this.position.y }, 0) b.drone({ x: this.position.x, y: this.position.y }, 0)
@@ -3178,7 +3179,7 @@ const b = {
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
if (targets.length - i > 0) { if (targets.length - i > 0) {
const index = Math.floor(Math.random() * targets.length) const index = Math.floor(Math.random() * targets.length)
const speed = 10 + 10 * Math.random() const speed = 6 + 6 * Math.random()
const velocity = Vector.mult(Vector.normalise(Vector.sub(targets[index].position, this.position)), speed) const velocity = Vector.mult(Vector.normalise(Vector.sub(targets[index].position, this.position)), speed)
b.foam(this.position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius) b.foam(this.position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
} else { } else {
@@ -3342,7 +3343,7 @@ const b = {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: this.position.x, x: this.position.x,
y: this.position.y, y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: Math.log(2 * dmg + 1.1) * 40 * who.damageReduction,
color: simulation.playerDmgColor, color: simulation.playerDmgColor,
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -3395,7 +3396,7 @@ const b = {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: this.position.x, x: this.position.x,
y: this.position.y, y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: Math.log(2 * dmg + 1.1) * 40 * who.damageReduction,
color: simulation.playerDmgColor, color: simulation.playerDmgColor,
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -3651,7 +3652,7 @@ const b = {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: this.position.x, x: this.position.x,
y: this.position.y, y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: 600 * dmg * q[i].damageReduction,
color: 'rgba(0,0,0,0.4)', color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -4204,7 +4205,8 @@ const b = {
simulation.drawList.push({ simulation.drawList.push({
x: path[1].x, x: path[1].x,
y: path[1].y, y: path[1].y,
radius: Math.sqrt(dmg) * 50, // radius: Math.sqrt(dmg) * 50 * mob[k].damageReduction,
radius: 600 * dmg * best.who.damageReduction,
color: "rgba(255,0,255,0.2)", color: "rgba(255,0,255,0.2)",
time: simulation.drawTime * 4 time: simulation.drawTime * 4
}); });
@@ -4297,7 +4299,7 @@ const b = {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: this.position.x, x: this.position.x,
y: this.position.y, y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: 600 * dmg * q[i].damageReduction,
color: 'rgba(0,0,0,0.4)', color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -5211,7 +5213,7 @@ const b = {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: this.position.x, x: this.position.x,
y: this.position.y, y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: Math.log(2 * dmg + 1.1) * 40 * q[i].damageReduction,
color: 'rgba(0,0,0,0.4)', color: 'rgba(0,0,0,0.4)',
time: simulation.drawTime time: simulation.drawTime
}); });

View File

@@ -155,7 +155,7 @@ function collisionChecks(event) {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 2000, radius: Math.sqrt(dmg) * 500,
color: "rgba(255,0,255,0.2)", color: "rgba(255,0,255,0.2)",
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -163,7 +163,7 @@ function collisionChecks(event) {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: dmg * 500, radius: Math.sqrt(dmg) * 200,
color: simulation.mobDmgColor, color: simulation.mobDmgColor,
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -182,7 +182,7 @@ function collisionChecks(event) {
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: Math.log(2 * dmg + 1.1) * 40 * mob[k].damageReduction,
color: simulation.playerDmgColor, color: simulation.playerDmgColor,
time: simulation.drawTime time: simulation.drawTime
}); });
@@ -217,7 +217,7 @@ function collisionChecks(event) {
simulation.drawList.push({ simulation.drawList.push({
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
y: pairs[i].activeContacts[0].vertex.y, y: pairs[i].activeContacts[0].vertex.y,
radius: Math.log(2 * dmg + 1.1) * 40, radius: Math.log(2 * dmg + 1.1) * 40 * mob[k].damageReduction,
color: simulation.playerDmgColor, color: simulation.playerDmgColor,
time: simulation.drawTime time: simulation.drawTime
}); });

View File

@@ -215,32 +215,30 @@ const build = {
if (tech.missileBotCount) botText += `<br>missile-bots: ${tech.missileBotCount}` if (tech.missileBotCount) botText += `<br>missile-bots: ${tech.missileBotCount}`
const harm = (1 - m.harmReduction()) * 100 const harm = (1 - m.harmReduction()) * 100
let text = "" let text = `<div class="pause-grid-module" style = "font-size: 13px;line-height: 120%;padding: 5px;">`
if (!simulation.isChoosing) text += `<div class="pause-grid-module"> if (!simulation.isChoosing) text += `<br><span style="font-size:1.5em;font-weight: 600;">PAUSED</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; press P to resume
<span style="font-size:1.5em;font-weight: 600;">PAUSED</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; press P to resume</div>` <br><br><svg class="SVG-button" onclick="build.shareURL(false)" width="92" height="20" style="padding:0px; margin: 1px;">
text += `<div class="pause-grid-module" style = "font-size: 13px;line-height: 120%;padding: 5px;"> <g stroke='none' fill='#333' stroke-width="2" font-size="14px" font-family="Ariel, sans-serif"> <text x="5" y="15">copy build url</text></g>
${simulation.isCheating? "<em>lore disabled</em><br><br>": ""} </svg><br>`
<strong class='color-d'>damage</strong> increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}% text += `<strong class='color-d'>damage</strong> increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}%
<br><strong class='color-harm'>harm</strong> reduction: ${harm.toFixed(harm > 90 ? 2 : 0)}% <br><strong class='color-harm'>harm</strong> reduction: ${harm.toFixed(harm > 90 ? 2 : 0)}%
<br><strong><em>fire delay</em></strong> decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}% <br><strong><em>fire delay</em></strong> decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
<br><strong class='color-dup'>duplication</strong> chance: ${(tech.duplicationChance()*100).toFixed(0)}% <br><strong class='color-dup'>duplication</strong> chance: ${(tech.duplicationChance()*100).toFixed(0)}%
${botText} ${botText}
<br> <br>
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count} <br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count}
<br><strong class='color-h'>health</strong>: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)}) &nbsp; <strong class='color-f'>energy</strong>: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)}) <br><strong class='color-h'>health</strong>: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)}) &nbsp; <strong class='color-f'>energy</strong>: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)})
<br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)}) <br><strong class='color-g'>gun</strong>: ${b.activeGun !== null ? b.guns[b.activeGun].name: "null"} &nbsp; <strong class='color-g'>ammo</strong>: ${b.activeGun !== null ? b.guns[b.activeGun].ammo: "0"}
<br>mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)} <br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
<br> <br>mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)}
<br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles <br>
<br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups <br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles
<br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups
<br>damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }% <br>damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }%
<br>harm difficulty scale: ${(simulation.dmgScale*100).toFixed(0)}% <br>harm difficulty scale: ${(simulation.dmgScale*100).toFixed(0)}%
<br>heal difficulty scale: ${(simulation.healScale*100).toFixed(1)}% <br>heal difficulty scale: ${(simulation.healScale*100).toFixed(1)}%
<br> ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
<svg class="SVG-button" onclick="build.shareURL(false)" width="110" height="25" style="padding:2px; margin: 10px;">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif"> <text x="5" y="18">copy build url</text> </g>
</svg>
</div>`; </div>`;
for (let i = 0, len = b.inventory.length; i < len; i++) { for (let i = 0, len = b.inventory.length; i < len; i++) {
text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>` text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`

View File

@@ -16,8 +16,8 @@ const level = {
// localSettings.levelsClearedLastGame = 10 // localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("wormhole") // m.setField("plasma torch")
// b.giveGuns("shotgun") // b.giveGuns("drones")
// b.giveGuns("nail gun") // b.giveGuns("nail gun")
// b.giveGuns("harpoon") // b.giveGuns("harpoon")
// tech.giveTech("needle gun") // tech.giveTech("needle gun")
@@ -2337,13 +2337,15 @@ const level = {
spawn.mapRect(4850, -275, 50, 175); spawn.mapRect(4850, -275, 50, 175);
//??? //???
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why
m.addHealth(Infinity)
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
// spawn.launcherOne(1700, -500)
// spawn.launcherBoss(3200, -500) // spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500) // spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(3200, -500) // spawn.powerUpBoss(3200, -500)
// spawn.powerUpBossBaby(3200, -500)
// spawn.snakeBoss(1700, -500) // spawn.snakeBoss(1700, -500)
// spawn.streamBoss(3200, -500) // spawn.streamBoss(3200, -500)
// spawn.pulsarBoss(1700, -500) // spawn.pulsarBoss(1700, -500)
@@ -2355,28 +2357,19 @@ const level = {
// spawn.laserBombingBoss(1700, -500) // spawn.laserBombingBoss(1700, -500)
// spawn.launcherBoss(3200, -500) // spawn.launcherBoss(3200, -500)
// spawn.blockBoss(1700, -500) // spawn.blockBoss(1700, -500)
// spawn.slashBoss(3200, -500) // spawn.blinkBoss(3200, -500)
// spawn.spiderBoss(3200, -500) // spawn.mantisBoss(1700, -500)
// spawn.tetherBoss(1700, -500) //go to actual level? // spawn.tetherBoss(1700, -500) //go to actual level?
spawn.revolutionBoss(1900, -500)
// spawn.bomberBoss(1400, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.launcherOne(1700, -500)
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40); // 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) // for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
// spawn.slashBoss(1900, -500) // spawn.pulsar(1900, -500)
spawn.pulsar(1900, -500)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1); // spawn.shield(mob[mob.length - 1], 1900, -500, 1);
// mob[mob.length - 1].isShielded = true // mob[mob.length - 1].isShielded = true
// spawn.growBossCulture(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.blinkBoss(1600, -500)
// spawn.laserTargetingBoss(1700, -120)
// spawn.bomberBoss(1400, -500)
// spawn.laser(1800, -320)
// spawn.laserBombingBoss(1600, -500)
// spawn.laserTargetingBoss(1600, -500)
// spawn.laserBoss(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.nodeGroup(1200, -500, "grenadier")
// spawn.nodeGroup(1800, -500, "grenadier")
// spawn.nodeGroup(1200, 0, "grenadier") // spawn.nodeGroup(1200, 0, "grenadier")
// spawn.blinkBoss(1200, -500) // spawn.blinkBoss(1200, -500)
// spawn.suckerBoss(2900, -500) // spawn.suckerBoss(2900, -500)

View File

@@ -59,7 +59,7 @@ const mobs = {
} }
function applySlow(whom) { function applySlow(whom) {
if (!whom.shield && !whom.isShielded && !m.isBodiesAsleep) { if (!whom.shield && !whom.isShielded && !m.isBodiesAsleep && who.damageReduction > 0) {
if (whom.isBoss) cycles = Math.floor(cycles * 0.25) if (whom.isBoss) cycles = Math.floor(cycles * 0.25)
let i = whom.status.length let i = whom.status.length
while (i--) { while (i--) {
@@ -98,7 +98,7 @@ const mobs = {
} }
}, },
statusStun(who, cycles = 180) { statusStun(who, cycles = 180) {
if (!who.shield && !who.isShielded && !m.isBodiesAsleep) { if (!who.shield && !who.isShielded && !m.isBodiesAsleep && who.damageReduction > 0) {
Matter.Body.setVelocity(who, { Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.8, x: who.velocity.x * 0.8,
y: who.velocity.y * 0.8 y: who.velocity.y * 0.8
@@ -150,7 +150,7 @@ const mobs = {
} }
}, },
statusDoT(who, tickDamage, cycles = 180) { statusDoT(who, tickDamage, cycles = 180) {
if (!who.isShielded && who.alive) { if (!who.isShielded && who.alive && who.damageReduction > 0) {
who.status.push({ who.status.push({
effect() { effect() {
if ((simulation.cycle - this.startCycle) % 30 === 0 && !m.isBodiesAsleep) { if ((simulation.cycle - this.startCycle) % 30 === 0 && !m.isBodiesAsleep) {
@@ -579,7 +579,7 @@ const mobs = {
springAttack() { springAttack() {
// set new values of the ends of the spring constraints // set new values of the ends of the spring constraints
const stepRange = 600 const stepRange = 600
if (this.seePlayer.recall && Matter.Query.ray(map, this.position, player.position).length === 0) { if (this.seePlayer.recall && Matter.Query.ray(map, this.position, this.seePlayer.position).length === 0) {
if (!(simulation.cycle % (this.seePlayerFreq * 2))) { if (!(simulation.cycle % (this.seePlayerFreq * 2))) {
const unit = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)) const unit = Vector.normalise(Vector.sub(this.seePlayer.position, this.position))
const goal = Vector.add(this.position, Vector.mult(unit, stepRange)) const goal = Vector.add(this.position, Vector.mult(unit, stepRange))
@@ -650,7 +650,7 @@ const mobs = {
} }
}; };
//move to a random location //move to a random location
if (!(simulation.cycle % (this.seePlayerFreq * 5))) { if (!(simulation.cycle % (this.seePlayerFreq * 4))) {
best = { best = {
x: null, x: null,
y: null, y: null,
@@ -797,6 +797,27 @@ const mobs = {
} }
} }
}, },
invulnerability() {
if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown--
//graphics //draw a super shield?
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.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)`
// ctx.fill();
ctx.strokeStyle = "rgba(255,255,255,0.4)";
ctx.stroke();
} else {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
}
},
grow() { grow() {
if (!m.isBodiesAsleep) { if (!m.isBodiesAsleep) {
if (this.seePlayer.recall) { if (this.seePlayer.recall) {

View File

@@ -327,7 +327,6 @@ const m = {
tech.tech[i].name !== "Ψ(t) collapse" && tech.tech[i].name !== "Ψ(t) collapse" &&
tech.tech[i].name !== "non-unitary operator" && tech.tech[i].name !== "non-unitary operator" &&
tech.tech[i].name !== "-quantum leap-" tech.tech[i].name !== "-quantum leap-"
) { ) {
totalTech += tech.tech[i].count totalTech += tech.tech[i].count
tech.tech[i].remove(); tech.tech[i].remove();

View File

@@ -1,6 +1,36 @@
let powerUp = []; let powerUp = [];
const powerUps = { const powerUps = {
ejectGraphic(color = "68, 102, 119") {
simulation.drawList.push({
x: m.pos.x,
y: m.pos.y,
radius: 100,
color: `rgba(${color}, 0.8)`,
time: 4
});
simulation.drawList.push({
x: m.pos.x,
y: m.pos.y,
radius: 75,
color: `rgba(${color}, 0.6)`,
time: 8
});
simulation.drawList.push({
x: m.pos.x,
y: m.pos.y,
radius: 50,
color: `rgba(${color}, 0.3)`,
time: 12
});
simulation.drawList.push({
x: m.pos.x,
y: m.pos.y,
radius: 25,
color: `rgba(${color}, 0.15)`,
time: 16
});
},
orb: { orb: {
research(num = 1) { research(num = 1) {
switch (num) { switch (num) {
@@ -963,8 +993,11 @@ const powerUps = {
tech.tech[choose].isLost = true; tech.tech[choose].isLost = true;
simulation.updateTechHUD(); simulation.updateTechHUD();
m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech
return true
} else {
return false
} }
} else { } else if (tech.tech[choose].count) {
// simulation.makeTextLog(`<div class='circle tech'></div> &nbsp; <strong>${tech.tech[choose].name}</strong> was ejected`, 600) //message about what tech was lost // simulation.makeTextLog(`<div class='circle tech'></div> &nbsp; <strong>${tech.tech[choose].name}</strong> was ejected`, 600) //message about what tech was lost
simulation.makeTextLog(`<span class='color-var'>tech</span>.remove("<span class='color-text'>${tech.tech[choose].name}</span>")`) simulation.makeTextLog(`<span class='color-var'>tech</span>.remove("<span class='color-text'>${tech.tech[choose].name}</span>")`)
@@ -978,6 +1011,9 @@ const powerUps = {
tech.tech[choose].isLost = true; tech.tech[choose].isLost = true;
simulation.updateTechHUD(); simulation.updateTechHUD();
m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech
return true
} else {
return false
} }
}, },
// removeRandomTech() { // removeRandomTech() {

View File

@@ -397,6 +397,7 @@ const simulation = {
} }
} }
if (tech.isCrouchAmmo) tech.isCrouchAmmo = 1 //this prevents hacking the tech by switching guns if (tech.isCrouchAmmo) tech.isCrouchAmmo = 1 //this prevents hacking the tech by switching guns
b.activeGun = b.inventory[b.inventoryGun]; b.activeGun = b.inventory[b.inventoryGun];
if (b.guns[b.activeGun].charge) b.guns[b.activeGun].charge = 0; //if switching into foam set charge to 0 if (b.guns[b.activeGun].charge) b.guns[b.activeGun].charge = 0; //if switching into foam set charge to 0
simulation.updateGunHUD(); simulation.updateGunHUD();

View File

@@ -1,9 +1,12 @@
//main object for spawning things in a level //main object for spawning things in a level
const spawn = { const spawn = {
nonCollideBossList: ["snakeBoss"], //"cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture" nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"],
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool // other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
// "shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",, , "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", , "slashBoss" randomLevelBoss(x, y, options = [
randomLevelBoss(x, y, options = ["snakeBoss", "powerUpBoss", "blockBoss"]) { "shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
"powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
"snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "mantisBoss"
]) {
spawn[options[Math.floor(Math.random() * options.length)]](x, y) spawn[options[Math.floor(Math.random() * options.length)]](x, y)
}, },
pickList: ["starter", "starter"], pickList: ["starter", "starter"],
@@ -1165,6 +1168,64 @@ const spawn = {
// } // }
} }
}, },
powerUpBossBaby(x, y, vertices = 9, radius = 70) {
mobs.spawn(x, y, vertices, radius, "transparent");
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.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map
me.memory = Infinity;
me.seePlayerFreq = 30
me.lockedOn = null;
if (vertices === 9) {
//on primary spawn
powerUps.spawnBossPowerUp(me.position.x, me.position.y)
powerUps.spawn(me.position.x, me.position.y, "heal");
powerUps.spawn(me.position.x, me.position.y, "ammo");
} else if (!m.isCloak) {
me.foundPlayer();
}
me.onHit = function() { //run this function on hitting player
if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255");
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "ammo");
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "research");
}
};
me.onDeath = function() {
this.leaveBody = false;
if (vertices > 3) {
this.isDropPowerUp = false;
spawn.powerUpBossBaby(this.position.x, this.position.y, vertices - 1)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x,
y: this.velocity.y
})
}
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)}%)`
//steal all power ups
for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
powerUp[i].collisionFilter.mask = 0
Matter.Body.setPosition(powerUp[i], this.vertices[i])
Matter.Body.setVelocity(powerUp[i], {
x: 0,
y: 0
})
}
this.seePlayerByHistory();
this.attraction();
this.checkStatus();
};
},
powerUpBoss(x, y, vertices = 9, radius = 130) { powerUpBoss(x, y, vertices = 9, radius = 130) {
mobs.spawn(x, y, vertices, radius, "transparent"); mobs.spawn(x, y, vertices, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -1186,9 +1247,11 @@ const spawn = {
me.foundPlayer(); me.foundPlayer();
} }
me.onHit = function() { //run this function on hitting player me.onHit = function() { //run this function on hitting player
powerUps.ejectTech() if (powerUps.ejectTech()) {
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "ammo"); powerUps.ejectGraphic("150, 138, 255");
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "research"); powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "ammo");
powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "research");
}
}; };
me.onDeath = function() { me.onDeath = function() {
this.leaveBody = false; this.leaveBody = false;
@@ -1222,6 +1285,7 @@ const spawn = {
this.checkStatus(); this.checkStatus();
}; };
}, },
// chaser(x, y, radius = 35 + Math.ceil(Math.random() * 40)) { // chaser(x, y, radius = 35 + Math.ceil(Math.random() * 40)) {
// mobs.spawn(x, y, 8, radius, "rgb(255,150,100)"); //"#2c9790" // mobs.spawn(x, y, 8, radius, "rgb(255,150,100)"); //"#2c9790"
// let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
@@ -1784,6 +1848,277 @@ const spawn = {
spawn.groupShield(targets, x, y, sideLength + 1 * radius + nodes * 5 - 25); spawn.groupShield(targets, x, y, sideLength + 1 * radius + nodes * 5 - 25);
spawn.allowShields = true; spawn.allowShields = true;
}, },
mantisBoss(x, y, radius = 35) {
mobs.spawn(x, y, 5, radius, "#6ba");
let me = mob[mob.length - 1];
me.babyList = [] //list of mobs that are apart of this boss
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //normal is 1, most bosses have 0.25
me.isBoss = true;
me.friction = 0;
me.frictionAir = 0.0067;
me.g = 0.0002; //required if using this.gravity
me.seePlayerFreq = 300;
const springStiffness = 0.0004; //simulation.difficulty
const springDampening = 0.005;
me.springTarget = {
x: me.position.x,
y: me.position.y
};
const len = cons.length;
cons[len] = Constraint.create({
pointA: me.springTarget,
bodyB: me,
stiffness: springStiffness,
damping: springDampening
});
Composite.add(engine.world, cons[cons.length - 1]);
cons[len].length = 100 + 1.5 * radius;
me.cons = cons[len];
me.springTarget2 = { x: me.position.x, y: me.position.y };
const len2 = cons.length;
cons[len2] = Constraint.create({
pointA: me.springTarget2,
bodyB: me,
stiffness: springStiffness,
damping: springDampening,
length: 0
});
Composite.add(engine.world, cons[cons.length - 1]);
cons[len2].length = 100 + 1.5 * radius;
me.cons2 = cons[len2];
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.invulnerabilityCountDown = 0
me.do = function() {
this.checkStatus();
this.gravity();
//draw the two dots on the end of the springs
ctx.beginPath();
ctx.arc(this.cons.pointA.x, this.cons.pointA.y, 6, 0, 2 * Math.PI);
ctx.arc(this.cons2.pointA.x, this.cons2.pointA.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = "#222";
ctx.fill();
this.seePlayerCheck()
// this.seePlayerByHistory()
if (this.isInvulnerable) {
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);
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) {
let vertices = this.babyList[i].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 if (this.invulnerabilityCountDown > 0) {
this.invulnerabilityCountDown--
} else {
this.isInvulnerable = true
this.startingDamageReduction = this.damageReduction
this.damageReduction = 0
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) {
this.babyList[i].isInvulnerable = true
this.babyList[i].damageReduction = 0
}
}
}
// set new values of the ends of the spring constraints
const stepRange = 1200
if (this.seePlayer.recall && Matter.Query.ray(map, this.position, this.seePlayer.position).length === 0) {
if (!(simulation.cycle % (this.seePlayerFreq * 2))) {
const unit = Vector.normalise(Vector.sub(this.seePlayer.position, this.position))
const goal = Vector.add(this.position, Vector.mult(unit, stepRange))
this.springTarget.x = goal.x;
this.springTarget.y = goal.y;
this.cons.length = -200;
this.cons2.length = 100 + 1.5 * this.radius;
this.isInvulnerable = false
this.invulnerabilityCountDown = 40 + Math.max(0, 70 - simulation.difficulty * 2)
this.damageReduction = this.startingDamageReduction
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction
}
} else if (!(simulation.cycle % this.seePlayerFreq)) {
const unit = Vector.normalise(Vector.sub(this.seePlayer.position, this.position))
const goal = Vector.add(this.position, Vector.mult(unit, stepRange))
this.springTarget2.x = goal.x;
this.springTarget2.y = goal.y;
this.cons.length = 100 + 1.5 * this.radius;
this.cons2.length = -200;
this.isInvulnerable = false
this.invulnerabilityCountDown = 40 + Math.max(0, 70 - simulation.difficulty * 2)
this.damageReduction = this.startingDamageReduction
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction
}
}
} else {
this.torque = this.lookTorque * this.inertia;
//spring to random place on map
const vertexCollision = function(v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
const len = vertices.length - 1;
for (let j = 0; j < len; j++) {
results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[j],
v2: vertices[j + 1]
};
}
}
}
results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
if (results.onLine1 && results.onLine2) {
const dx = v1.x - results.x;
const dy = v1.y - results.y;
const dist2 = dx * dx + dy * dy;
if (dist2 < best.dist2) {
best = {
x: results.x,
y: results.y,
dist2: dist2,
who: domain[i],
v1: vertices[0],
v2: vertices[len]
};
}
}
}
};
//move to a random location
if (!(simulation.cycle % (this.seePlayerFreq))) {
best = {
x: null,
y: null,
dist2: Infinity,
who: null,
v1: null,
v2: null
};
const seeRange = 3000;
const look = {
x: this.position.x + seeRange * Math.cos(this.angle),
y: this.position.y + seeRange * Math.sin(this.angle)
};
vertexCollision(this.position, look, map);
if (best.dist2 != Infinity) {
this.springTarget.x = best.x;
this.springTarget.y = best.y;
this.cons.length = 100 + 1.5 * this.radius;
this.cons2.length = 100 + 1.5 * this.radius;
}
}
}
};
me.onDeath = function() {
this.removeCons();
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) {
this.babyList[i].isInvulnerable = false
this.babyList[i].damageReduction = this.startingDamageReduction
this.babyList[i].collisionFilter.mask = cat.bullet | cat.player | cat.map | cat.body
}
}
};
const sideLength = 120 // distance between each node mob
const nodes = 3
const angle = 2 * Math.PI / nodes
spawn.allowShields = false; //don't want shields on individual mobs, it messes with the constraints
for (let i = 0; i < nodes; ++i) {
spawn.striker(x + sideLength * Math.sin(i * angle), y + sideLength * Math.cos(i * angle), 20, 12);
const babyMob = mob[mob.length - 1]
me.babyList.push(babyMob)
babyMob.fill = "rgb(68, 102, 119)"
babyMob.isBoss = true;
// Matter.Body.setDensity(babyMob, 0.001); //extra dense //normal is 0.001 //makes effective life much larger and increases damage
babyMob.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
babyMob.collisionFilter.mask = cat.bullet | cat.player //can't touch other mobs //cat.map | cat.body |
babyMob.delay = 60 + 50 * simulation.CDScale;
babyMob.strikeRange = 600
babyMob.onHit = function() {
this.cd = simulation.cycle + this.delay;
//dislodge ammo
if (b.inventory.length) {
let isRemovedAmmo = false
const numRemoved = 3
for (let j = 0; j < numRemoved; j++) {
for (let i = 0; i < b.inventory.length; i++) {
const gun = b.guns[b.inventory[i]]
if (gun.ammo > 0 && gun.ammo !== Infinity) {
gun.ammo -= Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * gun.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
if (gun.ammo < 0) gun.ammo = 0
isRemovedAmmo = true
}
}
}
if (isRemovedAmmo) {
simulation.updateGunHUD();
for (let j = 0; j < numRemoved; j++) powerUps.directSpawn(this.position.x + 10 * Math.random(), this.position.y + 10 * Math.random(), "ammo");
powerUps.ejectGraphic();
}
}
};
}
const stiffness = 0.01
const damping = 0.1
for (let i = 1; i < nodes; ++i) { //attach to center mob
consBB[consBB.length] = Constraint.create({
bodyA: mob[mob.length - i],
bodyB: mob[mob.length - i - 1],
stiffness: stiffness,
damping: damping
});
Composite.add(engine.world, consBB[consBB.length - 1]);
}
consBB[consBB.length] = Constraint.create({
bodyA: mob[mob.length - 1],
bodyB: mob[mob.length - nodes],
stiffness: stiffness,
damping: damping
});
Composite.add(engine.world, consBB[consBB.length - 1]);
for (let i = 0; i < nodes; ++i) { //attach to center mob
consBB[consBB.length] = Constraint.create({
bodyA: me,
bodyB: mob[mob.length - i - 1],
stiffness: stiffness,
damping: damping
});
Composite.add(engine.world, consBB[consBB.length - 1]);
}
spawn.allowShields = true;
},
// timeSkipBoss(x, y, radius = 55) { // timeSkipBoss(x, y, radius = 55) {
// mobs.spawn(x, y, 6, radius, '#000'); // mobs.spawn(x, y, 6, radius, '#000');
// let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
@@ -2358,12 +2693,13 @@ const spawn = {
me.memory = 240 me.memory = 240
me.seePlayerFreq = 60 me.seePlayerFreq = 60
me.blinkRange = 235 me.blinkRange = 235
if (false && 0.5 < Math.random()) { if (0.5 < Math.random()) {
me.grenadeDelay = 260 me.grenadeDelay = 260
me.blinkRange *= 1.5
} else { } else {
me.grenadeDelay = 100 me.grenadeDelay = 100
} }
me.pulseRadius = 1.4 * Math.min(550, 220 + simulation.difficulty * 4) me.pulseRadius = 1.5 * Math.min(550, 200 + simulation.difficulty * 2)
me.delay = 30 + 35 * simulation.CDScale; me.delay = 30 + 35 * simulation.CDScale;
me.nextBlinkCycle = me.delay; me.nextBlinkCycle = me.delay;
spawn.shield(me, x, y, 1); spawn.shield(me, x, y, 1);
@@ -2919,8 +3255,9 @@ const spawn = {
me.g = 0.00015; //required if using this.gravity me.g = 0.00015; //required if using this.gravity
me.frictionStatic = 0; me.frictionStatic = 0;
me.friction = 0; me.friction = 0;
me.delay = 90 * simulation.CDScale; me.delay = 30 + 60 * simulation.CDScale;
me.cd = Infinity; me.cd = Infinity;
me.strikeRange = 300
Matter.Body.rotate(me, Math.PI * 0.1); Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y); spawn.shield(me, x, y);
me.onDamage = function() { me.onDamage = function() {
@@ -2953,7 +3290,7 @@ const spawn = {
if (distMag < 400) { if (distMag < 400) {
Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), distMag - 20 - radius)); Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), distMag - 20 - radius));
} else { } else {
Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), 300)); Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), this.strikeRange));
} }
ctx.lineTo(this.position.x, this.position.y); ctx.lineTo(this.position.x, this.position.y);
ctx.lineWidth = radius * 2.1; ctx.lineWidth = radius * 2.1;
@@ -2966,7 +3303,7 @@ const spawn = {
} }
}; };
}, },
slashBoss(x, y, radius = 70) { revolutionBoss(x, y, radius = 70) {
const sides = 9 + Math.floor(Math.min(12, 0.2 * simulation.difficulty)) const sides = 9 + Math.floor(Math.min(12, 0.2 * simulation.difficulty))
const coolBends = [-1.8, 0, 0, 0.9, 1.2] const coolBends = [-1.8, 0, 0, 0.9, 1.2]
const bendFactor = coolBends[Math.floor(Math.random() * coolBends.length)]; const bendFactor = coolBends[Math.floor(Math.random() * coolBends.length)];
@@ -2979,7 +3316,7 @@ const spawn = {
me.laserAngle = 0; me.laserAngle = 0;
me.swordDamage = 0.0025 * simulation.dmgScale me.swordDamage = 0.0025 * simulation.dmgScale
spawn.shield(me, x, y, 1); // spawn.shield(me, x, y, 1);
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.11 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.11 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isBoss = true; me.isBoss = true;
@@ -2989,42 +3326,62 @@ const spawn = {
}; };
//invulnerability every 1/4 fraction of life lost
//required setup for invulnerable
// me.isInvulnerable = false
// me.isNextInvulnerability = 0.75
// me.invulnerabilityCountDown = 0
// me.invulnerable = function() {
// if (this.health < this.isNextInvulnerability) {
// this.isNextInvulnerability = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25
// this.isInvulnerable = true
// this.startingDamageReduction = this.damageReduction
// this.damageReduction = 0
// this.invulnerabilityCountDown = 240
// }
// if (this.isInvulnerable) {
// if (this.invulnerabilityCountDown > 0) {
// this.invulnerabilityCountDown--
// //graphics //draw a super shield?
// 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.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)`
// // ctx.fill();
// ctx.strokeStyle = "rgba(255,255,255,0.7)";
// ctx.stroke();
// } else {
// this.isInvulnerable = false
// this.damageReduction = this.startingDamageReduction
// }
// }
// }
me.startingDamageReduction = me.damageReduction //invulnerable every other revolution
me.isInvulnerable = false me.isInvulnerable = false
me.isNextInvulnerability = 0.75
me.invulnerabilityCountDown = 0
me.invulnerable = function() { me.invulnerable = function() {
if (this.health < this.isNextInvulnerability) { if (this.laserAngle % (4 * Math.PI) > 2 * Math.PI) {
this.isNextInvulnerability = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25 if (!this.isInvulnerable) {
this.isInvulnerable = true this.isInvulnerable = true
this.damageReduction = 0 this.startingDamageReduction = this.damageReduction
this.invulnerabilityCountDown = 180 this.damageReduction = 0
}
} else if (this.isInvulnerable) {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
} }
if (this.isInvulnerable) { if (this.isInvulnerable) {
if (this.invulnerabilityCountDown > 0) { ctx.beginPath();
this.invulnerabilityCountDown-- let vertices = this.vertices;
//graphics //draw a super shield? 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.beginPath(); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20;
let vertices = this.vertices; ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.stroke();
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.fillStyle = `rgba(${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},${Math.floor(255 * Math.random())},0.5)`
// ctx.fill();
ctx.strokeStyle = "rgba(255,255,255,0.4)";
ctx.stroke();
} else {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
} }
} }

View File

@@ -1980,9 +1980,7 @@ const tech = {
requires: "", requires: "",
effect() { effect() {
tech.isDroneOnDamage = true; tech.isDroneOnDamage = true;
for (let i = 0; i < 4; i++) { // for (let i = 0; i < 4; i++) b.drone()
b.drone() //spawn drone
}
}, },
remove() { remove() {
tech.isDroneOnDamage = false; tech.isDroneOnDamage = false;
@@ -5028,9 +5026,9 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return tech.haveGunCheck("drones", false) return tech.haveGunCheck("drones", false) && !tech.isDroneRespawn && tech.isBulletsLastLonger === 1
}, },
requires: "drones", requires: "drones, not drone repair, anti-shear topology",
effect() { effect() {
const num = 8 const num = 8
tech.isForeverDrones += num tech.isForeverDrones += num
@@ -5385,9 +5383,9 @@ const tech = {
isBot: true, isBot: true,
isBotTech: true, isBotTech: true,
isNonRefundable: true, isNonRefundable: true,
requires: "foam gun, not bot upgrades NOT EXPERIMENT MODE,", requires: "foam gun, NOT EXPERIMENT MODE, bot upgrades, fractionation, quantum foam",
allowed() { allowed() {
return tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() return tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() && !tech.isAmmoFoamSize && !tech.foamFutureFire
}, },
effect() { effect() {
tech.giveTech("foam-bot upgrade") tech.giveTech("foam-bot upgrade")

View File

@@ -435,7 +435,7 @@ summary {
z-index: 2; z-index: 2;
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: #ecf0f3; background-color: #e8edf0;
opacity: 1; opacity: 1;
transition: opacity 3s; transition: opacity 3s;
pointer-events: none; pointer-events: none;

View File

@@ -1,15 +1,43 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
several tech now have fewer requirements to unlock
some normal tech is now considered gun tech (mostly explosion stuff) mantisBoss: 3 punching mobs, eject your ammo when you get punched
snakeBoss tails, stay attached to each other invulnerable except for 1 second after moving
"snakeBoss", "blockBoss", "powerupBoss" are now the only bosses
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 bug fixes
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
suggestion: quasarBoss: inverted pulsar boss that hits everything except where its aiming 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
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
https://discord.com/channels/645222059647172618/646505973610971165/919116288008290324
quasarBoss: inverted pulsar boss that hits everything except where its aiming
pulsar mobs retarget too easily pulsar mobs retarget too easily
also they drift around too much also they drift around too much
@@ -18,9 +46,6 @@ intro map: diegeticly draw a mouse with field highlighted
also indicate space? also indicate space?
dynamically adjust drawing after picking up a gun dynamically adjust drawing after picking up a gun
some boss mobs need invulnerability phases
maybe trigger immunity to damage for 5-10s after taking the first hit?
increase mass and movement speed at the same time increase mass and movement speed at the same time
increase jump differently because it scales extra with mass increase jump differently because it scales extra with mass