shieldingBoss

shieldingBoss - doesn't attack, but shields all mobs every 2.5s

reworked how tetherBoss's constraint work
  please, let me know if the tether boss is buggy on any of the levels
  the chance for tether boss was removed from level: detours

tech: flip-flop - collisions do 25% more harm, but you become immune to harm for the next collision
This commit is contained in:
landgreen
2021-02-26 05:10:25 -08:00
parent 01b1286764
commit 5c466b4e09
11 changed files with 270 additions and 224 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -2468,7 +2468,7 @@ const b = {
Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0 && Matter.Query.ray(body, this.position, mob[i].position).length === 0 &&
!mob[i].isShielded) { !mob[i].isShielded) {
const SPEED = 45 const SPEED = 40
const unit = Vector.normalise(Vector.sub(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60)), this.position)) const unit = Vector.normalise(Vector.sub(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60)), this.position))
b.nail(this.position, Vector.mult(unit, SPEED), 0.4) b.nail(this.position, Vector.mult(unit, SPEED), 0.4)
this.force = Vector.mult(unit, -0.01 * this.mass) this.force = Vector.mult(unit, -0.01 * this.mass)
@@ -2611,8 +2611,8 @@ const b = {
lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade, lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade,
range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()), range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()),
drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4, drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4,
drain: 0.7 - 0.52 * tech.isLaserBotUpgrade, drain: 0.56 - 0.42 * tech.isLaserBotUpgrade,
laserDamage: 0.38 + 0.29 * tech.isLaserBotUpgrade, laserDamage: 0.5 + 0.35 * tech.isLaserBotUpgrade,
endCycle: Infinity, endCycle: Infinity,
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
@@ -3265,11 +3265,11 @@ const b = {
if (m.crouch) { if (m.crouch) {
spread = 0.75 spread = 0.75
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCD); // cool down
if (tech.isShotgunImmune) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCD); //player is immune to collision damage for 30 cycles if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(58 * b.fireCD)) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCD); //player is immune to collision damage for 30 cycles
knock = 0.01 knock = 0.01
} else { } else {
m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCD); // cool down
if (tech.isShotgunImmune) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCD); //player is immune to collision damage for 30 cycles if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCD)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCD); //player is immune to collision damage for 30 cycles
spread = 1.3 spread = 1.3
knock = 0.1 knock = 0.1
} }
@@ -4514,7 +4514,7 @@ const b = {
m.fireCDcycle = m.cycle + Math.floor(120 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(120 * b.fireCD); // cool down
} else { } else {
m.energy -= DRAIN m.energy -= DRAIN
m.immuneCycle = m.cycle + 30; //player is immune to collision damage for 5 cycles if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to collision damage for 5 cycles
Matter.Body.setPosition(player, history.position); Matter.Body.setPosition(player, history.position);
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y }); Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
if (m.health !== history.health) { if (m.health !== history.health) {

View File

@@ -108,7 +108,20 @@ function collisionChecks(event) {
m.damage(dmg); m.damage(dmg);
return return
} }
m.damage(dmg);
if (tech.isAnthropicHarm) {
if (!tech.isAnthropicHarmImmune) {
tech.isAnthropicHarmImmune = true
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = on`
m.damage(dmg * 1.25); //damage triggers immune to next hit with extra 10% damage
} else {
tech.isAnthropicHarmImmune = false //immune to damage this hit, lose immunity for next hit
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = off`
}
} else {
m.damage(dmg); //normal damage
}
if (tech.isPiezo) m.energy += 20.48; if (tech.isPiezo) m.energy += 20.48;
if (tech.isBayesian) powerUps.ejectTech() if (tech.isBayesian) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);

View File

@@ -12,7 +12,7 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(40) // level.difficultyIncrease(5)
// simulation.zoomScale = 1000; // simulation.zoomScale = 1000;
// simulation.setZoom(); // simulation.setZoom();
// m.setField("nano-scale manufacturing") // m.setField("nano-scale manufacturing")
@@ -792,7 +792,7 @@ const level = {
} else { } else {
if (damage < 0.02) { if (damage < 0.02) {
m.damage(damage) m.damage(damage)
} else if (m.immuneCycle < m.cycle) { } else if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; m.immuneCycle = m.cycle + tech.collisionImmuneCycles;
m.damage(damage) m.damage(damage)
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
@@ -1090,7 +1090,7 @@ const level = {
// spawn.boost(1500, 0, 900); // spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
// spawn.starter(1900, -500) spawn.starter(1900, -500)
// spawn.historyBoss(1900, -500) // spawn.historyBoss(1900, -500)
// spawn.ghoster(2900, -500) // spawn.ghoster(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
@@ -1103,12 +1103,12 @@ const level = {
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
// simulation.difficulty = 30 // simulation.difficulty = 30
spawn.orbitalBoss(1600, -500) spawn.shieldingBoss(1600, -500)
// spawn.beamer(1200, -500) // spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.shield(mob[mob.length - 1], 1800, -120, 1);
// spawn.nodeGroup(1200, -500, "launcher") // spawn.nodeGroup(1200, -500, "launcher")
// spawn.snakeBoss(1200, -500) spawn.snakeBoss(1200, -500)
// spawn.powerUpBoss(2900, -500) // spawn.powerUpBoss(2900, -500)
// spawn.randomMob(1600, -500) // spawn.randomMob(1600, -500)
}, },
@@ -1698,16 +1698,16 @@ const level = {
spawn.randomMob(-75, -1475, 0); spawn.randomMob(-75, -1475, 0);
spawn.randomGroup(600, -2600, 0); spawn.randomGroup(600, -2600, 0);
} }
if (simulation.difficulty < 25) { if (simulation.difficulty < 20) {
spawn.randomMob(700, -1650, 0); spawn.randomMob(700, -1650, 0);
spawn.randomMob(600, -3500, 0.2); spawn.randomMob(600, -3500, 0.2);
spawn.randomMob(-75, -1175, 0.2); spawn.randomMob(-75, -1175, 0.2);
powerUps.spawnBossPowerUp(-125, -1760); powerUps.spawnBossPowerUp(-125, -1760);
} else { } else {
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
spawn.randomLevelBoss(700, -1550, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss"]); spawn.randomLevelBoss(700, -1550, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss"]);
} else { } else {
spawn.randomLevelBoss(675, -2775, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss"]); spawn.randomLevelBoss(675, -2775, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss"]);
} }
} }
powerUps.addRerollToLevel() //needs to run after mobs are spawned powerUps.addRerollToLevel() //needs to run after mobs are spawned
@@ -1854,7 +1854,7 @@ const level = {
spawn.randomMob(3600, 1725, 0.9); spawn.randomMob(3600, 1725, 0.9);
spawn.randomMob(4100, 1225, 0.9); spawn.randomMob(4100, 1225, 0.9);
spawn.randomMob(2825, 400, 0.9); spawn.randomMob(2825, 400, 0.9);
if (simulation.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "historyBoss", "orbitalBoss"]); if (simulation.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "historyBoss", "orbitalBoss", "shieldingBoss"]);
powerUps.addRerollToLevel() //needs to run after mobs are spawned powerUps.addRerollToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275); if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275);
}, },
@@ -2459,17 +2459,7 @@ const level = {
if (simulation.difficulty > 3) { if (simulation.difficulty > 3) {
if (Math.random() < 0.1) { // tether ball if (Math.random() < 0.1) { // tether ball
const index = mob.length const index = mob.length
spawn.tetherBoss(4250, 0) spawn.tetherBoss(4250, 0, { x: 4250, y: -675 })
cons[cons.length] = Constraint.create({
pointA: {
x: 4250,
y: -675
},
bodyB: mob[index],
stiffness: 0.00007
});
World.add(engine.world, cons[cons.length - 1]);
if (simulation.difficulty > 4) spawn.nodeGroup(4250, 0, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss if (simulation.difficulty > 4) spawn.nodeGroup(4250, 0, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss
} else if (Math.random() < 0.2) { } else if (Math.random() < 0.2) {
spawn.randomLevelBoss(4250, -250); spawn.randomLevelBoss(4250, -250);
@@ -3214,16 +3204,7 @@ const level = {
height: 525, height: 525,
color: "#ccc" color: "#ccc"
}); });
spawn.tetherBoss(2850, -80) spawn.tetherBoss(2850, -80, { x: 2500, y: -500 })
cons[cons.length] = Constraint.create({
pointA: {
x: 2500,
y: -500
},
bodyB: mob[mob.length - 1],
stiffness: 0.00012
});
World.add(engine.world, cons[cons.length - 1]);
//chance to spawn a ring of exploding mobs around this boss //chance to spawn a ring of exploding mobs around this boss
if (simulation.difficulty > 6) spawn.nodeGroup(2850, -80, "spawns", 8, 20, 105); if (simulation.difficulty > 6) spawn.nodeGroup(2850, -80, "spawns", 8, 20, 105);
} else { } else {
@@ -3690,16 +3671,7 @@ const level = {
if (simulation.difficulty > 2) { if (simulation.difficulty > 2) {
if (Math.random() < 0.2) { if (Math.random() < 0.2) {
// tether ball // tether ball
spawn.tetherBoss(7000, -3300) spawn.tetherBoss(7000, -3300, { x: 7300, y: -3300 })
cons[cons.length] = Constraint.create({
pointA: {
x: 7300,
y: -3300
},
bodyB: mob[mob.length - 1],
stiffness: 0.00006
});
World.add(engine.world, cons[cons.length - 1]);
if (simulation.difficulty > 4) spawn.nodeGroup(7000, -3300, "spawns", 8, 20, 105); if (simulation.difficulty > 4) spawn.nodeGroup(7000, -3300, "spawns", 8, 20, 105);
} else if (simulation.difficulty > 3) { } else if (simulation.difficulty > 3) {
spawn.randomLevelBoss(6100, -3600, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss"]); spawn.randomLevelBoss(6100, -3600, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss"]);
@@ -3709,16 +3681,7 @@ const level = {
if (simulation.difficulty > 2) { if (simulation.difficulty > 2) {
if (Math.random() < 0.2) { if (Math.random() < 0.2) {
// tether ball // tether ball
spawn.tetherBoss(2300, -1300) spawn.tetherBoss(2300, -1300, { x: 2300, y: -1750 })
cons[cons.length] = Constraint.create({
pointA: {
x: 2300,
y: -1750
},
bodyB: mob[mob.length - 1],
stiffness: 0.00036
});
World.add(engine.world, cons[cons.length - 1]);
if (simulation.difficulty > 4) spawn.nodeGroup(2350, -1300, "spawns", 8, 20, 105); if (simulation.difficulty > 4) spawn.nodeGroup(2350, -1300, "spawns", 8, 20, 105);
} else if (simulation.difficulty > 3) { } else if (simulation.difficulty > 3) {
spawn.randomLevelBoss(2300, -1400, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "snakeBoss"]); spawn.randomLevelBoss(2300, -1400, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "snakeBoss"]);
@@ -3785,16 +3748,7 @@ const level = {
spawn.mapRect(3075, 1075, 375, 150); //Plafond salle trésor spawn.mapRect(3075, 1075, 375, 150); //Plafond salle trésor
spawn.mapRect(3300, 1075, 1500, 1800); //Mur droite salle trésor spawn.mapRect(3300, 1075, 1500, 1800); //Mur droite salle trésor
// tether ball // tether ball
spawn.tetherBoss(2330, 1850) spawn.tetherBoss(2330, 1850, { x: 2330, y: 1425 })
cons[cons.length] = Constraint.create({
pointA: {
x: 2330,
y: 1425
},
bodyB: mob[mob.length - 1],
stiffness: 0.00017
});
World.add(engine.world, cons[cons.length - 1]);
//chance to spawn a ring of exploding mobs around this boss //chance to spawn a ring of exploding mobs around this boss
if (simulation.difficulty > 4) spawn.nodeGroup(2330, 1850, "spawns", 8, 20, 105); if (simulation.difficulty > 4) spawn.nodeGroup(2330, 1850, "spawns", 8, 20, 105);
powerUps.chooseRandomPowerUp(3100, 1630); powerUps.chooseRandomPowerUp(3100, 1630);
@@ -4062,26 +4016,17 @@ const level = {
spawn.randomGroup(8025, -845, 0.2); spawn.randomGroup(8025, -845, 0.2);
if (simulation.difficulty > 2) { if (simulation.difficulty > 2) {
if (Math.random() < 0.2) { // if (Math.random() < 0.2) {
// tether ball // // tether ball
spawn.tetherBoss(8000, 630) // spawn.tetherBoss(8000, 630, { x: 8550, y: 680 })
let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
me.onDeath = function() { // me.onDeath = function() {
this.removeCons(); //remove constraint // this.removeCons(); //remove constraint
spawnCouloirEnHaut() // spawnCouloirEnHaut()
doorSortieSalle.isOpen = false; // doorSortieSalle.isOpen = false;
}; // };
cons[cons.length] = Constraint.create({ // if (simulation.difficulty > 4) spawn.nodeGroup(8000, 630, "spawns", 8, 20, 105);
pointA: { // } else {
x: 8550,
y: 680
},
bodyB: mob[mob.length - 1],
stiffness: 0.00015
});
World.add(engine.world, cons[cons.length - 1]);
if (simulation.difficulty > 4) spawn.nodeGroup(8000, 630, "spawns", 8, 20, 105);
} else {
spawn.randomLevelBoss(8000, 630, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "bomberBoss", "orbitalBoss"]); spawn.randomLevelBoss(8000, 630, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "bomberBoss", "orbitalBoss"]);
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.onDeath = function() { me.onDeath = function() {
@@ -4089,7 +4034,7 @@ const level = {
spawnCouloirEnHaut() spawnCouloirEnHaut()
doorSortieSalle.isOpen = false; doorSortieSalle.isOpen = false;
}; };
} // }
} else { } else {
spawn.randomLevelBoss(8000, 630, ["shooterBoss"]); spawn.randomLevelBoss(8000, 630, ["shooterBoss"]);
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -4658,18 +4603,8 @@ const level = {
if (simulation.difficulty > 3) { if (simulation.difficulty > 3) {
if (Math.random() < 0.16) { if (Math.random() < 0.16) {
spawn.tetherBoss(3380, -1775) spawn.tetherBoss(3380, -1775, { x: 3775, y: -1775 })
cons[cons.length] = Constraint.create({
pointA: {
x: 3775,
y: -1775
},
bodyB: mob[mob.length - 1],
stiffness: 0.00018 + 0.000007 * level.levelsCleared
});
World.add(engine.world, cons[cons.length - 1]);
if (simulation.difficulty > 4) spawn.nodeGroup(3380, -1775, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss if (simulation.difficulty > 4) spawn.nodeGroup(3380, -1775, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss
} else { } else {
spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "snakeBoss", "laserBoss"]); spawn.randomLevelBoss(3100, -1850, ["shooterBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "snakeBoss", "laserBoss"]);
} }

View File

@@ -651,6 +651,7 @@ const mobs = {
//cause all mobs, and bodies to rotate in a circle //cause all mobs, and bodies to rotate in a circle
applyCurl = function(center, array, isAntiGravity = true) { applyCurl = function(center, array, isAntiGravity = true) {
for (let i = 0; i < array.length; ++i) { for (let i = 0; i < array.length; ++i) {
if (!array[i].isNotHoldable) {
const sub = Vector.sub(center, array[i].position) const sub = Vector.sub(center, array[i].position)
const radius2 = Vector.magnitudeSquared(sub); const radius2 = Vector.magnitudeSquared(sub);
@@ -673,6 +674,7 @@ const mobs = {
} }
} }
} }
}
applyCurl(this.position, mob, false); applyCurl(this.position, mob, false);
applyCurl(this.position, body); applyCurl(this.position, body);
applyCurl(this.position, powerUp); applyCurl(this.position, powerUp);
@@ -1050,7 +1052,7 @@ const mobs = {
bullet[bullet.length - 1].endCycle = simulation.cycle + 1000 + Math.floor(400 * Math.random()) bullet[bullet.length - 1].endCycle = simulation.cycle + 1000 + Math.floor(400 * Math.random())
this.leaveBody = false; // no body since it turned into the bot this.leaveBody = false; // no body since it turned into the bot
} }
} else if (tech.isShieldAmmo && this.shield) { } else if (tech.isShieldAmmo && this.shield && !this.isBonusShield) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo" let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
type = "heal" type = "heal"

View File

@@ -570,7 +570,7 @@ const m = {
} }
} }
m.energy = Math.max(m.energy - steps / 136, 0.01) m.energy = Math.max(m.energy - steps / 136, 0.01)
m.immuneCycle = m.cycle + 30; //player is immune to collision damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
let isDrawPlayer = true let isDrawPlayer = true
const shortPause = function() { const shortPause = function() {
@@ -642,7 +642,7 @@ const m = {
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`)
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x, m.pos.y, "heal", false); for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x, m.pos.y, "heal", false);
m.energy = m.maxEnergy m.energy = m.maxEnergy
m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds if (m.immuneCycle < m.cycle + 360) m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds
simulation.wipe = function() { //set wipe to have trails simulation.wipe = function() { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)"; ctx.fillStyle = "rgba(255,255,255,0.03)";
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -671,7 +671,7 @@ const m = {
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span> simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span>
<br>${powerUps.research.count}`) <br>${powerUps.research.count}`)
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "heal", false); for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "heal", false);
m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds if (m.immuneCycle < m.cycle + 360) m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds
simulation.wipe = function() { //set wipe to have trails simulation.wipe = function() { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)"; ctx.fillStyle = "rgba(255,255,255,0.03)";
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
@@ -1777,7 +1777,7 @@ const m = {
simulation.cycle--; //pause all functions that depend on game cycle increasing simulation.cycle--; //pause all functions that depend on game cycle increasing
if (tech.isTimeSkip) { if (tech.isTimeSkip) {
m.immuneCycle = m.cycle + 10; if (m.immuneCycle < m.cycle + 10) m.immuneCycle = m.cycle + 10;
simulation.isTimeSkipping = true; simulation.isTimeSkipping = true;
m.cycle++; m.cycle++;
simulation.gravity(); simulation.gravity();
@@ -2537,7 +2537,7 @@ const m = {
x: velocity.x, x: velocity.x,
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
}); });
m.immuneCycle = m.cycle + 15; //player is immune to collision damage if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage
// move bots to player // move bots to player
for (let i = 0; i < bullet.length; i++) { for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) { if (bullet[i].botType) {
@@ -2813,7 +2813,7 @@ const m = {
if (tech.isPiezo) m.energy += 20.48; if (tech.isPiezo) m.energy += 20.48;
if (tech.isBayesian) powerUps.ejectTech() if (tech.isBayesian) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
//extra kick between player and mob //this section would be better with forces but they don't work... //extra kick between player and mob //this section would be better with forces but they don't work...
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {

View File

@@ -70,7 +70,7 @@ const powerUps = {
document.body.style.overflow = "hidden" document.body.style.overflow = "hidden"
simulation.paused = false; simulation.paused = false;
simulation.isChoosing = false; //stops p from un pausing on key down simulation.isChoosing = false; //stops p from un pausing on key down
m.immuneCycle = m.cycle + 60; //player is immune to collision damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
build.unPauseGrid() build.unPauseGrid()
requestAnimationFrame(cycle); requestAnimationFrame(cycle);
}, },

View File

@@ -1002,7 +1002,7 @@ const simulation = {
//ctx.fillText(bodies[i].id,bodies[i].position.x,bodies[i].position.y); //shows the id of every body //ctx.fillText(bodies[i].id,bodies[i].position.x,bodies[i].position.y); //shows the id of every body
let vertices = bodies[i].vertices; let vertices = bodies[i].vertices;
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j += 1) { for (let j = 1; j < vertices.length; j++) {
ctx.lineTo(vertices[j].x, vertices[j].y); ctx.lineTo(vertices[j].x, vertices[j].y);
} }
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);

View File

@@ -82,8 +82,8 @@ const spawn = {
} }
} }
}, },
//, "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss" //
randomLevelBoss(x, y, options = ["orbitalBoss"]) { randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss"]) {
// 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
spawn[options[Math.floor(Math.random() * options.length)]](x, y) spawn[options[Math.floor(Math.random() * options.length)]](x, y)
}, },
@@ -437,7 +437,7 @@ const spawn = {
vertexCollision(where, look, body); vertexCollision(where, look, body);
if (!m.isCloak) vertexCollision(where, look, [player]); if (!m.isCloak) vertexCollision(where, look, [player]);
if (best.who && best.who === player && m.immuneCycle < m.cycle) { if (best.who && best.who === player && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + 60 + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles if (m.immuneCycle < m.cycle + 60 + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + 60 + tech.collisionImmuneCycles; //player is immune to collision damage extra time
m.damage(dmg); m.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: best.x, x: best.x,
@@ -1623,7 +1623,7 @@ const spawn = {
vertexCollision(where, look, body); vertexCollision(where, look, body);
if (!m.isCloak) vertexCollision(where, look, [player]); if (!m.isCloak) vertexCollision(where, look, [player]);
if (best.who && best.who === player && m.immuneCycle < m.cycle) { if (best.who && best.who === player && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles m.immuneCycle = m.cycle + tech.collisionImmuneCycles + 60; //player is immune to collision damage for an extra second
const dmg = 0.14 * simulation.dmgScale; const dmg = 0.14 * simulation.dmgScale;
m.damage(dmg); m.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
@@ -1776,9 +1776,8 @@ const spawn = {
}; };
}, },
sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 20)) { sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 20)) {
let me;
mobs.spawn(x, y, 5, radius, "transparent"); mobs.spawn(x, y, 5, radius, "transparent");
me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.accelMag = 0.001 * simulation.accelScale; me.accelMag = 0.001 * simulation.accelScale;
me.frictionAir = 0.01; me.frictionAir = 0.01;
@@ -1828,9 +1827,8 @@ const spawn = {
}; };
}, },
ghoster(x, y, radius = 40 + Math.ceil(Math.random() * 100)) { ghoster(x, y, radius = 40 + Math.ceil(Math.random() * 100)) {
let me;
mobs.spawn(x, y, 7, radius, "transparent"); mobs.spawn(x, y, 7, radius, "transparent");
me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.seeAtDistance2 = 300000; me.seeAtDistance2 = 300000;
me.accelMag = 0.00012 * simulation.accelScale; me.accelMag = 0.00012 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
@@ -2321,6 +2319,62 @@ const spawn = {
} }
}; };
}, },
shieldingBoss(x, y, radius = 210) {
mobs.spawn(x, y, 9, radius, "rgb(150, 150, 255)");
let me = mob[mob.length - 1];
Matter.Body.rotate(me, Math.random() * 2 * Math.PI)
// me.stroke = "rgb(220,220,255)"
me.isBoss = true;
me.cycle = 0
me.maxCycles = 120;
me.frictionStatic = 0;
me.friction = 0;
me.frictionAir = 0.5;
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
me.onDamage = function() {};
me.do = function() {
this.checkStatus();
//draw cycle timer
ctx.beginPath();
ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y)
const phase = (this.vertices.length + 1) * this.cycle / this.maxCycles
if (phase > 1) ctx.lineTo(this.vertices[0].x, this.vertices[0].y)
for (let i = 1; i < phase - 1; i++) {
ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
}
ctx.lineWidth = 5
ctx.strokeStyle = "rgb(255,255,255)"
ctx.stroke();
if (!m.isBodiesAsleep) {
this.cycle++
if (this.cycle > this.maxCycles) {
this.cycle = 0
ctx.beginPath();
for (let i = 0; i < mob.length; i++) {
if (!mob[i].isShielded && !mob[i].shield && mob[i].dropPowerUp) {
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);
}
}
ctx.lineWidth = 20
// ctx.lineCap = "round";
ctx.strokeStyle = "rgba(200,200,255,0.9)"
ctx.stroke();
}
}
};
},
streamBoss(x, y, radius = 110) { streamBoss(x, y, radius = 110) {
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)"); mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -2492,7 +2546,6 @@ const spawn = {
me.memory = 250; me.memory = 250;
me.laserRange = 500; me.laserRange = 500;
Matter.Body.setDensity(me, 0.0015 + 0.0005 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0015 + 0.0005 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
me.onDeath = function() { me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < mob.length; i++) { //wake up tail mobs for (let i = 0; i < mob.length; i++) { //wake up tail mobs
@@ -2532,9 +2585,10 @@ const spawn = {
stiffness: 0.05 stiffness: 0.05
}); });
World.add(engine.world, consBB[consBB.length - 1]); World.add(engine.world, consBB[consBB.length - 1]);
spawn.shield(me, x, y, 1);
}, },
snakeBody(x, y, radius = 14) { snakeBody(x, y, radius = 14) {
mobs.spawn(x, y, 8, radius, "transparent"); mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
// me.onHit = function() { // me.onHit = function() {
// //run this function on hitting player // //run this function on hitting player
@@ -2545,7 +2599,7 @@ const spawn = {
me.leaveBody = false; me.leaveBody = false;
me.frictionAir = 0.02; me.frictionAir = 0.02;
me.isSnakeTail = true; me.isSnakeTail = true;
me.stroke = "#099" me.stroke = "transparent"
me.onDeath = function() { me.onDeath = function() {
if (this.isSnakeTail) { //wake up tail mobs if (this.isSnakeTail) { //wake up tail mobs
@@ -2567,7 +2621,7 @@ const spawn = {
this.attraction(); this.attraction();
}; };
}, },
tetherBoss(x, y, radius = 90) { tetherBoss(x, y, constraint, radius = 90) {
// constrained mob boss for the towers level // constrained mob boss for the towers level
// often has a ring of mobs around it // often has a ring of mobs around it
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)"); mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
@@ -2577,8 +2631,18 @@ const spawn = {
me.accelMag = 0.002 * simulation.accelScale; me.accelMag = 0.002 * simulation.accelScale;
me.memory = 20; me.memory = 20;
Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y, 1);
cons[cons.length] = Constraint.create({
pointA: {
x: constraint.x,
y: constraint.y
},
bodyB: me,
stiffness: 0.00012
});
World.add(engine.world, cons[cons.length - 1]);
spawn.shield(me, x, y, 1);
setTimeout(() => { spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) }, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital setTimeout(() => { spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) }, 100); //have to wait a sec so the tether constraint doesn't attach to an orbital
me.onDeath = function() { me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -2591,13 +2655,14 @@ const spawn = {
this.attraction(); this.attraction();
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2)) { shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2), isBonusShield = false) {
if (this.allowShields && Math.random() < chance) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "rgb(220,220,255)"; me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.isBonusShield = isBonusShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
@@ -2625,12 +2690,16 @@ const spawn = {
if (mob[i].id === this.shieldTargetID) mob[i].isShielded = false; if (mob[i].id === this.shieldTargetID) mob[i].isShielded = false;
} }
}; };
//swap order of shield and mob, so that mob is behind shield graphically
mob[mob.length - 1] = mob[mob.length - 2];
mob[mob.length - 2] = me;
me.do = function() { me.do = function() {
this.checkStatus(); this.checkStatus();
}; };
//move shield to the front of the array, so that mob is behind shield graphically
mob.unshift(me);
//swap order of shield and mob, so that mob is behind shield graphically
// mob[mob.length - 1] = mob[mob.length - 2];
// mob[mob.length - 2] = me;
} }
}, },
groupShield(targets, x, y, radius, stiffness = 0.4) { groupShield(targets, x, y, radius, stiffness = 0.4) {

View File

@@ -95,13 +95,12 @@
haveGunCheck(name) { haveGunCheck(name) {
if ( if (
!build.isExperimentSelection && !build.isExperimentSelection &&
b.inventory.length > 2 && b.inventory > 2 &&
name !== b.guns[b.activeGun].name && name !== b.guns[b.activeGun].name &&
Math.random() > 2 / (b.inventory.length + tech.isGunCycle * 3) //lower chance of tech specific to a gun if you have lots of guns Math.random() > 2 - b.inventory.length * 0.5
) { ) {
return false return false
} }
for (i = 0, len = b.inventory.length; i < len; i++) { for (i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].name === name) return true if (b.guns[b.inventory[i]].name === name) return true
} }
@@ -1164,10 +1163,10 @@
requires: "", requires: "",
effect() { effect() {
tech.collisionImmuneCycles += 45; tech.collisionImmuneCycles += 45;
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
}, },
remove() { remove() {
tech.collisionImmuneCycles = 25; tech.collisionImmuneCycles = 30;
} }
}, },
{ {
@@ -1186,6 +1185,84 @@
tech.cyclicImmunity = 0; tech.cyclicImmunity = 0;
} }
}, },
{
name: "flip-flop",
description: "after a <strong>collision</strong> take <strong>25%</strong> more <strong class='color-harm'>harm</strong><br>but, on your next <strong>collision</strong> take <strong>0</strong> <strong class='color-harm'>harm</strong>",
nameInfo: "<span id = 'tech-flip-flop'></span>",
addNameInfo() {
setTimeout(function() {
if (document.getElementById("tech-flip-flop")) {
if (tech.isAnthropicHarmImmune) {
document.getElementById("tech-flip-flop").innerHTML = ` = on`
} else {
document.getElementById("tech-flip-flop").innerHTML = ` = off`
}
}
}, 100);
},
maxCount: 1,
count: 0,
allowed() {
return true
},
requires: "",
effect() {
tech.isAnthropicHarm = true //do you have this tech
tech.isAnthropicHarmImmune = false //are you immune to next collision
},
remove() {
tech.isAnthropicHarm = false
tech.isAnthropicHarmImmune = false
}
},
{
name: "clock gating",
description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>20%</strong>`,
maxCount: 1,
count: 0,
allowed() {
return simulation.fpsCapDefault > 45 && !tech.isRailTimeSlow
},
requires: "FPS above 45",
effect() {
tech.isSlowFPS = true;
},
remove() {
tech.isSlowFPS = false;
}
},
{
name: "liquid cooling",
description: `<strong class='color-s'>freeze</strong> all mobs for <strong>7</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong>`,
maxCount: 1,
count: 0,
allowed() {
return tech.isSlowFPS
},
requires: "clock gating",
effect() {
tech.isHarmFreeze = true;
},
remove() {
tech.isHarmFreeze = false;
}
},
{
name: "osmoprotectant",
description: `collisions with <strong>stunned</strong> or <strong class='color-s'>frozen</strong> mobs<br>cause you <strong>no</strong> <strong class='color-harm'>harm</strong>`,
maxCount: 1,
count: 0,
allowed() {
return tech.isStunField || tech.isPulseStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage
},
requires: "a freezing or stunning effect",
effect() {
tech.isFreezeHarmImmune = true;
},
remove() {
tech.isFreezeHarmImmune = false;
}
},
{ {
name: "ablative drones", name: "ablative drones",
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>", description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>",
@@ -1237,54 +1314,6 @@
tech.isHarmDamage = false; tech.isHarmDamage = false;
} }
}, },
{
name: "liquid cooling",
description: `<strong class='color-s'>freeze</strong> all mobs for <strong>7</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong>`,
maxCount: 1,
count: 0,
allowed() {
return tech.isSlowFPS
},
requires: "clock gating",
effect() {
tech.isHarmFreeze = true;
},
remove() {
tech.isHarmFreeze = false;
}
},
{
name: "osmoprotectant",
description: `collisions with <strong>stunned</strong> or <strong class='color-s'>frozen</strong> mobs<br>cause you <strong>no</strong> <strong class='color-harm'>harm</strong>`,
maxCount: 1,
count: 0,
allowed() {
return tech.isStunField || tech.isPulseStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage
},
requires: "a freezing or stunning effect",
effect() {
tech.isFreezeHarmImmune = true;
},
remove() {
tech.isFreezeHarmImmune = false;
}
},
{
name: "clock gating",
description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>20%</strong>`,
maxCount: 1,
count: 0,
allowed() {
return simulation.fpsCapDefault > 45 && !tech.isRailTimeSlow
},
requires: "FPS above 45",
effect() {
tech.isSlowFPS = true;
},
remove() {
tech.isSlowFPS = false;
}
},
{ {
name: "CPT reversal", name: "CPT reversal",
description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-harm'>harm</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>", description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-harm'>harm</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>",
@@ -1339,7 +1368,7 @@
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return !tech.isEnergyHealth && m.harmReduction() < 1 return !tech.isEnergyHealth && (m.harmReduction() < 1 || tech.isAnthropicHarm)
}, },
requires: "not mass-energy equivalence, some harm reduction", requires: "not mass-energy equivalence, some harm reduction",
effect() { effect() {
@@ -1860,7 +1889,7 @@
}, },
{ {
name: "decoherence", name: "decoherence",
description: "enter an <strong>alternate reality</strong> after you <strong class='color-r'>research</strong><br>spawn <strong>9</strong> <strong class='color-r'>research</strong>", description: "enter an <strong>alternate reality</strong> after you <strong class='color-r'>research</strong><br>spawn <strong>11</strong> <strong class='color-r'>research</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1869,7 +1898,7 @@
requires: "not quantum immortality, many-worlds", requires: "not quantum immortality, many-worlds",
effect() { effect() {
tech.isResearchReality = true; tech.isResearchReality = true;
for (let i = 0; i < 9; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false); for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + Math.random() * 10, m.pos.y + Math.random() * 10, "research", false);
}, },
remove() { remove() {
tech.isResearchReality = false; tech.isResearchReality = false;
@@ -2011,7 +2040,7 @@
}, },
{ {
name: "bubble fusion", name: "bubble fusion",
description: "after destroying a mob's <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>research</strong>", description: "after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>research</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -4307,7 +4336,7 @@
}, },
{ {
name: "ship", name: "ship",
description: "<strong>experimental mode:</strong> fly around with no legs<br>aim by rotating with keyboard", description: "<strong>experiment:</strong> fly around with no legs<br>aim by rotating with keyboard",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4324,7 +4353,7 @@
}, },
{ {
name: "quantum leap", name: "quantum leap",
description: "<strong>experimental mode:</strong> every 20 seconds<br>become an alternate version of yourself", description: "<strong>experiment:</strong> every 20 seconds<br>become an alternate version of yourself",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -5373,5 +5402,7 @@
isHarmReduceAfterKill: null, isHarmReduceAfterKill: null,
isSwitchReality: null, isSwitchReality: null,
isResearchReality: null, isResearchReality: null,
isAnthropicDamage: null isAnthropicDamage: null,
isAnthropicHarm: null,
isAnthropicHarmImmune: null
} }

View File

@@ -1,14 +1,19 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
mob orbitals can now be destroyed, but it takes a very large amount of damage shieldingBoss - doesn't attack, but shields all mobs every 2.5s
laser-bot upgrade: gives 75% damage, range, and energy efficiency (was 400% damage, but they ran out of energy too fast) reworked how tetherBoss's constraint work
boom-bots are now smart about not hurting the player with explosions while doing the most damage please, let me know if the tether boss is buggy on any of the levels
the chance for tether boss was removed from level: detours
tech: flip-flop - collisions do 25% more harm, but you become immune to harm for the next collision
tech: strong anthropic principle - after anthropic principle prevents your death do 137.03599 extra damage for the rest of the level
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
shields being put in front of mob array messes up some types of index = mob.length-1 uses
adding orbitals puts a random # of mobs in front of target, and shield behind
use the floor of portal sensor on the player? to unstuck player use the floor of portal sensor on the player? to unstuck player
(only once on my computer) once every 7 second check isn't running code (only once on my computer) once every 7 second check isn't running code
@@ -35,9 +40,6 @@ use the floor of portal sensor on the player? to unstuck player
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
tech: after using anthropic principle do 200% more damage for the rest of the level
use ship tech to make a mob mode use ship tech to make a mob mode
differences from ship to mob differences from ship to mob
graphics graphics
@@ -58,12 +60,6 @@ bosses should have 2x health, but only do about 50 health damage
tech: spawn a bot after taking collision damage tech: spawn a bot after taking collision damage
tech: standing wave freezes the mobs it hits
tech: health becomes drones
requires mass-energy?
junk tech?
map: laboratory map: laboratory
rooms with switches that change physics rooms with switches that change physics
gravity room gravity room
@@ -373,7 +369,7 @@ possible names for tech
perturbation theory perturbation theory
holonomy - parallel transport of a vector leads to movement (applies to curved space) holonomy - parallel transport of a vector leads to movement (applies to curved space)
hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other. hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other.
uncertainty principle
chapter 1: bot can hear audio and learns testing mode chapter 1: bot can hear audio and learns testing mode
bot uses testing mode to exit room bot uses testing mode to exit room